diff --git a/README.md b/README.md index bb4381a3..4ab197bd 100644 --- a/README.md +++ b/README.md @@ -132,7 +132,7 @@ in the appropriate channel's topic to use it. ## Commands -Total: 411 +Total: 413 ### Utility: @@ -513,7 +513,6 @@ Total: 411 * **clap:** Sends 👏 text 👏 like 👏 this. * **cow-say:** Makes a cow say your text. * **cursive:** Converts text to cursive. -* **dec-talk:** The world's best Text-to-Speech. * **dvorak:** Converts text to Dvorak encoding. * **embed:** Sends text in an embed. * **emojify:** Converts text to emoji form. @@ -565,9 +564,15 @@ Total: 411 * **tax:** Determines the total cost of something plus tax. * **units:** Converts units to/from other units. -### Other: +### Voice-Based: * **airhorn:** Plays an airhorn sound in a voice channel. +* **dec-talk:** The world's best Text-to-Speech. +* **join:** Joins your voice channel. +* **leave:** Leaves the current voice channel. + +### Other: + * **cleverbot:** Talk to Cleverbot. (Owner-Only) * **phone-book:** Looks up phone-enabled servers. * **phone:** Starts a phone call with a random server. diff --git a/Xiao.js b/Xiao.js index 46378aed..f5925f35 100644 --- a/Xiao.js +++ b/Xiao.js @@ -33,6 +33,7 @@ client.registry ['edit-meme', 'Meme Generators'], ['edit-text', 'Text Manipulation'], ['edit-number', 'Number Manipulation'], + ['voice', 'Voice-Based'], ['other', 'Other'], ['roleplay', 'Roleplay'], ['readme', 'README Generators'] diff --git a/commands/other/airhorn.js b/commands/other/airhorn.js deleted file mode 100644 index 60d46c85..00000000 --- a/commands/other/airhorn.js +++ /dev/null @@ -1,49 +0,0 @@ -const Command = require('../../structures/Command'); -const path = require('path'); -const sounds = require('../../assets/json/airhorn'); - -module.exports = class AirhornCommand extends Command { - constructor(client) { - super(client, { - name: 'airhorn', - group: 'other', - memberName: 'airhorn', - description: 'Plays an airhorn sound in a voice channel.', - guildOnly: true, - throttling: { - usages: 1, - duration: 10 - }, - credit: [ - { - name: 'Discord', - url: 'https://discord.com/', - reason: 'Airhorn Sounds', - reasonURL: 'https://github.com/discord/airhornbot/tree/master/audio' - } - ] - }); - } - - async run(msg) { - const voiceChannel = msg.member.voice.channel; - if (!voiceChannel) return msg.say('Please enter a voice channel first.'); - if (!voiceChannel.permissionsFor(this.client.user).has(['CONNECT', 'SPEAK'])) { - return msg.say('Missing the "Connect" or "Speak" permission for the voice channel.'); - } - if (!voiceChannel.joinable) return msg.say('Your voice channel is not joinable.'); - if (this.client.voice.connections.has(voiceChannel.guild.id)) return msg.say('I am already playing a sound.'); - try { - const connection = await voiceChannel.join(); - const airhorn = sounds[Math.floor(Math.random() * sounds.length)]; - const dispatcher = connection.play(path.join(__dirname, '..', '..', 'assets', 'sounds', 'airhorn', airhorn)); - await msg.react('🔉'); - dispatcher.once('finish', () => voiceChannel.leave()); - dispatcher.once('error', () => voiceChannel.leave()); - return null; - } catch (err) { - voiceChannel.leave(); - throw err; - } - } -}; diff --git a/commands/util/invite.js b/commands/util/invite.js index e3c93c63..d7b3e0f2 100644 --- a/commands/util/invite.js +++ b/commands/util/invite.js @@ -6,7 +6,6 @@ module.exports = class InviteCommand extends Command { constructor(client) { super(client, { name: 'invite', - aliases: ['join'], group: 'util', memberName: 'invite', description: 'Responds with the bot\'s invite links.', diff --git a/commands/voice/airhorn.js b/commands/voice/airhorn.js new file mode 100644 index 00000000..427cb474 --- /dev/null +++ b/commands/voice/airhorn.js @@ -0,0 +1,41 @@ +const Command = require('../../structures/Command'); +const path = require('path'); +const sounds = require('../../assets/json/airhorn'); + +module.exports = class AirhornCommand extends Command { + constructor(client) { + super(client, { + name: 'airhorn', + group: 'voice', + memberName: 'airhorn', + description: 'Plays an airhorn sound in a voice channel.', + guildOnly: true, + throttling: { + usages: 1, + duration: 10 + }, + userPermissions: ['CONNECT', 'SPEAK'], + clientPermissions: ['ADD_REACTIONS', 'READ_MESSAGE_HISTORY'], + credit: [ + { + name: 'Discord', + url: 'https://discord.com/', + reason: 'Airhorn Sounds', + reasonURL: 'https://github.com/discord/airhornbot/tree/master/audio' + } + ] + }); + } + + async run(msg) { + const inGuild = msg.guild ? undefined : null; + const connection = this.client.voice.connections.get(msg.guild.id); + if (!connection) { + return msg.say(`I am not in a voice channel. Use ${msg.anyUsage('join', inGuild, inGuild)} to fix that!.`); + } + const airhorn = sounds[Math.floor(Math.random() * sounds.length)]; + connection.play(path.join(__dirname, '..', '..', 'assets', 'sounds', 'airhorn', airhorn)); + await msg.react('🔉'); + return null; + } +}; diff --git a/commands/edit-text/dec-talk.js b/commands/voice/dec-talk.js similarity index 66% rename from commands/edit-text/dec-talk.js rename to commands/voice/dec-talk.js index 77101033..684cb3ce 100644 --- a/commands/edit-text/dec-talk.js +++ b/commands/voice/dec-talk.js @@ -6,7 +6,7 @@ module.exports = class DECTalkCommand extends Command { super(client, { name: 'dec-talk', aliases: ['text-to-speech', 'tts'], - group: 'edit-text', + group: 'voice', memberName: 'dec-talk', description: 'The world\'s best Text-to-Speech.', guildOnly: true, @@ -47,25 +47,19 @@ module.exports = class DECTalkCommand extends Command { } async run(msg, { text }) { - const voiceChannel = msg.member.voice.channel; - if (!voiceChannel) return msg.say('Please enter a voice channel first.'); - if (!voiceChannel.permissionsFor(this.client.user).has(['CONNECT', 'SPEAK'])) { - return msg.say('Missing the "Connect" or "Speak" permission for the voice channel.'); + const inGuild = msg.guild ? undefined : null; + const connection = this.client.voice.connections.get(msg.guild.id); + if (!connection) { + return msg.say(`I am not in a voice channel. Use ${msg.anyUsage('join', inGuild, inGuild)} to fix that!.`); } - if (!voiceChannel.joinable) return msg.say('Your voice channel is not joinable.'); - if (this.client.voice.connections.has(voiceChannel.guild.id)) return msg.say('I am already playing a sound.'); try { - const connection = await voiceChannel.join(); const { url } = await request .get('http://tts.cyzon.us/tts') .query({ text }); - const dispatcher = connection.play(url); + connection.play(url); await msg.react('🔉'); - dispatcher.once('finish', () => voiceChannel.leave()); - dispatcher.once('error', () => voiceChannel.leave()); return null; } catch (err) { - voiceChannel.leave(); return msg.reply(`Oh no, an error occurred: \`${err.message}\`. Try again later!`); } } diff --git a/commands/voice/join.js b/commands/voice/join.js new file mode 100644 index 00000000..b9dea00b --- /dev/null +++ b/commands/voice/join.js @@ -0,0 +1,27 @@ +const Command = require('../../structures/Command'); + +module.exports = class JoinCommand extends Command { + constructor(client) { + super(client, { + name: 'join', + aliases: ['join-voice-channel', 'join-vc', 'join-voice', 'join-channel'], + group: 'voice', + memberName: 'join', + description: 'Joins your voice channel.', + guarded: true, + userPermissions: ['CONNECT'] + }); + } + + async run(msg) { + const voiceChannel = msg.member.voice.channel; + if (!voiceChannel) return msg.say('Please enter a voice channel first.'); + if (!voiceChannel.permissionsFor(this.client.user).has(['CONNECT', 'SPEAK', 'VIEW_CHANNEL'])) { + return msg.say('I am missing the "Connect", "Speak", or "View Channel" permission for this voice channel.'); + } + if (!voiceChannel.joinable) return msg.say('Your voice channel is not joinable.'); + if (this.client.voice.connections.has(voiceChannel.guild.id)) return msg.say('I am already in a voice channel.'); + await voiceChannel.join(); + return msg.reply(`Joined **${voiceChannel.name}**!`); + } +}; diff --git a/commands/voice/leave.js b/commands/voice/leave.js new file mode 100644 index 00000000..caa31428 --- /dev/null +++ b/commands/voice/leave.js @@ -0,0 +1,22 @@ +const Command = require('../../structures/Command'); + +module.exports = class LeaveCommand extends Command { + constructor(client) { + super(client, { + name: 'leave', + aliases: ['leave-voice-channel', 'leave-vc', 'leave-voice', 'leave-channel'], + group: 'voice', + memberName: 'leave', + description: 'Leaves the current voice channel.', + guarded: true, + userPermissions: ['MOVE_MEMBERS'] + }); + } + + run(msg) { + const connection = this.client.voice.connections.get(msg.guild.id); + if (!connection) return msg.say('I am not in a voice channel.'); + connection.channel.leave(); + return msg.reply(`Left **${connection.channel.name}**...`); + } +}; diff --git a/package.json b/package.json index c6827a09..22acadd6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "xiao", - "version": "114.4.0", + "version": "114.5.0", "description": "Your personal server companion.", "main": "Xiao.js", "scripts": {