diff options
Diffstat (limited to 'src/commands/dev')
-rw-r--r-- | src/commands/dev/eval.ts | 213 | ||||
-rw-r--r-- | src/commands/dev/reload.ts | 10 | ||||
-rw-r--r-- | src/commands/dev/setLevel.ts | 13 |
3 files changed, 170 insertions, 66 deletions
diff --git a/src/commands/dev/eval.ts b/src/commands/dev/eval.ts index bab5f8e..2f1d45d 100644 --- a/src/commands/dev/eval.ts +++ b/src/commands/dev/eval.ts @@ -1,15 +1,16 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ -import { BushCommand } from '../../lib/extensions/BushCommand'; -import { MessageEmbed, Message } from 'discord.js'; -import { inspect, promisify } from 'util'; import { exec } from 'child_process'; +import { Constants } from 'discord-akairo'; +import { Message, MessageEmbed, MessageEmbedOptions, Util } from 'discord.js'; +import { transpile } from 'typescript'; +import { inspect, promisify } from 'util'; +import { BushCommand } from '../../lib/extensions/BushCommand'; const clean = (text) => { - if (typeof text === 'string') - return text.replace(/`/g, '`' + String.fromCharCode(8203)).replace(/@/g, '@' + String.fromCharCode(8203)); - else return text; + if (typeof text === 'string') { + return (text = Util.cleanCodeBlockContent(text)); + } else return text; }; - export default class EvalCommand extends BushCommand { public constructor() { super('eval', { @@ -17,29 +18,54 @@ export default class EvalCommand extends BushCommand { category: 'dev', description: { content: 'Use the command to eval stuff in the bot.', - usage: 'eval <code> [--silent] [--depth #]', + usage: 'eval [--depth #] <code> [--sudo] [--silent] [--delete] [--proto] [--hidden] [--ts]', examples: ['eval message.guild.name', 'eval this.client.ownerID'] }, args: [ { - id: 'depth', - match: 'option', - type: 'number', + id: 'selDepth', + match: Constants.ArgumentMatches.OPTION, + type: Constants.ArgumentTypes.NUMBER, flag: '--depth', default: 0 }, { + id: 'sudo', + match: Constants.ArgumentMatches.FLAG, + flag: '--sudo' + }, + { + id: 'deleteMSG', + match: Constants.ArgumentMatches.FLAG, + flag: '--delete' + }, + { id: 'silent', - match: 'flag', + match: Constants.ArgumentMatches.FLAG, flag: '--silent' }, { + id: 'typescript', + match: Constants.ArgumentMatches.FLAG, + flag: '--ts' + }, + { + id: 'hidden', + match: Constants.ArgumentMatches.FLAG, + flag: '--hidden' + }, + { + id: 'showProto', + match: Constants.ArgumentMatches.FLAG, + flag: '--proto' + }, + { id: 'code', - match: 'rest', - type: 'string', + match: Constants.ArgumentMatches.REST, + type: Constants.ArgumentTypes.STRING, prompt: { start: 'What would you like to eval?', - retry: 'Invalid code to eval. What would you like to eval?' + retry: '{error} Invalid code to eval.' } } ], @@ -48,11 +74,62 @@ export default class EvalCommand extends BushCommand { }); } + private redactCredentials(old: string) { + const mapping = { + ['token']: 'Token', + ['devToken']: 'Dev Token', + ['MongoDB']: 'MongoDB URI', + ['hypixelApiKey']: 'Hypixel Api Key', + ['webhookID']: 'Webhook ID', + ['webhookToken']: 'Webhook Token' + }; + return mapping[old] || old; + } + public async exec( message: Message, - { depth, code, silent }: { depth: number; code: string; silent: boolean } - ): Promise<void> { + { + selDepth, + code: codeArg, + sudo, + silent, + deleteMSG, + typescript, + hidden, + showProto + }: { + selDepth: number; + code: string; + sudo: boolean; + silent: boolean; + deleteMSG: boolean; + typescript: boolean; + hidden: boolean; + showProto: boolean; + } + ): Promise<unknown> { + if (!this.client.config.owners.includes(message.author.id)) + return await message.channel.send(`${this.client.util.emojis.error} Only my developers can run this command.`); + const code: { js?: string | null; ts?: string | null; lang?: 'js' | 'ts' } = {}; + codeArg = codeArg.replace(/[ββ]/g, '"'); + codeArg = codeArg.replace(/```/g, ''); + if (typescript) { + code.ts = codeArg; + code.js = transpile(codeArg); + code.lang = 'ts'; + } else { + code.ts = null; + code.js = codeArg; + code.lang = 'js'; + } + const embed: MessageEmbed = new MessageEmbed(); + const bad_phrases: string[] = ['delete', 'destroy']; + if (bad_phrases.some((p) => code[code.lang].includes(p)) && !sudo) { + return await message.util.send(`${this.client.util.emojis.error} This eval was blocked by smooth brain protectionβ’.`); + } + const embeds: (MessageEmbed | MessageEmbedOptions)[] = [new MessageEmbed()]; + embeds.some((embed) => embed); try { let output; @@ -62,59 +139,85 @@ export default class EvalCommand extends BushCommand { guild = message.guild, channel = message.channel, config = this.client.config, + members = message.guild.members, + roles = message.guild.roles, sh = promisify(exec), models = this.client.db.models, got = require('got'); // eslint-disable-line @typescript-eslint/no-var-requires - output = eval(code); - output = await output; - if (typeof output !== 'string') output = inspect(output, { depth }); - output = output.replace(new RegExp(this.client.token, 'g'), '[token omitted]'); + if (code[code.lang].replace(/ /g, '').includes('9+10' || '10+9')) { + output = 21; + } else { + output = eval(code.js); + output = await output; + } + let proto, outputProto; + if (showProto) { + proto = Object.getPrototypeOf(output); + outputProto = clean(inspect(proto, { depth: 1, getters: true, showHidden: true })); + } + if (typeof output !== 'string') + output = inspect(output, { depth: selDepth, showHidden: hidden, getters: true, showProxy: true }); + for (const credentialName in this.client.config.credentials) { + const credential = this.client.config.credentials[credentialName]; + const newCredential = this.redactCredentials(credentialName); + output = output.replace( + new RegExp(credential.toString().replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'g'), + `[${newCredential} Omitted]` + ); + output = output.replace( + new RegExp([...credential.toString().replace(/[.*+?^${}()|[\]\\]/g, '\\$&')].reverse().join(''), 'g'), + `[${newCredential} Omitted]` + ); + } + output = clean(output); + const inputJS = clean(code.js); + embed - .setTitle('β
Evaled code successfully') - .addField( - 'π₯ Input', - code.length > 1012 - ? 'Too large to display. Hastebin: ' + (await this.client.util.haste(code)) - : '```js\n' + code + '```' - ) - .addField( - 'π€ Output', - output.length > 1012 - ? 'Too large to display. Hastebin: ' + (await this.client.util.haste(output)) - : '```js\n' + output + '```' - ) - .setColor('#66FF00') - .setFooter(message.author.username, message.author.displayAvatarURL({ dynamic: true })) + .setTitle(`${this.client.util.emojis.successFull} Evaled code successfully`) + .setColor(this.client.util.colors.success) + .setFooter(message.author.tag, message.author.displayAvatarURL({ dynamic: true })) .setTimestamp(); + if (code.lang === 'ts') { + const inputTS = clean(code.ts); + embed + .addField('π₯ Input (typescript)', await this.client.util.codeblock(inputTS, 1024, 'ts')) + .addField('π₯ Input (transpiled javascript)', await this.client.util.codeblock(inputJS, 1024, 'js')); + } else { + embed.addField('π₯ Input', await this.client.util.codeblock(inputJS, 1024, 'js')); + } + embed.addField('π€ Output', await this.client.util.codeblock(output, 1024, 'js')); + if (showProto) embed.addField('βοΈ Proto', await this.client.util.codeblock(outputProto, 1024, 'js')); } catch (e) { + const inputJS = clean(code.js); embed - .setTitle('β Code was not able to be evaled') - .addField( - 'π₯ Input', - code.length > 1012 - ? 'Too large to display. Hastebin: ' + (await this.client.util.haste(code)) - : '```js\n' + code + '```' - ) - .addField( - 'π€ Output', - e.length > 1012 - ? 'Too large to display. Hastebin: ' + (await this.client.util.haste(e)) - : '```js\n' + e + '```Full stack:' + (await this.client.util.haste(e.stack)) - ) - .setColor('#FF0000') - .setFooter(message.author.username, message.author.displayAvatarURL({ dynamic: true })) + .setTitle(`${this.client.util.emojis.errorFull} Code was not able to be evaled.`) + .setColor(this.client.util.colors.error) + .setFooter(message.author.tag, message.author.displayAvatarURL({ dynamic: true })) .setTimestamp(); + if (code.lang === 'ts') { + const inputTS = clean(code.ts); + embed + .addField('π₯ Input (typescript)', await this.client.util.codeblock(inputTS, 1024, 'ts')) + .addField('π₯ Input (transpiled javascript)', await this.client.util.codeblock(inputJS, 1024, 'js')); + } else { + embed.addField('π₯ Input', await this.client.util.codeblock(inputJS, 1024, 'js')); + } + embed.addField('π€ Output', await this.client.util.codeblock(e?.stack, 1024, 'js')); } if (!silent) { - await message.util.send(embed); + await message.util.reply({ embeds: [embed] }); } else { try { - await message.author.send(embed); - await message.react('<a:Check_Mark:790373952760971294>'); + await message.author.send({ embeds: [embed] }); + if (!deleteMSG) await message.react(this.client.util.emojis.successFull); } catch (e) { - await message.react('β'); + if (!deleteMSG) await message.react(this.client.util.emojis.errorFull); } } + + if (deleteMSG && message.deletable) { + await message.delete(); + } } } diff --git a/src/commands/dev/reload.ts b/src/commands/dev/reload.ts index 0cf32ce..3194ce2 100644 --- a/src/commands/dev/reload.ts +++ b/src/commands/dev/reload.ts @@ -1,9 +1,9 @@ -import { BushCommand } from '../../lib/extensions/BushCommand'; import { stripIndent } from 'common-tags'; +import { ApplicationCommandOptionType } from 'discord-api-types'; import { Message } from 'discord.js'; -import { CommandInteraction } from 'discord.js'; +import { BushCommand } from '../../lib/extensions/BushCommand'; +import { BushInteractionMessage } from '../../lib/extensions/BushInteractionMessage'; import { SlashCommandOption } from '../../lib/extensions/Util'; -import { ApplicationCommandOptionType } from 'discord-api-types'; export default class ReloadCommand extends BushCommand { constructor() { @@ -55,7 +55,7 @@ export default class ReloadCommand extends BushCommand { await message.util.send(await this.getResponse(fast)); } - public async execSlash(message: CommandInteraction, { fast }: { fast: SlashCommandOption<boolean> }): Promise<void> { - await message.reply(await this.getResponse(fast?.value)); + public async execSlash(message: BushInteractionMessage, { fast }: { fast: SlashCommandOption<boolean> }): Promise<void> { + await message.interaction.reply(await this.getResponse(fast?.value)); } } diff --git a/src/commands/dev/setLevel.ts b/src/commands/dev/setLevel.ts index e57e2f8..7401699 100644 --- a/src/commands/dev/setLevel.ts +++ b/src/commands/dev/setLevel.ts @@ -1,8 +1,7 @@ import { ApplicationCommandOptionType } from 'discord-api-types'; -import { CommandInteraction } from 'discord.js'; -import { User } from 'discord.js'; -import { Message } from 'discord.js'; +import { Message, User } from 'discord.js'; import { BushCommand } from '../../lib/extensions/BushCommand'; +import { BushInteractionMessage } from '../../lib/extensions/BushInteractionMessage'; import { SlashCommandOption } from '../../lib/extensions/Util'; import { Level } from '../../lib/models'; import AllowedMentions from '../../lib/utils/AllowedMentions'; @@ -68,16 +67,18 @@ export default class SetLevelCommand extends BushCommand { } async exec(message: Message, { user, level }: { user: User; level: number }): Promise<void> { - await message.util.send(await this.setLevel(user, level), { + await message.util.send({ + content: await this.setLevel(user, level), allowedMentions: AllowedMentions.none() }); } async execSlash( - message: CommandInteraction, + message: BushInteractionMessage, { user, level }: { user: SlashCommandOption<void>; level: SlashCommandOption<number> } ): Promise<void> { - await message.reply(await this.setLevel(user.user, level.value), { + await message.interaction.reply({ + content: await this.setLevel(user.user, level.value), allowedMentions: AllowedMentions.none() }); } |