Skip to content

Commit

Permalink
Merge pull request #16 from Nich87/dev
Browse files Browse the repository at this point in the history
おめでとうございます?あなたは今頃それ修正したの!?ってPRを受け取りました。
  • Loading branch information
MotiCAT authored Nov 28, 2024
2 parents 167eee9 + 77d1868 commit 74c127f
Show file tree
Hide file tree
Showing 30 changed files with 194 additions and 123 deletions.
3 changes: 0 additions & 3 deletions .eslintignore

This file was deleted.

39 changes: 39 additions & 0 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { FlatCompat } from '@eslint/eslintrc';
import js from '@eslint/js';
import typescriptEslint from '@typescript-eslint/eslint-plugin';
import tsParser from '@typescript-eslint/parser';
import globals from 'globals';
import path from 'node:path';
import { fileURLToPath } from 'node:url';

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const compat = new FlatCompat({
baseDirectory: __dirname,
recommendedConfig: js.configs.recommended,
allConfig: js.configs.all
});

export default [
{
ignores: ['**/build/', '**/node_modules/', '**/.env']
},
...compat.extends('eslint:recommended', 'plugin:@typescript-eslint/recommended', 'prettier'),
{
plugins: {
'@typescript-eslint': typescriptEslint
},

languageOptions: {
globals: {
...globals.node
},

parser: tsParser,
ecmaVersion: 'latest',
sourceType: 'module'
},

rules: {}
}
];
21 changes: 11 additions & 10 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,26 +23,27 @@
},
"license": "MIT",
"devDependencies": {
"@eslint/eslintrc": "^3.2.0",
"@eslint/js": "^9.15.0",
"@trivago/prettier-plugin-sort-imports": "^4.3.0",
"@typescript-eslint/eslint-plugin": "^6.21.0",
"@typescript-eslint/parser": "^6.21.0",
"eslint": "^8.57.1",
"@typescript-eslint/eslint-plugin": "^8.16.0",
"@typescript-eslint/parser": "^8.16.0",
"eslint": "^9.15.0",
"eslint-config-prettier": "^9.1.0",
"prettier": "^3.3.3",
"globals": "^15.12.0",
"prettier": "^3.4.1",
"ts-node": "^10.9.2",
"typescript": "^5.6.3"
"typescript": "^5.7.2"
},
"dependencies": {
"@discordjs/opus": "^0.9.0",
"@discordjs/voice": "^0.16.1",
"@discordjs/voice": "^0.18.0",
"@distube/ytdl-core": "^4.15.1",
"@distube/ytpl": "^1.2.1",
"discord.js": "^14.16.3",
"dotenv": "^16.4.5",
"ffmpeg-static": "^5.2.0",
"node-cache": "^5.1.2",
"tweetnacl": "^1.0.3",
"youtube-sr": "^4.3.11",
"ytpl": "^2.3.0"
"youtube-sr": "^4.3.11"
},
"repository": {
"type": "git",
Expand Down
4 changes: 0 additions & 4 deletions src/Events/onInteractionCreate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,6 @@ export async function onInteractionCreate(interaction: BaseInteraction): Promise
return;
}
if (channel.type !== ChannelType.GuildVoice) return;
if (!channel.joinable) {
interaction.reply(embeds.voiceChannnelJoined);
return;
}
if (!channel.speakable) {
interaction.reply(embeds.voiceChannnelPermission);
return;
Expand Down
4 changes: 0 additions & 4 deletions src/Events/onMessageCreate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,6 @@ export async function onMessageCreate(message: Message): Promise<Awaitable<void>
return;
}
if (channel.type !== ChannelType.GuildVoice) return;
if (!channel.joinable) {
message.reply(embeds.voiceChannnelJoined);
return;
}
if (!channel.speakable) {
message.reply(embeds.voiceChannnelPermission);
return;
Expand Down
10 changes: 7 additions & 3 deletions src/Events/onReady.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
import { Client, version } from 'discord.js';
import { extendedClient } from '../Utils/extendedClient';
import { version as voiceVersion } from '@discordjs/voice';
import { version as djsVersion } from 'discord.js';

export function onReady(client: Client) {
export function onReady(client: extendedClient): void {
console.log(`Logged in as ${client.user?.tag}`);
client.user?.setActivity('CatHouse Products');
console.table({
'Bot User': client.user?.tag,
'Guild(s)': client.guilds.cache.size + ' Servers',
Watching: client.guilds.cache.reduce((a, b) => a + b.memberCount, 0) + ' Members',
'Discord.js': version,
'Discord.js': djsVersion,
'@discordjs/voice': voiceVersion,
Proxy: client.useProxy ? client.getURI() : 'No Proxy',
'Node.js': process.version,
Plattform: process.platform + ' | ' + process.arch,
Memory:
Expand Down
14 changes: 4 additions & 10 deletions src/Events/onVoiceStateUpdate.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,11 @@
import { Queue, queueManager } from '../classes/queue';
import { client } from '../index';
import { VoiceState } from 'discord.js';

export async function onVoiceStateUpdate(oldState: VoiceState, newState: VoiceState) {
const botId = oldState.client.user?.id;
const channel = oldState.channel;
if (!botId) return;

if (channel && channel.members.size === 1 && channel.members.has(botId)) {
newState.guild.members.me?.voice.disconnect();
client.player = undefined;
queueManager.deleteQueue(newState.guild.id);
}
const oldchannel = oldState.channel;
const newchannel = newState.channel;

console.log(`[INFO] Old Channel: ${oldchannel?.name} | New Channel: ${newchannel?.name}
`);
if (!queueManager.getQueue(newState.guild.id)) queueManager.setQueue(newState.guild.id, new Queue());
}
36 changes: 33 additions & 3 deletions src/Utils/extendedClient.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,40 @@
import { YTPlayer } from '../classes/player';
import { ClientOptions, Client } from 'discord.js';

interface ProxyOptions {
host: string;
port: number;
}

export class extendedClient extends Client {
player: YTPlayer | undefined;
constructor(options: ClientOptions) {
player: Map<string, YTPlayer>;
useProxy: boolean;
proxySettings?: ProxyOptions;

constructor(options: ClientOptions, proxyOptions?: ProxyOptions) {
super(options);
this.player = undefined;
this.player = new Map();
this.useProxy = Boolean(proxyOptions);
this.proxySettings = proxyOptions ?? undefined;
}

public setPlayer(serverId: string, player: YTPlayer): void {
this.player.set(serverId, player);
}

public getPlayer(serverId: string): YTPlayer | undefined {
return this.player.get(serverId);
}

public deletePlayer(serverId: string): boolean {
return this.player.delete(serverId);
}

public getURI(): string {
if (this.useProxy && this.proxySettings) {
const { host, port } = this.proxySettings;
return `http://${host}:${port}/`;
}
return '';
}
}
23 changes: 13 additions & 10 deletions src/Utils/songResolver.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { format_count, seconds_to_time } from '../Utils/NumberUtil';
import { YTPlayer } from '../classes/player';
import { client } from '../index';
import { Builder } from './Builder';
import ytdl from '@distube/ytdl-core';
Expand All @@ -18,28 +19,30 @@ export function songResolver(info: ytdl.videoInfo, requestedBy?: string, request
}

export function formatProgressBar(current: number, total: number, barLength: number = 20): string {
const progress = Math.round((current / total) * barLength);
const empty = Math.max(barLength - progress, 0); // `empty` が負にならないように修正
const filled = '█'.repeat(progress); // 進行中部分(█)
const unfilled = '░'.repeat(empty); // 残り部分(░)
const progress = Math.round((current / total) * barLength);
const empty = Math.max(barLength - progress, 0); // `empty` が負にならないように修正
const filled = '█'.repeat(progress); // 進行中部分(█)
const unfilled = '░'.repeat(empty); // 残り部分(░)

return `${seconds_to_time(current)} [${filled}${unfilled}] ${seconds_to_time(total)} (${Math.round((current / total) * 100)}%)`;
return `${seconds_to_time(current)} [${filled}${unfilled}] ${seconds_to_time(total)} (${Math.round((current / total) * 100)}%)`;
}


export async function getSongInfo(url: string) {
export async function getSongInfo(url: string, serverId: string) {
const info = await ytdl.getInfo(url);
const song = songResolver(info);
const player = client.getPlayer(serverId) as YTPlayer;

// currentDuration が undefined または NaN の場合、デフォルトで 0 を設定
const currentDuration = Number(client.player?.resource?.playbackDuration) ? Math.round(Number(client.player?.resource?.playbackDuration) / 1000) : 0;
const currentDuration = Number(player.resource?.playbackDuration)
? Math.round(Number(player.resource?.playbackDuration) / 1000)
: 0;
const totalDuration = Number(info.videoDetails.lengthSeconds);

const progressBar = formatProgressBar(currentDuration, totalDuration);

// 次の曲がキューにあるか確認
const nextSong = (await ytdl.validateURL(client.player?.queue.store[1] as string))
? await ytdl.getInfo(client.player?.queue.store[1] as string)
const nextSong = (await ytdl.validateURL(player?.queue.store[1] as string))
? await ytdl.getInfo(player.queue.store[1] as string)
: null;

let footerText = '次の曲はありません';
Expand Down
15 changes: 10 additions & 5 deletions src/classes/player.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export class YTPlayer {
});
this.player = createAudioPlayer();
this.queue = queueManager.getQueue(serverId) as Queue;
this.volume = 0.1;
this.volume = 1;
this.player
.on('subscribe', () => {
this.isPlaying = true;
Expand All @@ -42,17 +42,22 @@ export class YTPlayer {
}

public play() {
let agent = undefined;
if (client.useProxy) agent = ytdl.createProxyAgent({ uri: client.getURI() });

const queue = queueManager.getQueue(this.serverId);
const stream = ytdl(ytdl.getURLVideoID(queue?.currentSong as string), {
agent: agent ?? undefined,
filter: (format) => format.audioCodec === 'opus' && format.container === 'webm',
quality: 'highest',
highWaterMark: 32 * 1024 * 1024
});

this.resource = createAudioResource(stream, {
inputType: StreamType.WebmOpus,
inlineVolume: true
});
this.resource.volume?.setVolume(this.volume);
this.resource.volume?.setVolume(this.volume / 10);
this.connection.subscribe(this.player);
this.player.play(this.resource);
}
Expand All @@ -68,7 +73,7 @@ export class YTPlayer {
public stop(): void {
this.connection.destroy();
queueManager.deleteQueue(this.serverId);
client.player = undefined;
client.deletePlayer(this.serverId);
}

public skip(): void {
Expand All @@ -94,14 +99,14 @@ export class YTPlayer {
if (this.queue.loop === 'queue') this.queue.loopQueue();
if (this.queue.loop === 'track') this.queue.loopTrack();
this.play();
await this.fetchSongData();
return await this.fetchSongData();
}

private async fetchSongData() {
const channel = client.channels.cache.get(this.messageChannelId);
if (!channel || !channel.isTextBased()) return;
if (channel.isTextBased() && 'send' in channel) {
await channel.send(await getSongInfo(this.queue.currentSong!));
await channel.send(await getSongInfo(this.queue.currentSong!, this.serverId));
}
}
}
2 changes: 1 addition & 1 deletion src/commands/changeVolume.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { client } from '../index';
import { Message } from 'discord.js';

export async function changeVolumeCommand(message: Message) {
const player = client?.player;
const player = client.getPlayer(message.guildId!);
if (!player) return message.reply(embeds.videoNotPlaying);

const content = message.content.split(' ');
Expand Down
8 changes: 6 additions & 2 deletions src/commands/loop.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,16 @@ import { client } from '../index';
import { Message } from 'discord.js';

export async function loopCommand(message: Message, args: string[]) {
const player = client?.player;
const player = client.getPlayer(message.guildId!);
if (!player) return message.reply(embeds.videoNotPlaying);
const queue = queueManager.queues.get(message.guildId!) as Queue;
args = args.filter((arg) => arg !== '');
if (args.length === 0) {
queue.loop === 'none' ? queue.setLoop('queue') : queue.setLoop('none');
if (queue.loop === 'none') {
queue.setLoop('queue');
} else {
queue.setLoop('none');
}
} else if (args.length === 1) {
switch (args[0]) {
case 'none':
Expand Down
4 changes: 2 additions & 2 deletions src/commands/nowplaying.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import { client } from '../index';
import { Message } from 'discord.js';

export async function nowplayingCommand(message: Message) {
const player = client?.player;
const player = client.getPlayer(message.guildId!);
if (!player) return message.reply(embeds.videoNotPlaying);
const queue = queueManager.getQueue(message.guild?.id as string) as Queue;
const info = await getSongInfo(queue.currentSong);
const info = await getSongInfo(queue.currentSong, message.guildId!);
return message.reply(info);
}
2 changes: 1 addition & 1 deletion src/commands/pause.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { AudioPlayerStatus } from '@discordjs/voice';
import { Message } from 'discord.js';

export async function pauseCommand(message: Message) {
const player = client?.player;
const player = client.getPlayer(message.guildId!);
if (!player) return message.reply(embeds.videoNotPlaying);

if (player.player.state.status === AudioPlayerStatus.Playing) {
Expand Down
15 changes: 7 additions & 8 deletions src/commands/play.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,17 @@ import { Message, VoiceBasedChannel } from 'discord.js';
let url: string;

export async function playCommand(message: Message) {
let player = client?.player;
if (!queueManager.getQueue(message.guild?.id as string)) {
queueManager.setQueue(message.guild?.id as string, new Queue());
let player = client.getPlayer(message.guildId!);
if (!queueManager.getQueue(message.guild!.id)) {
queueManager.setQueue(message.guild!.id, new Queue());
}
const queue = queueManager.getQueue(message.guild?.id as string) as Queue;
if (!player) {
client.player = new YTPlayer(
message.guild?.id as string,
message.member?.voice.channel as VoiceBasedChannel,
message.channel.id
client.setPlayer(
message.guild!.id,
new YTPlayer(message.guildId!, message.member!.voice.channel as VoiceBasedChannel, message.channelId)
);
player = client.player;
player = client.getPlayer(message.guildId!) as YTPlayer;
}
url = message.content.split(' ')[1];
if (!url) return message.reply(embeds.noUrl);
Expand Down
2 changes: 1 addition & 1 deletion src/commands/queue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import ytdl from '@distube/ytdl-core';
import { Message } from 'discord.js';

export async function queueCommand(message: Message) {
const player = client?.player;
const player = client.getPlayer(message.guildId!);
if (!player) return message.reply(embeds.videoNotPlaying);
const queue = queueManager.getQueue(message.guildId!) as Queue;

Expand Down
2 changes: 1 addition & 1 deletion src/commands/resume.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { AudioPlayerStatus } from '@discordjs/voice';
import { Message } from 'discord.js';

export async function resumeCommand(message: Message) {
const player = client?.player;
const player = client.getPlayer(message.guildId!);
if (!player) return message.reply(embeds.videoNotPlaying);
if (player.player.state.status === AudioPlayerStatus.Paused) {
player.resume();
Expand Down
2 changes: 1 addition & 1 deletion src/commands/skip.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { client } from '../index';
import { Message } from 'discord.js';

export async function skipCommand(message: Message) {
const player = client?.player;
const player = client.getPlayer(message.guildId!);
if (!player) return message.reply(embeds.videoNotPlaying);
player.skip();
return message.reply(embeds.videoNext);
Expand Down
Loading

0 comments on commit 74c127f

Please sign in to comment.