From 3e827357091e5c49f957fb93b20ddec07e182135 Mon Sep 17 00:00:00 2001 From: ysr9029 <56439343+Nich87@users.noreply.github.com> Date: Thu, 7 Dec 2023 00:22:12 +0900 Subject: [PATCH 1/8] =?UTF-8?q?=F0=9F=A7=B9=20Redundant=20code=20made=20ne?= =?UTF-8?q?at?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Events/onInteractionCreate.ts | 1 + src/Events/onMessageCreate.ts | 5 ++++- src/commands/debug.ts | 8 ++------ src/commands/help.ts | 4 ++-- src/commands/loop.ts | 2 +- src/commands/nowplaying.ts | 2 +- src/commands/pause.ts | 6 ++---- src/commands/play.ts | 4 ++-- src/commands/queue.ts | 2 +- src/commands/resume.ts | 6 ++---- src/commands/skip.ts | 2 +- src/commands/stop.ts | 4 +--- src/embeds/index.ts | 2 +- src/interactions/help.ts | 2 +- src/interactions/loop.ts | 2 +- src/interactions/nowplaying.ts | 2 +- src/interactions/pause.ts | 6 ++---- src/interactions/play.ts | 4 ++-- src/interactions/queue.ts | 2 +- src/interactions/resume.ts | 4 +--- src/interactions/skip.ts | 2 +- src/interactions/stop.ts | 4 +--- 22 files changed, 32 insertions(+), 44 deletions(-) diff --git a/src/Events/onInteractionCreate.ts b/src/Events/onInteractionCreate.ts index 52edbc5..996746b 100644 --- a/src/Events/onInteractionCreate.ts +++ b/src/Events/onInteractionCreate.ts @@ -6,6 +6,7 @@ export async function onInteractionCreate(interaction: BaseInteraction): Promise if (!interaction.isChatInputCommand()) return; if (!interaction.guild) { interaction.reply({ content: 'This command can only be used in a server!', ephemeral: true }); + return; } const commandName = interaction.commandName; if (commandName === 'help') return interactions.help(interaction); diff --git a/src/Events/onMessageCreate.ts b/src/Events/onMessageCreate.ts index 008ba86..2cc2dfe 100644 --- a/src/Events/onMessageCreate.ts +++ b/src/Events/onMessageCreate.ts @@ -8,7 +8,10 @@ export async function onMessageCreate(message: Message): Promise if (message.author.bot || !message.content.startsWith(prefix) || !message.guild) return; const args = message.content.slice(prefix.length).trim().split(/ +/) as string[]; const commandName = args.shift()?.toLowerCase(); - if (commandName === 'help' || commandName === 'h') return commands.help(message); + if (commandName === 'help' || commandName === 'h') { + commands.help(message); + return; + } const channel = message.member?.voice.channel; if (!channel) { message.reply(embeds.voiceChannelJoin); diff --git a/src/commands/debug.ts b/src/commands/debug.ts index 6965d37..1bb4dcc 100644 --- a/src/commands/debug.ts +++ b/src/commands/debug.ts @@ -5,12 +5,8 @@ import ytdl from 'ytdl-core'; export async function debugCommand(message: Message) { const url = message.content.split(' ')[1]; - if (!url) { - return message.reply(embeds.noUrl); - } - if (!ytdl.validateURL(url)) { - return message.reply(embeds.invaildUrl); - } + if (!url) return message.reply(embeds.noUrl); + if (!ytdl.validateURL(url)) return message.reply(embeds.invaildUrl); const info = await ytdl.getInfo(url); console.table(songResolver(info)); } diff --git a/src/commands/help.ts b/src/commands/help.ts index f911b48..f715799 100644 --- a/src/commands/help.ts +++ b/src/commands/help.ts @@ -1,6 +1,6 @@ import { embeds } from '../embeds'; import { Message } from 'discord.js'; -export async function helpCommand(message: Message): Promise { - message.reply(embeds.help); +export async function helpCommand(message: Message) { + return message.reply(embeds.help); } diff --git a/src/commands/loop.ts b/src/commands/loop.ts index 8b6a0e1..40f63e0 100644 --- a/src/commands/loop.ts +++ b/src/commands/loop.ts @@ -5,7 +5,7 @@ import { Message } from 'discord.js'; export async function loopCommand(message: Message, args: string[]) { const player = client?.player; - if (typeof player === 'undefined') return message.reply(embeds.videoNotPlaying); + 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) { diff --git a/src/commands/nowplaying.ts b/src/commands/nowplaying.ts index 15f0e7a..03afc05 100644 --- a/src/commands/nowplaying.ts +++ b/src/commands/nowplaying.ts @@ -6,7 +6,7 @@ import { Message } from 'discord.js'; export async function nowplayingCommand(message: Message) { const player = client?.player; - if (typeof player === 'undefined') return message.reply(embeds.videoNotPlaying); + if (!player) return message.reply(embeds.videoNotPlaying); const queue = queueManager.getQueue(message.guild?.id as string) as Queue; const info = await getSongInfo(queue.currentSong); return message.reply(info); diff --git a/src/commands/pause.ts b/src/commands/pause.ts index 986ad15..05cb29d 100644 --- a/src/commands/pause.ts +++ b/src/commands/pause.ts @@ -5,7 +5,7 @@ import { Message } from 'discord.js'; export async function pauseCommand(message: Message) { const player = client?.player; - if (typeof player === 'undefined') return message.reply(embeds.videoNotPlaying); + if (!player) return message.reply(embeds.videoNotPlaying); if (player.player.state.status === AudioPlayerStatus.Playing) { player.pause(); @@ -13,7 +13,5 @@ export async function pauseCommand(message: Message) { } else if (player.player.state.status === AudioPlayerStatus.Paused) { player.resume(); message.reply(embeds.videoResumed); - } else { - message.reply(embeds.videoNotPlaying); - } + } else message.reply(embeds.videoNotPlaying); } diff --git a/src/commands/play.ts b/src/commands/play.ts index 38d635e..5da3c87 100644 --- a/src/commands/play.ts +++ b/src/commands/play.ts @@ -9,11 +9,11 @@ let url: string; export async function playCommand(message: Message) { let player = client?.player; - if (typeof queueManager.getQueue(message.guild?.id as string) === 'undefined') { + if (!queueManager.getQueue(message.guild?.id as string)) { queueManager.setQueue(message.guild?.id as string, new Queue()); } const queue = queueManager.getQueue(message.guild?.id as string) as Queue; - if (typeof player === 'undefined') { + if (!player) { client.player = new YTPlayer( message.guild?.id as string, message.member?.voice.channel as VoiceBasedChannel, diff --git a/src/commands/queue.ts b/src/commands/queue.ts index 3a102f4..b5aaeae 100644 --- a/src/commands/queue.ts +++ b/src/commands/queue.ts @@ -7,7 +7,7 @@ import ytdl from 'ytdl-core'; export async function queueCommand(message: Message) { const player = client?.player; - if (typeof player === 'undefined') return message.reply(embeds.videoNotPlaying); + if (!player) return message.reply(embeds.videoNotPlaying); const queue = queueManager.getQueue(message.guildId!) as Queue; const embed = new embeds.embed().setTitle('Queue').setColor('Blue').setTimestamp(); diff --git a/src/commands/resume.ts b/src/commands/resume.ts index 21e9cd8..3e514e6 100644 --- a/src/commands/resume.ts +++ b/src/commands/resume.ts @@ -5,13 +5,11 @@ import { Message } from 'discord.js'; export async function resumeCommand(message: Message) { const player = client?.player; - if (typeof player === 'undefined') return message.reply(embeds.videoNotPlaying); + if (!player) return message.reply(embeds.videoNotPlaying); if (player.player.state.status === AudioPlayerStatus.Paused) { player.resume(); message.reply(embeds.videoResumed); } else if (player.player.state.status === AudioPlayerStatus.Playing) { message.reply(embeds.videoNotPaused); - } else { - message.reply(embeds.videoNotPlaying); - } + } else message.reply(embeds.videoNotPlaying); } diff --git a/src/commands/skip.ts b/src/commands/skip.ts index f60aaa9..d6aac50 100644 --- a/src/commands/skip.ts +++ b/src/commands/skip.ts @@ -4,7 +4,7 @@ import { Message } from 'discord.js'; export async function skipCommand(message: Message) { const player = client?.player; - if (typeof player === 'undefined') return message.reply(embeds.videoNotPlaying); + if (!player) return message.reply(embeds.videoNotPlaying); player.skip(); return message.reply(embeds.videoNext); } diff --git a/src/commands/stop.ts b/src/commands/stop.ts index 5e8965f..5b59308 100644 --- a/src/commands/stop.ts +++ b/src/commands/stop.ts @@ -8,9 +8,7 @@ export async function stopCommand(message: Message): Promise { message.guild.members.me.voice.disconnect(); client.player = undefined; message.reply(embeds.videoStopped); - } else { - message.reply(embeds.videoNotPlaying); - } + } else message.reply(embeds.videoNotPlaying); queueManager.queues.delete(message.guildId!); } diff --git a/src/embeds/index.ts b/src/embeds/index.ts index 19d3751..7bf3ab3 100644 --- a/src/embeds/index.ts +++ b/src/embeds/index.ts @@ -15,7 +15,7 @@ export const embeds = { { name: 'pause', value: '再生を一時停止/再開します。' }, { name: 'resume', value: '再生を再開します。' }, { name: 'nowplaying', value: '現在の曲を表示します。' }, - { name: 'volume', value: '音量を変更します。'} + { name: 'volume', value: '音量を変更します。' } ) .build(), videoNotPlaying: new Builder() diff --git a/src/interactions/help.ts b/src/interactions/help.ts index 7b04714..73871a1 100644 --- a/src/interactions/help.ts +++ b/src/interactions/help.ts @@ -1,6 +1,6 @@ import { embeds } from '../embeds'; import { ChatInputCommandInteraction } from 'discord.js'; -export async function helpCommand(interaction: ChatInputCommandInteraction): Promise { +export async function helpCommand(interaction: ChatInputCommandInteraction) { interaction.reply(embeds.help); } diff --git a/src/interactions/loop.ts b/src/interactions/loop.ts index ec7636d..087b924 100644 --- a/src/interactions/loop.ts +++ b/src/interactions/loop.ts @@ -5,7 +5,7 @@ import { ChatInputCommandInteraction } from 'discord.js'; export async function loopCommand(interaction: ChatInputCommandInteraction) { const player = client?.player; - if (typeof player === 'undefined') return interaction.reply(embeds.videoNotPlaying); + if (!player) return interaction.reply(embeds.videoNotPlaying); const queue = queueManager.queues.get(interaction.guildId!) as Queue; const settings = interaction.options.getString('mode') as string; if (!settings) { diff --git a/src/interactions/nowplaying.ts b/src/interactions/nowplaying.ts index 7934402..49f21d5 100644 --- a/src/interactions/nowplaying.ts +++ b/src/interactions/nowplaying.ts @@ -7,7 +7,7 @@ import { ChatInputCommandInteraction } from 'discord.js'; export async function nowplayingCommand(interaction: ChatInputCommandInteraction) { await interaction.deferReply(); const player = client?.player; - if (typeof player === 'undefined') return interaction.followUp(embeds.videoNotPlaying); + if (!player) return interaction.followUp(embeds.videoNotPlaying); const queue = queueManager.getQueue(interaction.guild?.id as string) as Queue; const info = await getSongInfo(queue.currentSong); return interaction.followUp(info); diff --git a/src/interactions/pause.ts b/src/interactions/pause.ts index bea9980..5d62ab7 100644 --- a/src/interactions/pause.ts +++ b/src/interactions/pause.ts @@ -5,7 +5,7 @@ import { ChatInputCommandInteraction } from 'discord.js'; export async function pauseCommand(interaction: ChatInputCommandInteraction) { const player = client?.player; - if (typeof player === 'undefined') return interaction.reply(embeds.videoNotPlaying); + if (!player) return interaction.reply(embeds.videoNotPlaying); if (player.player.state.status === AudioPlayerStatus.Playing) { player.pause(); @@ -13,7 +13,5 @@ export async function pauseCommand(interaction: ChatInputCommandInteraction) { } else if (player.player.state.status === AudioPlayerStatus.Paused) { player.resume(); interaction.reply(embeds.videoResumed); - } else { - interaction.reply(embeds.videoNotPlaying); - } + } else interaction.reply(embeds.videoNotPlaying); } diff --git a/src/interactions/play.ts b/src/interactions/play.ts index 5778632..cef7b9c 100644 --- a/src/interactions/play.ts +++ b/src/interactions/play.ts @@ -9,13 +9,13 @@ let url: string; export async function playCommand(interaction: ChatInputCommandInteraction) { let player = client?.player; - if (typeof queueManager.getQueue(interaction.guild?.id as string) === 'undefined') { + if (!queueManager.getQueue(interaction.guild?.id as string)) { queueManager.setQueue(interaction.guild?.id as string, new Queue()); } const queue = queueManager.getQueue(interaction.guild?.id as string) as Queue; if (!interaction.channel) return; if (!(interaction.member instanceof GuildMember)) return; - if (typeof player === 'undefined') { + if (!player) { client.player = new YTPlayer( interaction.guild?.id as string, interaction.member?.voice.channel as VoiceBasedChannel, diff --git a/src/interactions/queue.ts b/src/interactions/queue.ts index 72c5830..77271c2 100644 --- a/src/interactions/queue.ts +++ b/src/interactions/queue.ts @@ -8,7 +8,7 @@ import ytdl from 'ytdl-core'; export async function queueCommand(interaction: ChatInputCommandInteraction) { const player = client?.player; await interaction.deferReply(); - if (typeof player === 'undefined') return interaction.followUp(embeds.videoNotPlaying); + if (!player) return interaction.followUp(embeds.videoNotPlaying); const queue = queueManager.getQueue(interaction.guildId!) as Queue; const embed = new embeds.embed().setTitle('Queue').setColor('Blue').setTimestamp(); diff --git a/src/interactions/resume.ts b/src/interactions/resume.ts index 50c0703..7af6de3 100644 --- a/src/interactions/resume.ts +++ b/src/interactions/resume.ts @@ -11,7 +11,5 @@ export async function resumeCommand(interaction: ChatInputCommandInteraction) { interaction.reply(embeds.videoResumed); } else if (player.player.state.status === AudioPlayerStatus.Playing) { interaction.reply(embeds.videoNotPaused); - } else { - interaction.reply(embeds.videoNotPlaying); - } + } else interaction.reply(embeds.videoNotPlaying); } diff --git a/src/interactions/skip.ts b/src/interactions/skip.ts index 39872d7..3056b95 100644 --- a/src/interactions/skip.ts +++ b/src/interactions/skip.ts @@ -4,7 +4,7 @@ import { ChatInputCommandInteraction } from 'discord.js'; export async function skipCommand(interaction: ChatInputCommandInteraction) { const player = client?.player; - if (typeof player === 'undefined') return interaction.reply(embeds.videoNotPlaying); + if (!player) return interaction.reply(embeds.videoNotPlaying); player.skip(); return interaction.reply(embeds.videoNext); } diff --git a/src/interactions/stop.ts b/src/interactions/stop.ts index 39af13c..3890016 100644 --- a/src/interactions/stop.ts +++ b/src/interactions/stop.ts @@ -8,9 +8,7 @@ export async function stopCommand(interaction: ChatInputCommandInteraction): Pro interaction.guild.members.me.voice.disconnect(); client.player = undefined; interaction.reply(embeds.videoStopped); - } else { - interaction.reply(embeds.videoNotPlaying); - } + } else interaction.reply(embeds.videoNotPlaying); queueManager.queues.delete(interaction.guildId!); } From 10124382dcd79d074c9fc7504e61f650a52b007c Mon Sep 17 00:00:00 2001 From: ysr9029 <56439343+Nich87@users.noreply.github.com> Date: Thu, 7 Dec 2023 00:27:21 +0900 Subject: [PATCH 2/8] =?UTF-8?q?=F0=9F=94=A7=20Fixed=20to=20keep=20volume?= =?UTF-8?q?=20changes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/classes/player.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/classes/player.ts b/src/classes/player.ts index b9f228c..8c11008 100644 --- a/src/classes/player.ts +++ b/src/classes/player.ts @@ -52,7 +52,7 @@ export class YTPlayer { inputType: StreamType.WebmOpus, inlineVolume: true }); - this.resource.volume?.setVolume(0.1); + this.resource.volume?.setVolume(this.volume); this.connection.subscribe(this.player); this.player.play(this.resource); } @@ -76,6 +76,7 @@ export class YTPlayer { public changeVolume(volume: number): void { if (!this.resource) return; + this.volume = volume; this.resource.volume?.setVolume(volume / 10); } From 7d402c9abf3b30c02183a3423ac01b647019e15b Mon Sep 17 00:00:00 2001 From: MotiCAT Date: Thu, 7 Dec 2023 05:35:24 +0900 Subject: [PATCH 3/8] =?UTF-8?q?=F0=9F=A9=B9Fixed=20not=20reconnecting?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/classes/player.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/classes/player.ts b/src/classes/player.ts index 8c11008..4100370 100644 --- a/src/classes/player.ts +++ b/src/classes/player.ts @@ -68,6 +68,7 @@ export class YTPlayer { public stop(): void { this.connection.destroy(); queueManager.deleteQueue(this.serverId); + client.player = undefined; } public skip(): void { From 3f2c5d8871f76e620c92f7b9389f1d95fe9733b0 Mon Sep 17 00:00:00 2001 From: MotiCAT Date: Thu, 7 Dec 2023 11:24:43 +0900 Subject: [PATCH 4/8] =?UTF-8?q?=F0=9F=A9=B9Default=20volume=20changed=20to?= =?UTF-8?q?=200.1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/classes/player.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/classes/player.ts b/src/classes/player.ts index 4100370..06708b3 100644 --- a/src/classes/player.ts +++ b/src/classes/player.ts @@ -29,7 +29,7 @@ export class YTPlayer { }); this.player = createAudioPlayer(); this.queue = queueManager.getQueue(serverId) as Queue; - this.volume = 100 / 10; + this.volume = 0.1; this.player .on('subscribe', () => { this.isPlaying = true; From fd3fa79fa4966edb9d7387a87c990fab61522453 Mon Sep 17 00:00:00 2001 From: MotiCAT Date: Thu, 7 Dec 2023 11:25:40 +0900 Subject: [PATCH 5/8] =?UTF-8?q?=F0=9F=A9=B9Fixed=20a=20bug=20with=20differ?= =?UTF-8?q?ent=20display=20volume.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/interactions/changeVolume.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/interactions/changeVolume.ts b/src/interactions/changeVolume.ts index 1092916..d6f3621 100644 --- a/src/interactions/changeVolume.ts +++ b/src/interactions/changeVolume.ts @@ -7,7 +7,7 @@ export async function changeVolumeCommand(interaction: ChatInputCommandInteracti if (!player) return interaction.reply(embeds.videoNotPlaying); const vol = interaction.options.getInteger('volume'); - if (!vol) return interaction.reply({ content: `現在の音量は${player.volume}です。` }); + if (!vol) return interaction.reply({ content: `現在の音量は${player.volume * 10}です。` }); if (vol >= 100) { player.changeVolume(100 / 10); return interaction.reply({ content: 'ボリュームを最大に設定しました。' }); From a82ef478487aa8dd209a027ca1cd71d77a3d8c6f Mon Sep 17 00:00:00 2001 From: ysr9029 <56439343+Nich87@users.noreply.github.com> Date: Fri, 8 Dec 2023 23:27:12 +0900 Subject: [PATCH 6/8] =?UTF-8?q?=F0=9F=92=BE=20added=20youtube-sr?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package-lock.json | 6 ++++++ package.json | 1 + 2 files changed, 7 insertions(+) diff --git a/package-lock.json b/package-lock.json index 89a75d2..b385192 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,6 +15,7 @@ "dotenv": "^16.3.1", "ffmpeg-static": "^5.2.0", "tweetnacl": "^1.0.3", + "youtube-sr": "^4.3.10", "ytdl-core": "^4.11.5" }, "devDependencies": { @@ -3015,6 +3016,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/youtube-sr": { + "version": "4.3.10", + "resolved": "https://registry.npmjs.org/youtube-sr/-/youtube-sr-4.3.10.tgz", + "integrity": "sha512-YTpIWy2c1XLN4VpsUuZTDNXpJ2sLZQyG0kX1vq3nymHhDKro2SoeODey3pZazW+6AjfmNxoSnI8pCSzPrEa3jw==" + }, "node_modules/ytdl-core": { "version": "4.11.5", "resolved": "https://registry.npmjs.org/ytdl-core/-/ytdl-core-4.11.5.tgz", diff --git a/package.json b/package.json index c0ff75f..ed71679 100644 --- a/package.json +++ b/package.json @@ -37,6 +37,7 @@ "dotenv": "^16.3.1", "ffmpeg-static": "^5.2.0", "tweetnacl": "^1.0.3", + "youtube-sr": "^4.3.10", "ytdl-core": "^4.11.5" }, "repository": { From f8291e9800f64e7a535716cd1db01b1116bd8808 Mon Sep 17 00:00:00 2001 From: ysr9029 <56439343+Nich87@users.noreply.github.com> Date: Fri, 8 Dec 2023 23:29:09 +0900 Subject: [PATCH 7/8] =?UTF-8?q?=E2=9C=A8=20Create=20search=20commands?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Events/onInteractionCreate.ts | 7 ++++ src/Events/onMessageCreate.ts | 3 ++ src/commands/index.ts | 4 +- src/commands/search.ts | 28 +++++++++++++ src/deploy-commands.ts | 4 ++ src/embeds/index.ts | 4 ++ src/interactions/handleplay.ts | 68 +++++++++++++++++++++++++++++++ src/interactions/index.ts | 6 ++- src/interactions/search.ts | 34 ++++++++++++++++ 9 files changed, 156 insertions(+), 2 deletions(-) create mode 100644 src/commands/search.ts create mode 100644 src/interactions/handleplay.ts create mode 100644 src/interactions/search.ts diff --git a/src/Events/onInteractionCreate.ts b/src/Events/onInteractionCreate.ts index 996746b..d7f30d0 100644 --- a/src/Events/onInteractionCreate.ts +++ b/src/Events/onInteractionCreate.ts @@ -3,6 +3,10 @@ import { interactions } from '../interactions'; import { BaseInteraction, Awaitable, ChannelType, GuildMember } from 'discord.js'; export async function onInteractionCreate(interaction: BaseInteraction): Promise> { + if (interaction.isStringSelectMenu()) { + interactions.searchplay(interaction); + return; + } if (!interaction.isChatInputCommand()) return; if (!interaction.guild) { interaction.reply({ content: 'This command can only be used in a server!', ephemeral: true }); @@ -54,6 +58,9 @@ export async function onInteractionCreate(interaction: BaseInteraction): Promise case 'nowplaying': interactions.nowplaying(interaction); break; + case 'search': + interactions.search(interaction); + break; default: interaction.reply(embeds.unknownCommand); break; diff --git a/src/Events/onMessageCreate.ts b/src/Events/onMessageCreate.ts index 2cc2dfe..d1db9b1 100644 --- a/src/Events/onMessageCreate.ts +++ b/src/Events/onMessageCreate.ts @@ -69,6 +69,9 @@ export async function onMessageCreate(message: Message): Promise case 'current': commands.nowplaying(message); break; + case 'search': + commands.search(message); + break; default: message.reply(embeds.unknownCommand); break; diff --git a/src/commands/index.ts b/src/commands/index.ts index 7cff44a..b6d3903 100644 --- a/src/commands/index.ts +++ b/src/commands/index.ts @@ -6,6 +6,7 @@ import { pauseCommand } from './pause'; import { playCommand } from './play'; import { queueCommand } from './queue'; import { resumeCommand } from './resume'; +import { searchCommand } from './search'; import { skipCommand } from './skip'; import { stopCommand } from './stop'; @@ -19,5 +20,6 @@ export const commands = { queue: queueCommand, resume: resumeCommand, skip: skipCommand, - stop: stopCommand + stop: stopCommand, + search: searchCommand }; diff --git a/src/commands/search.ts b/src/commands/search.ts new file mode 100644 index 0000000..a7364a5 --- /dev/null +++ b/src/commands/search.ts @@ -0,0 +1,28 @@ +import { embeds } from '../embeds'; +import { Message, StringSelectMenuBuilder, StringSelectMenuOptionBuilder, ActionRowBuilder } from 'discord.js'; +import ytsr from 'youtube-sr'; + +export async function searchCommand(message: Message) { + const videos = await ytsr.search(message.content.split(' ').slice(1).join(' '), { + type: 'video' + }); + + if (!videos.length) return message.reply(embeds.noResult); + + const menu = new StringSelectMenuBuilder() + .setCustomId('search') + .setPlaceholder('Select a video') + .addOptions( + videos.map((video, index) => + new StringSelectMenuOptionBuilder() + .setLabel(`${index + 1}. ${video.title}`) + .setValue(video.url) + .setDescription(String(video.durationFormatted)) + .setEmoji('🎵') + ) + ); + + const row = new ActionRowBuilder().addComponents(menu); + + message.reply({ content: 'Select a video', components: [row] }); +} diff --git a/src/deploy-commands.ts b/src/deploy-commands.ts index e65a53d..da8e66e 100644 --- a/src/deploy-commands.ts +++ b/src/deploy-commands.ts @@ -8,6 +8,10 @@ const commands = [ .setName('play') .setDescription('Play a song') .addStringOption((option) => option.setName('url').setDescription('The song to play').setRequired(true)), + new SlashCommandBuilder() + .setName('search') + .setDescription('Search for a song') + .addStringOption((option) => option.setName('query').setDescription('Enter search words').setRequired(true)), new SlashCommandBuilder().setName('pause').setDescription('Pause the current song'), new SlashCommandBuilder().setName('resume').setDescription('Resume the current song'), new SlashCommandBuilder().setName('skip').setDescription('Skip the current song'), diff --git a/src/embeds/index.ts b/src/embeds/index.ts index 7bf3ab3..b2a56bc 100644 --- a/src/embeds/index.ts +++ b/src/embeds/index.ts @@ -38,6 +38,10 @@ export const embeds = { .addFields({ name: 'Error', value: '有効なURLを指定してください。' }) .setColor('Red') .build(), + noResult: new Builder() + .addFields({ name: 'Error', value: '検索結果が見つかりませんでした。' }) + .setColor('Red') + .build(), voiceChannnelPermission: new Builder() .addFields({ name: 'Error', value: 'ボイスチャンネルに参加する権限がありません。' }) .setColor('Red') diff --git a/src/interactions/handleplay.ts b/src/interactions/handleplay.ts new file mode 100644 index 0000000..c89924c --- /dev/null +++ b/src/interactions/handleplay.ts @@ -0,0 +1,68 @@ +import { YTPlayer } from '../classes/player'; +import { Queue, queueManager } from '../classes/queue'; +import { embeds } from '../embeds'; +import { client } from '../index'; +import { StringSelectMenuInteraction, ChannelType, VoiceBasedChannel, GuildMember } from 'discord.js'; +import ytdl from 'ytdl-core'; + +let url: string; + +export async function searchPlayCommand(interaction: StringSelectMenuInteraction) { + let player = client?.player; + if (!queueManager.getQueue(interaction.guild?.id as string)) { + queueManager.setQueue(interaction.guild?.id as string, new Queue()); + } + const queue = queueManager.getQueue(interaction.guild?.id as string) as Queue; + if (!interaction.channel) return; + if (!(interaction.member instanceof GuildMember)) return; + if (!player) { + client.player = new YTPlayer( + interaction.guild?.id as string, + interaction.member?.voice.channel as VoiceBasedChannel, + interaction.channel?.id + ); + player = client.player; + } + + url = interaction.values[0]; + const channel = interaction.member?.voice.channel; + if (!url) return interaction.reply(embeds.noUrl); + if (!ytdl.validateURL(url)) return interaction.reply(embeds.invaildUrl); + if (!channel) return interaction.reply(embeds.voiceChannelJoin); + if (channel.type !== ChannelType.GuildVoice) return; + if (!channel.joinable) return interaction.reply(embeds.voiceChannnelJoined); + if (!channel.speakable) return interaction.reply(embeds.voiceChannnelPermission); + + if (!queue.length || !player.isPlaying) { + queue.addSong(url); + const info = await ytdl.getInfo(url); + interaction.reply( + new embeds.embed() + .setTitle('Success') + .setDescription(`**[${info.videoDetails.title}](${info.videoDetails.video_url})を再生します。**`) + .addFields({ + name: info.videoDetails.title, + value: `投稿者: [${info.videoDetails.author.name}](${info.videoDetails.author.channel_url})` + }) + .setImage(info.videoDetails.thumbnails[0].url.split('?')[0]) + .setColor('Green') + .build() + ); + if (queue.length === 1) return player.play(); + } else { + queue.addSong(url); + const info = await ytdl.getInfo(url); + interaction.reply( + new embeds.embed() + .setTitle('Info') + .setDescription(`**[${info.videoDetails.title}](${info.videoDetails.video_url})をキューに追加しました。**`) + .addFields({ + name: info.videoDetails.title, + value: `投稿者: [${info.videoDetails.author.name}](${info.videoDetails.author.channel_url})` + }) + .setImage(info.videoDetails.thumbnails[0].url.split('?')[0]) + .setColor('Yellow') + .build() + ); + } +} diff --git a/src/interactions/index.ts b/src/interactions/index.ts index 2435020..d9edbf4 100644 --- a/src/interactions/index.ts +++ b/src/interactions/index.ts @@ -1,4 +1,5 @@ import { changeVolumeCommand } from './changeVolume'; +import { searchPlayCommand } from './handleplay'; import { helpCommand } from './help'; import { loopCommand } from './loop'; import { nowplayingCommand } from './nowplaying'; @@ -6,6 +7,7 @@ import { pauseCommand } from './pause'; import { playCommand } from './play'; import { queueCommand } from './queue'; import { resumeCommand } from './resume'; +import { searchCommand } from './search'; import { skipCommand } from './skip'; import { stopCommand } from './stop'; @@ -19,5 +21,7 @@ export const interactions = { queue: queueCommand, resume: resumeCommand, skip: skipCommand, - stop: stopCommand + stop: stopCommand, + search: searchCommand, + searchplay: searchPlayCommand }; diff --git a/src/interactions/search.ts b/src/interactions/search.ts new file mode 100644 index 0000000..523dc78 --- /dev/null +++ b/src/interactions/search.ts @@ -0,0 +1,34 @@ +import { embeds } from '../embeds'; +import { + ChatInputCommandInteraction, + StringSelectMenuBuilder, + StringSelectMenuOptionBuilder, + ActionRowBuilder +} from 'discord.js'; +import ytsr from 'youtube-sr'; + +export async function searchCommand(interaction: ChatInputCommandInteraction) { + interaction.deferReply(); + const videos = await ytsr.search(interaction.options.getString('query') as string, { + type: 'video' + }); + + if (!videos.length) return interaction.followUp(embeds.noResult); + + const menu = new StringSelectMenuBuilder() + .setCustomId('search') + .setPlaceholder('Select a video') + .addOptions( + videos.map((video, index) => + new StringSelectMenuOptionBuilder() + .setLabel(`${index + 1}. ${video.title}`) + .setValue(video.url) + .setDescription(String(video.durationFormatted)) + .setEmoji('🎵') + ) + ); + + const row = new ActionRowBuilder().addComponents(menu); + + interaction.followUp({ content: 'Select a video', components: [row] }); +} From 58d217e816779eab8ea1b4759ac2d725b8561bae Mon Sep 17 00:00:00 2001 From: ysr9029 <56439343+Nich87@users.noreply.github.com> Date: Fri, 8 Dec 2023 23:38:32 +0900 Subject: [PATCH 8/8] =?UTF-8?q?=F0=9F=93=9D=20Create=20.gitattributes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitattributes | 1 + 1 file changed, 1 insertion(+) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..94f480d --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +* text=auto eol=lf \ No newline at end of file