const Command = require("../lib/command.js"); const CATEGORY = "bot"; const logger = require("../lib/logger.js"); const child_process = require("child_process"); const {inspect} = require("util"); const {resolve} = require("path"); const {hastebin} = require("../lib/utils.js"); const guildSettings = require("../lib/guildSettings.js"); function spawn(args) { const shell = process.env.SHELL || (process.platform == "win32" ? "powershell" : "sh"); const newArgs = []; if (shell.match(/powershell/i) && process.platform == "win32") { newArgs.push("-NoLogo", "-Command"); } else { newArgs.push("-c"); } newArgs.push(args); const proc = child_process.spawn(shell, newArgs, { cwd: resolve(__dirname, "..", ".."), }); return { pid: proc.pid, stdout: { on: (event, handler) => proc.stdout.on(event, (data) => { handler(data.toString("utf8")); }), }, stderr: { on: (event, handler) => proc.stderr.on(event, (data) => { handler(data.toString("utf8")); }), }, on: (event, handler) => proc.on(event, handler), }; } const reload = new Command("reload"); reload.ownerOnly = true; reload.category = CATEGORY; reload.helpText = "Reloads a module."; reload.callback = function (msg, line) { try { require.resolve(`./${line}.js`); } catch (err) { if (err.code == "MODULE_NOT_FOUND") { return "Module not found."; } else { return `:warning: An error occurred: \`\`\`\n${err}\`\`\``; } } try { logger.info("hf:modules", `Reloading module: '${line}'`); delete require.cache[require.resolve(`./${line}.js`)]; require(`./${line}.js`); return {reaction: "\uD83D\uDC4C"}; } catch (err) { return `:warning: An error occurred: \`\`\`\n${err}\`\`\``; } }; hf.registerCommand(reload); const restart = new Command("restart"); restart.ownerOnly = true; restart.category = CATEGORY; restart.helpText = "Restarts the bot."; restart.callback = function () { setTimeout(process.exit, 500); return {reaction: "\uD83D\uDD04"}; }; hf.registerCommand(restart); const _eval = new Command("eval"); _eval.elevatedOnly = true; _eval.category = CATEGORY; _eval.helpText = "Evalueates Javascript"; _eval.callback = async function (msg, line) { let errored = false; let out; try { out = eval(line); if (out && out instanceof Promise) out = await out; } catch (err) { out = err.toString(); errored = true; } out = errored ? out : inspect(out, {depth: 0}); const token = hf.config.token; out = out.replace( new RegExp(token.replace(/\./g, "\\."), "g"), "lol no key 4 u" ); if (errored) { return ":warning: Output (errored):\n```js\n" + out + "\n```"; } else { if (out.toString().length > 1980) { const haste = await hastebin(out.toString()); return `\u2705 Output too long to send in a message: ${haste}`; } else { return "\u2705 Output:\n```js\n" + out + "\n```"; } } }; hf.registerCommand(_eval); const exec = new Command("exec"); exec.elevatedOnly = true; exec.category = CATEGORY; exec.helpText = "Executes a command"; exec.callback = async function (msg, line) { const proc = spawn(line); let out = `\x1b[1mSpawned ${proc.pid}: \`${line}'\x1b[0m\n`; proc.stdout.on("data", (data) => { out += data; }); proc.stderr.on("data", (data) => { out += data; }); proc.on("close", async (code) => { out += `\n\x1b[0m\x1b[1m====\x1b[0m\n\x1b[1m${ code != 0 ? "\x1b[31m" : "" }Exited with ${code}\x1b[0m`; if (out.length > 1980) { const haste = await hastebin(out); msg.channel.createMessage({ content: `Output too long to send in a message: ${haste}`, allowedMentions: { repliedUser: false, }, messageReference: { messageID: msg.id, }, }); } else { msg.channel.createMessage({ content: `\`\`\`ansi\n${out}\`\`\``, allowedMentions: { repliedUser: false, }, messageReference: { messageID: msg.id, }, }); } }); }; hf.registerCommand(exec); const settings = new Command("settings"); settings.category = CATEGORY; settings.helpText = "Manage guild specific bot settings"; settings.callback = async function (msg, line, [cmd, key, value]) { if (!msg.guildID) "This command only works in guilds."; switch (cmd) { case "get": case "set": return "TODO"; case "flags": { const flags = await guildSettings.getFlags(msg.guildID); return `\`\`\`\n${Object.keys(flags) .map((key) => `${key} = ${flags[key]}`) .join("\n")}\n\`\`\``; } case "enable": { if ( !msg.channel.permissionsOf(msg.author.id).has("manageGuild") && !hf.config.elevated.includes(msg.author.id) ) return "You do not have `Manage Server` permissions"; if (!guildSettings.flags[key]) return "Unknown key."; const enabled = await guildSettings.hasFlag(msg.guildID, key); if (enabled === true) return "Already enabled."; await guildSettings.enableFlag(msg.guildID, key); return {reaction: "\uD83D\uDC4C"}; } case "disable": { if ( !msg.channel.permissionsOf(msg.author.id).has("manageGuild") && !hf.config.elevated.includes(msg.author.id) ) return "You do not have `Manage Server` permissions"; if (!guildSettings.flags[key]) return "Unknown key."; const enabled = await guildSettings.hasFlag(msg.guildID, key); if (enabled === false) return "Already disabled."; await guildSettings.disableFlag(msg.guildID, key); return {reaction: "\uD83D\uDC4C"}; } default: return `__**Settings Subcommands**__ \u2022 \`get \` - List all current values or a specific value \u2022 \`set [key] [value]\` - Set a value \u2022 \`flags\` - List flags \u2022 \`enable [key]\` - Enable a flag \u2022 \`disable [key]\` - Disable a flag`; } }; hf.registerCommand(settings);