diff --git a/commands/games-sp/whos-that-pokemon.js b/commands/games-sp/whos-that-pokemon.js index cf4be146..16d8bbfc 100644 --- a/commands/games-sp/whos-that-pokemon.js +++ b/commands/games-sp/whos-that-pokemon.js @@ -1,5 +1,4 @@ const Command = require('../../framework/Command'); -const { getVoiceConnection, createAudioPlayer, createAudioResource, AudioPlayerStatus } = require('@discordjs/voice'); const { createCanvas, loadImage } = require('canvas'); const request = require('node-superfetch'); const { reactIfAble } = require('../../util/Util'); @@ -94,23 +93,9 @@ module.exports = class WhosThatPokemonCommand extends Command { const names = data.names.map(name => name.name.toLowerCase()); const attachment = await this.createImage(data, true); const answerAttachment = await this.createImage(data, false); - const connection = msg.guild ? getVoiceConnection(msg.guild.id) : null; - if (msg.guild && connection && !this.client.dispatchers.has(msg.guild.id)) { - const resource = createAudioResource( - path.join(__dirname, '..', '..', 'assets', 'sounds', 'whos-that-pokemon.mp3') - ); - const dispatcher = createAudioPlayer(); - connection.subscribe(dispatcher); - dispatcher.play(resource); - this.client.dispatchers.set(msg.guild.id, dispatcher); - dispatcher.once(AudioPlayerStatus.Idle, () => { - this.client.dispatchers.get(msg.guild.id).stop(); - this.client.dispatchers.delete(msg.guild.id); - }); - dispatcher.once('error', () => { - this.client.dispatchers.get(msg.guild.id).stop(); - this.client.dispatchers.delete(msg.guild.id); - }); + const connection = msg.guild ? this.client.dispatchers.get(msg.guild.id) : null; + if (msg.guild && connection && connection.canPlay) { + connection.play(path.join(__dirname, '..', '..', 'assets', 'sounds', 'whos-that-pokemon.mp3')); await reactIfAble(msg, this.client.user, '🔉'); } await msg.reply('**You have 15 seconds, who\'s that Pokémon?**', { files: [attachment] }); @@ -119,6 +104,7 @@ module.exports = class WhosThatPokemonCommand extends Command { max: 1, time: 15000 }); + if (connection && data.cry) connection.play(data.cry); this.client.games.delete(msg.channel.id); if (!msgs.size) return msg.reply(`Time! It's **${data.name}**!`, { files: [answerAttachment] }); const guess = msgs.first().content.toLowerCase(); diff --git a/commands/util-voice/join.js b/commands/util-voice/join.js index bd656924..c653a0b8 100644 --- a/commands/util-voice/join.js +++ b/commands/util-voice/join.js @@ -1,5 +1,6 @@ const Command = require('../../framework/Command'); -const { joinVoiceChannel, getVoiceConnection } = require('@discordjs/voice'); +const { joinVoiceChannel } = require('@discordjs/voice'); +const Dispatcher = require('../../structures/Dispatcher'); module.exports = class JoinCommand extends Command { constructor(client) { @@ -22,7 +23,7 @@ module.exports = class JoinCommand extends Command { return msg.reply('I\'m missing the "Connect", "Speak", or "View Channel" permission for this channel.'); } if (!voiceChannel.joinable) return msg.reply('Your voice channel is not joinable.'); - if (getVoiceConnection(voiceChannel.guild.id)) { + if (this.client.dispatchers.has(msg.guild.id)) { return msg.reply('I am already in a voice channel.'); } joinVoiceChannel({ @@ -30,6 +31,7 @@ module.exports = class JoinCommand extends Command { guildId: voiceChannel.guild.id, adapterCreator: voiceChannel.guild.voiceAdapterCreator, }); + this.client.dispatchers.set(msg.guild.id, new Dispatcher(voiceChannel)); return msg.reply(`Joined **${voiceChannel.name}**!`); } }; diff --git a/commands/util-voice/leave.js b/commands/util-voice/leave.js index 162110ba..8e9e9fa2 100644 --- a/commands/util-voice/leave.js +++ b/commands/util-voice/leave.js @@ -1,5 +1,4 @@ const Command = require('../../framework/Command'); -const { getVoiceConnection } = require('@discordjs/voice'); module.exports = class LeaveCommand extends Command { constructor(client) { @@ -15,13 +14,13 @@ module.exports = class LeaveCommand extends Command { } run(msg) { - const connection = getVoiceConnection(msg.guild.id); + const connection = this.client.dispatchers.get(msg.guild.id); if (!connection) return msg.reply('I am not in a voice channel.'); - if (this.client.dispatchers.has(msg.guild.id)) { + if (!connection.canPlay) { const usage = this.client.registry.commands.get('stop').usage(); return msg.reply(`I am currently playing audio in this server. Please use ${usage} first.`); } - connection.destroy(); - return msg.reply('No more words out of me...'); + connection.leave(); + return msg.reply(`Left **${connection.channel.name}**...`); } }; diff --git a/commands/util-voice/pause.js b/commands/util-voice/pause.js index 90556b0e..19fdf869 100644 --- a/commands/util-voice/pause.js +++ b/commands/util-voice/pause.js @@ -1,5 +1,4 @@ const Command = require('../../framework/Command'); -const { getVoiceConnection } = require('@discordjs/voice'); module.exports = class PauseCommand extends Command { constructor(client) { @@ -15,12 +14,12 @@ module.exports = class PauseCommand extends Command { } run(msg) { - const connection = getVoiceConnection(msg.guild.id); + const connection = this.client.dispatchers.get(msg.guild.id); if (!connection) return msg.reply('I am not in a voice channel.'); - if (!this.client.dispatchers.has(msg.guild.id)) { - return msg.reply(`I am not currently playing audio in this server.`); + if (connection.canPlay) { + return msg.reply('I am not currently playing audio in this server.'); } - this.client.dispatchers.get(msg.guild.id).pause(); + connection.pause(); return msg.reply('Paused playing.'); } }; diff --git a/commands/util-voice/resume.js b/commands/util-voice/resume.js index e94bb663..531196d0 100644 --- a/commands/util-voice/resume.js +++ b/commands/util-voice/resume.js @@ -1,5 +1,4 @@ const Command = require('../../framework/Command'); -const { getVoiceConnection } = require('@discordjs/voice'); module.exports = class ResumeCommand extends Command { constructor(client) { @@ -15,12 +14,12 @@ module.exports = class ResumeCommand extends Command { } run(msg) { - const connection = getVoiceConnection(msg.guild.id); + const connection = this.client.dispatchers.get(msg.guild.id); if (!connection) return msg.reply('I am not in a voice channel.'); - if (!this.client.dispatchers.has(msg.guild.id)) { - return msg.reply(`I am not currently playing audio in this server.`); + if (connection.canPlay) { + return msg.reply('I am not currently playing audio in this server.'); } - this.client.dispatchers.get(msg.guild.id).unpause(); + connection.unpause(); return msg.reply('Resumed playing.'); } }; diff --git a/commands/util-voice/stop.js b/commands/util-voice/stop.js index 51ecdf7b..163ce07c 100644 --- a/commands/util-voice/stop.js +++ b/commands/util-voice/stop.js @@ -1,5 +1,4 @@ const Command = require('../../framework/Command'); -const { getVoiceConnection } = require('@discordjs/voice'); module.exports = class StopCommand extends Command { constructor(client) { @@ -15,13 +14,12 @@ module.exports = class StopCommand extends Command { } run(msg) { - const connection = getVoiceConnection(msg.guild.id); + const connection = this.client.dispatchers.get(msg.guild.id); if (!connection) return msg.reply('I am not in a voice channel.'); - if (!this.client.dispatchers.has(msg.guild.id)) { - return msg.reply(`I am not currently playing audio in this server.`); + if (connection.canPlay) { + return msg.reply('I am not currently playing audio in this server.'); } - this.client.dispatchers.get(msg.guild.id).stop(); - this.client.dispatchers.delete(msg.guild.id); + connection.stop(); return msg.reply('Stopped playing.'); } }; diff --git a/structures/Dispatcher.js b/structures/Dispatcher.js new file mode 100644 index 00000000..bd1da7cc --- /dev/null +++ b/structures/Dispatcher.js @@ -0,0 +1,51 @@ +const { getVoiceConnection, createAudioPlayer, createAudioResource, AudioPlayerStatus } = require('@discordjs/voice'); + +module.exports = class VoiceDispatcher { + constructor(channel) { + this.channel = channel; + this.player = createAudioPlayer(); + getVoiceConnection(channel.guild.id).subscribe(this.player); + } + + play(content) { + this.player.stop(); + const resource = createAudioResource(content); + this.player.play(resource); + this.player.once(AudioPlayerStatus.Idle, () => this.stop()); + this.player.once('error', () => this.stop()); + return this.player; + } + + stop() { + return this.player.stop(true); + } + + leave() { + this.client.dispatchers.delete(this.guild.id); + return this.connection.destroy(); + } + + pause() { + return this.player.pause(); + } + + unpause() { + return this.player.unpause(); + } + + get connection() { + return getVoiceConnection(this.guild.id); + } + + get guild() { + return this.channel.guild; + } + + get client() { + return this.channel.client; + } + + get canPlay() { + return this.player.state === AudioPlayerStatus.Idle; + } +};