revolt-bot/commands/eval.js

124 lines
4.8 KiB
JavaScript

const Revolt = require('revolt.js');
const { client, logger, config } = require('..');
const { exec } = require('child_process');
let evalEnabled = [];
let OTP = [];
let OTPTimer = [];
module.exports = {
OTP, evalEnabled, OTPTimer
}
module.exports.meta = {
name: 'eval',
aliases: [],
description: 'Evaluate code.',
devLevel: 99
}
/**
*
* @param { Revolt.Message } message
* @param { string[] } args
*/
module.exports.run = async (message, args) => new Promise(async (resolve, reject) => {
if (!evalEnabled[message.author] && process.env['DISABLE_EVAL_OTP'] != 'true') {
OTP[message.author] = createOTP();
client.channels.sendMessage(message.channel, `OTP has been printed to console. Use \`${config.prefix}verify [code]\` to verify.`);
console.log(`Admin authentication required`);
console.log(`OTP: \u001b[31;1m${OTP[message.author]}\u001b[0m`);
console.log(`Code expires in 120 seconds.`);
if (OTPTimer[message.author]) {
console.log('Old OTP code has been invalidated.');
clearTimeout(OTPTimer[message.author]);
}
OTPTimer[message.author] = setTimeout(() => {
console.log(`OTP Code \u001b[31;1m${OTP[message.author]}\u001b[0m has been invalidated.`);
OTP[message.author] = null;
}, 120000);
return;
}
let command = args.join(' ');
if (command.length == 0) return client.channels.sendMessage(message.channel, `❌ No command provided`);
if (command.startsWith('js:')) {
// Execute javascript
command = command.substring(3);
if (command.length == 0) return client.channels.sendMessage(message.channel, `❌ No command provided`);
let mesg = await client.channels.sendMessage(message.channel, `Evaluating JavaScript...`);
let parseOutput = (output) => {
if (output instanceof Error) return `${output.name || 'Error'} : ${output.message}`;
if (output instanceof Object) return `${JSON.stringify(output, null, 4)}`;
return `${output}`;
}
try {
let output = eval(command);
if (output instanceof Promise) {
client.channels.editMessage(message.channel, mesg._id, { content: `\`\`\`js\nPromise : Pending\n\`\`\`` });
output
.then(val => {
client.channels.editMessage(message.channel, mesg._id, { content: `\`\`\`js\nPromise : Resolved\n${parseOutput(val)}\n\`\`\`` });
})
.catch(val => {
client.channels.editMessage(message.channel, mesg._id, { content: `\`\`\`js\nPromise : Rejected\n${parseOutput(val)}\n\`\`\`` });
});
} else {
client.channels.editMessage(message.channel, mesg._id, { content: `\`\`\`js\n${parseOutput(output)}\n\`\`\`` });
}
} catch(e) {
client.channels.editMessage(message.channel, mesg._id, { content: `\`\`\`js\n${parseOutput(e)}\n\`\`\`` });
}
} else {
let mesg = await client.channels.sendMessage(message.channel, `Executing: \`${command}\``);
let outTxt = '';
let cOutTxt = '';
let prevTxt = '';
let cutLetters = 0;
let exited = false;
let updateMsg = (msg, exitCode) => {
outTxt += `${msg}`
.replace(/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g, '')
.replace(/`/g, '\u200b`');
while (outTxt.length >= 1920) {
outTxt = outTxt.slice(2, outTxt.length);
cutLetters++;
}
let charCutTxt = '';
if (cutLetters > 0) charCutTxt = `${cutLetters} character${cutLetters == 1 ? ' has' : 's have'} been cut\n`;
let exitText = '';
if (exitCode != null) {
exitText = `\nExited with code ${exitCode}`;
exited = true;
}
cOutTxt = `${charCutTxt}\`\`\`bash\n${outTxt.trimRight() || 'No output'}\n\`\`\`${exitText}`;
}
let execution = exec(command);
execution.stdout.on('data', updateMsg);
execution.stderr.on('data', updateMsg);
execution.once('exit', (exitCode) => {
updateMsg('', exitCode);
});
let interval = setInterval(() => {
if (cOutTxt != prevTxt) {
prevTxt = cOutTxt;
client.channels.editMessage(message.channel, mesg._id, { content: cOutTxt });
}
}, 200);
}
});
// $\color{red}\text{h}$
function createOTP() {
let code = '';
for (let i = 0; i < 6; i++) code += Math.round(Math.random() * 10);
return code.substr(0, 6);
}