From 7b389ce679d070410dfb62bd1f30f037cd82c4ae Mon Sep 17 00:00:00 2001 From: Dragon Fire Date: Fri, 12 Feb 2021 18:10:44 -0500 Subject: [PATCH] Better voice management --- commands/music/play.js | 10 ++++------ commands/util-public/leave.js | 4 ++++ commands/util-public/stop.js | 28 ++++++++++++++++++++++++++++ commands/voice/airhorn.js | 6 +++++- commands/voice/dec-talk.js | 6 +++++- commands/voice/soundboard.js | 6 +++++- commands/voice/vocodes.js | 6 +++++- structures/Client.js | 1 + 8 files changed, 57 insertions(+), 10 deletions(-) create mode 100644 commands/util-public/stop.js diff --git a/commands/music/play.js b/commands/music/play.js index 832f17c8..95c36877 100644 --- a/commands/music/play.js +++ b/commands/music/play.js @@ -34,8 +34,6 @@ module.exports = class PlayCommand extends Command { } ] }); - - this.dispatchers = new Map(); } async run(msg, { query }) { @@ -44,15 +42,15 @@ module.exports = class PlayCommand extends Command { const usage = this.client.registry.commands.get('join').usage(); return msg.reply(`I am not in a voice channel. Use ${usage} to fix that!`); } - if (this.dispatchers.has(msg.guild.id)) return msg.reply('I am already playing music in this server.'); + if (this.client.dispatchers.has(msg.guild.id)) return msg.reply('I am already playing audio in this server.'); const result = await this.searchForVideo(query, msg.channel.nsfw || false); if (!result) return msg.say('Could not find any results for your query.'); const canPlay = await this.canUseVideo(result, msg.channel.nsfw || false); if (!canPlay) return msg.say('I cannot play this video.'); const dispatcher = connection.play(ytdl(result, { filter: 'audioonly', quality: 'lowest' })); - this.dispatchers.set(msg.guild.id, dispatcher); - dispatcher.once('finish', () => this.dispatchers.delete(msg.guild.id)); - dispatcher.once('error', () => this.dispatchers.delete(msg.guild.id)); + this.client.dispatchers.set(msg.guild.id, dispatcher); + dispatcher.once('finish', () => this.client.dispatchers.delete(msg.guild.id)); + dispatcher.once('error', () => this.client.dispatchers.delete(msg.guild.id)); await reactIfAble(msg, this.client.user, '🔉'); return null; } diff --git a/commands/util-public/leave.js b/commands/util-public/leave.js index 99a2471b..c9e8ac14 100644 --- a/commands/util-public/leave.js +++ b/commands/util-public/leave.js @@ -19,6 +19,10 @@ module.exports = class LeaveCommand extends Command { if (!msg.channel.permissionsFor(msg.author).has('MOVE_MEMBERS') && connection.channel.members.size > 2) { return msg.reply('You need the "Move members" permission to remove me from this voice channel.'); } + if (this.client.dispatchers.has(msg.guild.id)) { + 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.channel.leave(); return msg.reply(`Left **${connection.channel.name}**...`); } diff --git a/commands/util-public/stop.js b/commands/util-public/stop.js new file mode 100644 index 00000000..934b4e20 --- /dev/null +++ b/commands/util-public/stop.js @@ -0,0 +1,28 @@ +const Command = require('../../structures/Command'); + +module.exports = class StopCommand extends Command { + constructor(client) { + super(client, { + name: 'stop', + aliases: ['stop-voice-channel', 'stop-vc', 'stop-voice', 'stop-play', 'stop-playing'], + group: 'util-public', + memberName: 'stop', + description: 'Stops the current audio playing.', + guildOnly: true, + guarded: true + }); + } + + run(msg) { + const connection = this.client.voice.connections.get(msg.guild.id); + if (!connection) return msg.reply('I am not in a voice channel.'); + if (!msg.channel.permissionsFor(msg.author).has('MOVE_MEMBERS') && connection.channel.members.size > 2) { + return msg.reply('You need the "Move members" permission to stop playing audio.'); + } + if (!this.client.dispatchers.has(msg.guild.id)) { + return msg.reply(`I am not currently playing audio in this server.`); + } + this.client.dispatchers.get(msg.guild.id).end(); + return msg.reply('Stopped playing.'); + } +}; diff --git a/commands/voice/airhorn.js b/commands/voice/airhorn.js index 1a7ba764..b2f10d42 100644 --- a/commands/voice/airhorn.js +++ b/commands/voice/airhorn.js @@ -34,8 +34,12 @@ module.exports = class AirhornCommand extends Command { const usage = this.client.registry.commands.get('join').usage(); return msg.reply(`I am not in a voice channel. Use ${usage} to fix that!`); } + if (this.client.dispatchers.has(msg.guild.id)) return msg.reply('I am already playing audio in this server.'); const airhorn = sounds[Math.floor(Math.random() * sounds.length)]; - connection.play(path.join(__dirname, '..', '..', 'assets', 'sounds', 'airhorn', airhorn)); + const dispatcher = connection.play(path.join(__dirname, '..', '..', 'assets', 'sounds', 'airhorn', airhorn)); + this.client.dispatchers.set(msg.guild.id, dispatcher); + dispatcher.once('finish', () => this.client.dispatchers.delete(msg.guild.id)); + dispatcher.once('error', () => this.client.dispatchers.delete(msg.guild.id)); await reactIfAble(msg, this.client.user, '🔉'); return null; } diff --git a/commands/voice/dec-talk.js b/commands/voice/dec-talk.js index 6611ae56..ea0b32c7 100644 --- a/commands/voice/dec-talk.js +++ b/commands/voice/dec-talk.js @@ -54,12 +54,16 @@ module.exports = class DECTalkCommand extends Command { const usage = this.client.registry.commands.get('join').usage(); return msg.reply(`I am not in a voice channel. Use ${usage} to fix that!`); } + if (this.client.dispatchers.has(msg.guild.id)) return msg.reply('I am already playing audio in this server.'); try { await reactIfAble(msg, this.client.user, LOADING_EMOJI_ID, '💬'); const { body } = await request .get('http://tts.cyzon.us/tts') .query({ text }); - connection.play(Readable.from([body])); + const dispatcher = connection.play(Readable.from([body])); + this.client.dispatchers.set(msg.guild.id, dispatcher); + dispatcher.once('finish', () => this.client.dispatchers.delete(msg.guild.id)); + dispatcher.once('error', () => this.client.dispatchers.delete(msg.guild.id)); await reactIfAble(msg, this.client.user, '🔉'); return null; } catch (err) { diff --git a/commands/voice/soundboard.js b/commands/voice/soundboard.js index 1306fb1b..ee529d12 100644 --- a/commands/voice/soundboard.js +++ b/commands/voice/soundboard.js @@ -128,7 +128,11 @@ module.exports = class SoundboardCommand extends Command { const usage = this.client.registry.commands.get('join').usage(); return msg.reply(`I am not in a voice channel. Use ${usage} to fix that!`); } - connection.play(path.join(__dirname, '..', '..', 'assets', 'sounds', ...sound)); + if (this.client.dispatchers.has(msg.guild.id)) return msg.reply('I am already playing audio in this server.'); + const dispatcher = connection.play(path.join(__dirname, '..', '..', 'assets', 'sounds', ...sound)); + this.client.dispatchers.set(msg.guild.id, dispatcher); + dispatcher.once('finish', () => this.client.dispatchers.delete(msg.guild.id)); + dispatcher.once('error', () => this.client.dispatchers.delete(msg.guild.id)); await reactIfAble(msg, this.client.user, '🔉'); return null; } diff --git a/commands/voice/vocodes.js b/commands/voice/vocodes.js index 2203207c..42f66e26 100644 --- a/commands/voice/vocodes.js +++ b/commands/voice/vocodes.js @@ -51,6 +51,7 @@ module.exports = class VocodesCommand extends Command { const usage = this.client.registry.commands.get('join').usage(); return msg.reply(`I am not in a voice channel. Use ${usage} to fix that!`); } + if (this.client.dispatchers.has(msg.guild.id)) return msg.reply('I am already playing audio in this server.'); try { await reactIfAble(msg, this.client.user, LOADING_EMOJI_ID, '💬'); const { body } = await request @@ -59,7 +60,10 @@ module.exports = class VocodesCommand extends Command { speaker: voice, text }); - connection.play(Readable.from([Buffer.from(body.audio_base64, 'base64')])); + const dispatcher = connection.play(Readable.from([Buffer.from(body.audio_base64, 'base64')])); + this.client.dispatchers.set(msg.guild.id, dispatcher); + dispatcher.once('finish', () => this.client.dispatchers.delete(msg.guild.id)); + dispatcher.once('error', () => this.client.dispatchers.delete(msg.guild.id)); await reactIfAble(msg, this.client.user, '🔉'); return null; } catch (err) { diff --git a/structures/Client.js b/structures/Client.js index 6ebc1bf9..9a8d6b75 100644 --- a/structures/Client.js +++ b/structures/Client.js @@ -43,6 +43,7 @@ module.exports = class XiaoClient extends CommandoClient { disableMentions: 'everyone' }) : null; this.games = new Collection(); + this.dispatchers = new Map(); this.phone = new Collection(); this.activities = activities; this.leaveMessages = leaveMsgs;