diff --git a/assets/json/horoscope.json b/assets/json/horoscope.json deleted file mode 100644 index 5f58712a..00000000 --- a/assets/json/horoscope.json +++ /dev/null @@ -1,14 +0,0 @@ -[ - "capricorn", - "aquarius", - "pisces", - "aries", - "taurus", - "gemini", - "cancer", - "leo", - "virgo", - "libra", - "scorpio", - "sagittarius" -] diff --git a/assets/json/permissions.json b/assets/json/permissions.json deleted file mode 100644 index d21b9e8d..00000000 --- a/assets/json/permissions.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "ADMINISTRATOR": "Administrator", - "VIEW_AUDIT_LOG": "View Audit Log", - "MANAGE_GUILD": "Manage Server", - "MANAGE_ROLES": "Manage Roles", - "MANAGE_CHANNELS": "Manage Channels", - "KICK_MEMBERS": "Kick Members", - "BAN_MEMBERS": "Ban Members", - "CREATE_INSTANT_INVITE": "Create Instant Invite", - "CHANGE_NICKNAME": "Change Nickname", - "MANAGE_NICKNAMES": "Manage Nicknames", - "MANAGE_EMOJIS": "Manage Emojis", - "MANAGE_WEBHOOKS": "Manage Webhooks", - "VIEW_CHANNEL": "Read Text Channels and See Voice Channels", - "SEND_MESSAGES": "Send Messages", - "SEND_TTS_MESSAGES": "Send TTS Messages", - "MANAGE_MESSAGES": "Manage Messages", - "EMBED_LINKS": "Embed Links", - "ATTACH_FILES": "Attach Files", - "READ_MESSAGE_HISTORY": "Read Message History", - "MENTION_EVERYONE": "Mention Everyone", - "USE_EXTERNAL_EMOJIS": "Use External Emojis", - "ADD_REACTIONS": "Add Reactions", - "CONNECT": "Connect", - "SPEAK": "Speak", - "MUTE_MEMBERS": "Mute Members", - "DEAFEN_MEMBERS": "Deafen Members", - "MOVE_MEMBERS": "Move Members", - "USE_VAD": "Use Voice Activity" -} diff --git a/commands/games/math-game.js b/commands/games/math-game.js index ab4c6ea7..5d64c1b8 100644 --- a/commands/games/math-game.js +++ b/commands/games/math-game.js @@ -1,5 +1,5 @@ const Command = require('../../structures/Command'); -const { MessageEmbed } = require('discord.js'); +const { stripIndents } = require('common-tags'); const { list } = require('../../structures/Util'); const difficulties = ['easy', 'medium', 'hard', 'extreme', 'impossible']; const operations = ['addition', 'subtraction', 'multiplication', 'division']; @@ -59,11 +59,10 @@ module.exports = class MathGameCommand extends Command { else if (operation === 'subtraction') answer = value1 - value2; else if (operation === 'multiplication') answer = value1 * value2; else if (operation === 'division') answer = value1 / value2; - const embed = new MessageEmbed() - .setTitle('You have 10 seconds to answer:') - .setColor(0x9797FF) - .setDescription(`${value1} ${operationDisplay[operation]} ${value2}`); - await msg.embed(embed); + await msg.say(stripIndents` + **You have 10 seconds to answer this question.** + ${value1} ${operationDisplay[operation]} ${value2} + `); const msgs = await msg.channel.awaitMessages(res => res.author.id === msg.author.id, { max: 1, time: 10000 diff --git a/commands/games/quiz.js b/commands/games/quiz.js index 3b9c9d2e..4bd3cca5 100644 --- a/commands/games/quiz.js +++ b/commands/games/quiz.js @@ -1,5 +1,4 @@ const Command = require('../../structures/Command'); -const { MessageEmbed } = require('discord.js'); const { stripIndents } = require('common-tags'); const snekfetch = require('snekfetch'); const { shuffle, list } = require('../../structures/Util'); @@ -56,15 +55,12 @@ module.exports = class QuizCommand extends Command { const answers = body.results[0].incorrect_answers.map(answer => decodeURIComponent(answer.toLowerCase())); const correct = decodeURIComponent(body.results[0].correct_answer.toLowerCase()); answers.push(correct); - const embed = new MessageEmbed() - .setTitle('You have 15 seconds to answer this question:') - .setColor(0x9797FF) - .setDescription(stripIndents` - **${decodeURIComponent(body.results[0].category)}** - ${type === 'boolean' ? '**True or False:** ' : ''}${decodeURIComponent(body.results[0].question)} - ${type === 'multiple' ? `**Choices:** ${list(shuffle(answers), 'or')}` : ''} - `); - await msg.embed(embed); + await msg.say(stripIndents` + **You have 15 seconds to answer this question.** + _${decodeURIComponent(body.results[0].category)}:_ ${decodeURIComponent(body.results[0].question)} + + ${type === 'boolean' ? 'True or False?' : ''}${type === 'multiple' ? list(shuffle(answers), 'or') : ''} + `); const msgs = await msg.channel.awaitMessages(res => res.author.id === msg.author.id, { max: 1, time: 15000 diff --git a/commands/games/typing-game.js b/commands/games/typing-game.js index 9c34174c..0e2ef9d1 100644 --- a/commands/games/typing-game.js +++ b/commands/games/typing-game.js @@ -1,5 +1,5 @@ const Command = require('../../structures/Command'); -const { MessageEmbed } = require('discord.js'); +const { stripIndents } = require('common-tags'); const { list } = require('../../structures/Util'); const difficulties = ['easy', 'medium', 'hard', 'extreme', 'impossible']; const times = { @@ -38,11 +38,10 @@ module.exports = class TypingGameCommand extends Command { const { difficulty } = args; const sentence = sentences[Math.floor(Math.random() * sentences.length)]; const time = times[difficulty]; - const embed = new MessageEmbed() - .setTitle(`You have ${time / 1000} seconds to type:`) - .setColor(0x9797FF) - .setDescription(sentence); - await msg.embed(embed); + await msg.say(stripIndents` + **You have ${time / 1000} seconds to type this sentence.** + ${sentence} + `); const msgs = await msg.channel.awaitMessages(res => res.author.id === msg.author.id, { max: 1, time diff --git a/commands/guild-info/emoji.js b/commands/guild-info/emoji.js deleted file mode 100644 index c8eb39c6..00000000 --- a/commands/guild-info/emoji.js +++ /dev/null @@ -1,18 +0,0 @@ -const Command = require('../../structures/Command'); - -module.exports = class EmojiCommand extends Command { - constructor(client) { - super(client, { - name: 'emoji', - group: 'guild-info', - memberName: 'emoji', - description: 'Responds with a list of the server\'s custom emoji.', - guildOnly: true - }); - } - - run(msg) { - if (!msg.guild.emojis.size) return msg.say('This server has no custom emoji.'); - return msg.say(msg.guild.emojis.map(e => e).join('')); - } -}; diff --git a/commands/guild-info/role-info.js b/commands/guild-info/role-info.js index 17a9517f..8cb7e559 100644 --- a/commands/guild-info/role-info.js +++ b/commands/guild-info/role-info.js @@ -1,6 +1,6 @@ const Command = require('../../structures/Command'); const { MessageEmbed } = require('discord.js'); -const perms = require('../../assets/json/permissions'); +const { util } = require('discord.js-commando'); module.exports = class RoleInfoCommand extends Command { constructor(client) { @@ -39,9 +39,9 @@ module.exports = class RoleInfoCommand extends Command { .addField('❯ Mentionable', role.mentionable ? 'Yes' : 'No', true) .addField('❯ Permissions', - Object.keys(perms) + Object.keys(util.permissions) .filter(perm => role.serialize()[perm]) - .map(perm => perms[perm]) + .map(perm => util.permissions[perm]) .join(', ')); return msg.embed(embed); } diff --git a/commands/image-edit/meme.js b/commands/image-edit/meme.js index 1bb61bca..3fdf0ca3 100644 --- a/commands/image-edit/meme.js +++ b/commands/image-edit/meme.js @@ -52,7 +52,7 @@ module.exports = class MemeCommand extends Command { try { const { body } = await snekfetch .get(`https://memegen.link/api/templates/${type}/${top}/${bottom}`); - return msg.say({ files: [body.direct.visible] }); + return msg.say(body.direct.masked); } catch (err) { return msg.say(`Oh no, an error occurred: \`${err.message}\`. Try again later!`); } diff --git a/commands/random-res/would-you-rather.js b/commands/random-res/would-you-rather.js index 25a3a83b..1a12bdde 100644 --- a/commands/random-res/would-you-rather.js +++ b/commands/random-res/would-you-rather.js @@ -1,6 +1,6 @@ const Command = require('../../structures/Command'); -const { MessageEmbed } = require('discord.js'); const snekfetch = require('snekfetch'); +const { stripIndents } = require('common-tags'); module.exports = class WouldYouRatherCommand extends Command { constructor(client) { @@ -18,12 +18,10 @@ module.exports = class WouldYouRatherCommand extends Command { try { const { body } = await snekfetch .get('http://www.rrrather.com/botapi'); - const embed = new MessageEmbed() - .setTitle(`${body.title}...`) - .setURL(body.link) - .setColor(0x9797FF) - .setDescription(`${body.choicea} OR ${body.choiceb}?`); - return msg.embed(embed); + return msg.say(stripIndents` + ${body.title}... + ${body.choicea} OR ${body.choiceb}? + `); } catch (err) { return msg.say(`Oh no, an error occurred: \`${err.message}\`. Try again later!`); } diff --git a/commands/random-res/today.js b/commands/random/history.js similarity index 77% rename from commands/random-res/today.js rename to commands/random/history.js index f77b05dc..a4cece3b 100644 --- a/commands/random-res/today.js +++ b/commands/random/history.js @@ -2,13 +2,13 @@ const Command = require('../../structures/Command'); const { MessageEmbed } = require('discord.js'); const snekfetch = require('snekfetch'); -module.exports = class TodayCommand extends Command { +module.exports = class HistoryCommand extends Command { constructor(client) { super(client, { - name: 'today', - aliases: ['event', 'history'], + name: 'history', + aliases: ['event', 'today'], group: 'random-res', - memberName: 'today', + memberName: 'history', description: 'Responds with an event that occurred today in history, or on a specific day.', clientPermissions: ['EMBED_LINKS'], args: [ @@ -35,10 +35,12 @@ module.exports = class TodayCommand extends Command { .setURL(body.url) .setTitle(`On this day (${body.date})...`) .setTimestamp() - .setDescription(`${event.year}: ${event.text}`); + .setDescription(`${event.year}: ${event.text}`) + .addField('❯ See More', + event.links.map(link => `${link.title}: ${link.link.replace(/\)/g, '%29')}`).join('\n')); return msg.embed(embed); } catch (err) { - if (err.status === 404 || err.status === 500) return msg.say('Invalid date.'); + if (err.status === 404 || err.status === 500) return msg.say('Could not find any results.'); return msg.say(`Oh no, an error occurred: \`${err.message}\`. Try again later!`); } } diff --git a/commands/random/horoscope.js b/commands/random/horoscope.js index ccd8a8c9..1e75760e 100644 --- a/commands/random/horoscope.js +++ b/commands/random/horoscope.js @@ -2,7 +2,20 @@ const Command = require('../../structures/Command'); const { MessageEmbed } = require('discord.js'); const snekfetch = require('snekfetch'); const { list } = require('../../structures/Util'); -const signs = require('../../assets/json/horoscope'); +const signs = [ + 'capricorn', + 'aquarius', + 'pisces', + 'aries', + 'taurus', + 'gemini', + 'cancer', + 'leo', + 'virgo', + 'libra', + 'scorpio', + 'sagittarius' +]; module.exports = class HoroscopeCommand extends Command { constructor(client) { diff --git a/commands/random/soundboard.js b/commands/random/soundboard.js index 82a52fa8..47e1049d 100644 --- a/commands/random/soundboard.js +++ b/commands/random/soundboard.js @@ -23,6 +23,7 @@ module.exports = class SoundboardCommand extends Command { key: 'sound', prompt: `What sound would you like to play? Either ${list(sounds, 'or')}.`, type: 'string', + default: sounds[Math.floor(Math.random() * sounds.length)], validate: sound => { if (sounds.includes(sound.toLowerCase())) return true; return `Invalid sound, please enter either ${list(sounds, 'or')}.`; @@ -36,9 +37,9 @@ module.exports = class SoundboardCommand extends Command { async run(msg, args) { const { sound } = args; const channel = msg.member.voiceChannel; - if (!channel) return msg.say('Please enter a Voice Channel first.'); + if (!channel) return msg.say('Please enter a voice channel first.'); if (!channel.permissionsFor(this.client.user).has(['CONNECT', 'SPEAK'])) { - return msg.say('Missing the `Connect` or `Speak` Permission for the Voice Channel.'); + return msg.say('Missing the "Connect" or "Speak" permission for the voice channel.'); } if (!channel.joinable) return msg.say('Your Voice Channel is not joinable.'); if (this.client.voiceConnections.has(channel.guild.id)) return msg.say('I am already playing a sound.'); diff --git a/commands/random/stocks.js b/commands/random/stocks.js index c67d44b1..6d25520c 100644 --- a/commands/random/stocks.js +++ b/commands/random/stocks.js @@ -34,7 +34,7 @@ module.exports = class StocksCommand extends Command { if (body['Error Message']) return msg.say('Could not find any results.'); const data = Object.values(body['Time Series (1min)'])[0]; const embed = new MessageEmbed() - .setTitle(`Stocks for Symbol ${symbol}`) + .setTitle(`Stocks for Symbol ${symbol.toUpperCase()}`) .setColor(0x9797FF) .addField('❯ Open', `$${data['1. open']}`, true) @@ -47,7 +47,7 @@ module.exports = class StocksCommand extends Command { .addField('❯ Low', `$${data['3. low']}`, true) .addField('❯ Last Updated', - new Date(body['Meta Data']['Last Refreshed']).toDateString(), true); + new Date(body['Meta Data']['3. Last Refreshed']).toDateString(), true); return msg.embed(embed); } catch (err) { return msg.say(`Oh no, an error occurred: \`${err.message}\`. Try again later!`); diff --git a/commands/search/discrim.js b/commands/search/discrim.js index 4c9faad6..235c68d4 100644 --- a/commands/search/discrim.js +++ b/commands/search/discrim.js @@ -1,5 +1,5 @@ const Command = require('../../structures/Command'); -const { MessageEmbed } = require('discord.js'); +const { stripIndents } = require('common-tags'); module.exports = class DiscrimCommand extends Command { constructor(client) { @@ -28,10 +28,9 @@ module.exports = class DiscrimCommand extends Command { run(msg, args) { const discrim = args.discrim || msg.author.discriminator; const users = this.client.users.filter(user => user.discriminator === discrim).map(user => user.username); - const embed = new MessageEmbed() - .setTitle(`${users.length} Users with the discriminator #${discrim}`) - .setColor(0x9797FF) - .setDescription(users.join(', ')); - return msg.embed(embed); + return msg.say(stripIndents` + **Found ${users.length} users with the discriminator #${discrim}** + ${users.join(', ')} + `); } }; diff --git a/commands/text-edit/say.js b/commands/text-edit/say.js index d5f48a0e..43643f63 100644 --- a/commands/text-edit/say.js +++ b/commands/text-edit/say.js @@ -20,7 +20,9 @@ module.exports = class SayCommand extends Command { async run(msg, args) { const { text } = args; - if (msg.guild && msg.channel.permissionsFor(this.client.user).has('MANAGE_MESSAGES')) await msg.delete(); + if (msg.channel.type === 'text' && msg.channel.permissionsFor(this.client.user).has('MANAGE_MESSAGES')) { + await msg.delete(); + } return msg.say(text); } }; diff --git a/commands/text-edit/translate.js b/commands/text-edit/translate.js index ce47ecd2..05657615 100644 --- a/commands/text-edit/translate.js +++ b/commands/text-edit/translate.js @@ -29,10 +29,13 @@ module.exports = class TranslateCommand extends Command { prompt: `Which language would you like to translate to? Either ${list(Object.keys(codes), 'or')}.`, type: 'string', validate: target => { - if (codes[target.toLowerCase()]) return true; + if (codes[target.toLowerCase()] || Object.values(codes).includes(target)) return true; return `Invalid target, please enter either ${list(Object.keys(codes), 'or')}.`; }, - parse: target => target.toLowerCase() + parse: target => { + if (codes[target.toLowerCase()]) return target.toLowerCase(); + return Object.keys(codes).find(key => codes[key] === target); + } }, { key: 'original', @@ -40,10 +43,13 @@ module.exports = class TranslateCommand extends Command { type: 'string', default: '', validate: original => { - if (codes[original.toLowerCase()]) return true; + if (codes[original.toLowerCase()] || Object.values(codes).includes(original)) return true; return `Invalid original, please enter either ${list(Object.keys(codes), 'or')}.`; }, - parse: original => original.toLowerCase() + parse: original => { + if (codes[original.toLowerCase()]) return original.toLowerCase(); + return Object.keys(codes).find(key => codes[key] === original); + } } ] }); diff --git a/commands/text-edit/webhook.js b/commands/text-edit/webhook.js index 790beef1..1340d559 100644 --- a/commands/text-edit/webhook.js +++ b/commands/text-edit/webhook.js @@ -23,7 +23,9 @@ module.exports = class WebhookCommand extends Command { async run(msg, args) { const { content } = args; - if (msg.guild && msg.channel.permissionsFor(this.client.user).has('MANAGE_MESSAGES')) await msg.delete(); + if (msg.channel.type === 'text' && msg.channel.permissionsFor(this.client.user).has('MANAGE_MESSAGES')) { + await msg.delete(); + } try { await snekfetch .post(WEBHOOK_URL) diff --git a/package.json b/package.json index 4776668c..1c8c8418 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "xiaobot", - "version": "35.3.0", + "version": "36.0.0", "description": "Your personal server companion.", "main": "Shard.js", "scripts": { diff --git a/structures/Util.js b/structures/Util.js index ebd5239f..63c3dba8 100644 --- a/structures/Util.js +++ b/structures/Util.js @@ -51,7 +51,8 @@ class Util { return promisify(setTimeout)(time); } - static shuffle(arr) { + static shuffle(array) { + const arr = array.slice(0); for (let i = arr.length - 1; i >= 0; i--) { const j = Math.floor(Math.random() * (i + 1)); const temp = arr[i];