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); }