aboutsummaryrefslogtreecommitdiff
path: root/src/commands/dev
diff options
context:
space:
mode:
Diffstat (limited to 'src/commands/dev')
-rw-r--r--src/commands/dev/eval.ts213
-rw-r--r--src/commands/dev/reload.ts10
-rw-r--r--src/commands/dev/setLevel.ts13
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()
});
}