HiddenPhox/src/lib/commandDispatcher.js

233 lines
6.1 KiB
JavaScript

const logger = require("./logger.js");
const {pastelize, getTopColor} = require("./utils.js");
function convertIfApplicable(val) {
if (isNaN(val)) {
if (val.toString().toLowerCase() === "true") {
return true;
} else if (val.toString().toLowerCase() === "false") {
return false;
} else {
return val;
}
} else {
return Number(val);
}
}
function removeStartHyphens(val) {
return val.replace(/^--?/g, "");
}
// taken from ethanent/gar
// modified to make - arguments only be bools unless =
function parseAsArgv(argv) {
const optional = {};
const args = [];
for (const arg of argv) {
const equalsIndex = arg.charAt(0) === "-" ? arg.indexOf("=") : -1;
const argName =
equalsIndex === -1
? removeStartHyphens(arg)
: removeStartHyphens(arg.slice(0, equalsIndex));
if (equalsIndex !== -1) {
optional[argName] = convertIfApplicable(arg.slice(equalsIndex + 1));
} else if (arg.charAt(0) === "-") {
if (arg.charAt(1) === "-") {
optional[argName] = true;
} else {
for (let b = 0; b < argName.length; b++) {
optional[argName.charAt(b)] = true;
}
}
} else {
args.push(convertIfApplicable(argName));
}
}
return {
optional,
args,
};
}
function parseArguments(str) {
return str.match(/\\?.|^$/g).reduce(
(p, c) => {
if (c === '"') {
p.quote ^= 1;
} else if (!p.quote && c === " ") {
p.a.push("");
} else {
p.a[p.a.length - 1] += c.replace(/\\(.)/, "$1");
}
return p;
},
{a: [""]}
).a;
}
async function runCommand(msg, cmd, line) {
let cmdObj = hf.commands.get(cmd);
if (!cmdObj) {
for (const c of hf.commands.values()) {
if (c.hasAlias(cmd)) {
cmdObj = c;
break;
}
}
}
if (!cmdObj) return null;
if (cmdObj.ownerOnly && msg.author.id != hf.config.owner_id) {
return "No\n\nSent from my iPhone.";
}
if (cmdObj.elevatedOnly && !hf.config.elevated.includes(msg.author.id)) {
return "No\n\nSent from my iPhone.";
}
if (cmdObj.guildOnly && !msg.guildID) {
return "This command can only be used in guilds.";
}
try {
const args = parseArguments(line);
const argv = parseAsArgv(args);
const ret = cmdObj.callback(msg, line, argv.args, argv.optional);
if (ret instanceof Promise) {
return await ret;
} else {
return ret;
}
} catch (err) {
logger.error("hf:cmd:" + cmd, err + "\n" + err.stack);
return ":warning: An internal error occurred.";
}
}
async function CommandDispatcher(msg) {
let str = msg.content;
let inCommand = false;
const prefix1 = hf.config.prefix;
const prefix2 = `<@${hf.bot.user.id}> `;
const prefix3 = `<@!${hf.bot.user.id}> `;
if (str.startsWith(prefix1)) {
str = str.substring(prefix1.length);
inCommand = true;
} else if (str.startsWith(prefix2)) {
str = str.substring(prefix2.length);
inCommand = true;
} else if (str.startsWith(prefix3)) {
str = str.substring(prefix3.length);
inCommand = true;
}
if (inCommand) {
let line = str.split(" ");
let [cmd] = line.splice(0, 1);
cmd = cmd.toLowerCase();
line = line.join(" ");
try {
const response = await runCommand(msg, cmd, line);
if (response != null) {
msg.hasRan = true;
if (response.file) {
const newFile = response.file;
delete response.file;
if (newFile.contents) {
newFile.file = newFile.contents;
delete newFile.contents;
}
if (newFile.name) {
newFile.filename = newFile.name;
delete newFile.name;
}
const files = response.attachments ?? [];
files.push(newFile);
response.attachments = files;
}
if (response.files) {
response.attachments = response.files;
delete response.files;
for (const attachment of response.attachments) {
if (attachment.contents) {
attachment.file = attachment.contents;
delete attachment.contents;
}
if (attachment.name) {
attachment.filename = attachment.name;
delete attachment.name;
}
}
}
if (response.embed) {
response.embeds = [...(response.embeds ?? []), response.embed];
delete response.embed;
}
if (response.embeds) {
for (const embed of response.embeds) {
embed.color =
embed.color ||
getTopColor(msg, hf.bot.user.id, pastelize(hf.bot.user.id));
}
}
if (response.reaction) {
msg.addReaction(response.reaction);
} else {
try {
const outMessage = await msg.channel.createMessage(
Object.assign(
typeof response === "string" ? {content: response} : response,
{
allowedMentions: {
repliedUser: false,
},
messageReference: {
messageID: msg.id,
},
}
)
);
if (response.addReactions) {
for (const index in response.addReactions) {
const reaction = response.addReactions[index];
await outMessage.addReaction(reaction);
}
}
} catch (err) {
msg.channel.createMessage({
content: `:warning: An error has occurred:\n\`\`\`${err}\`\`\``,
allowedMentions: {
repliedUser: false,
},
messageReference: {
messageID: msg.id,
},
});
}
}
}
} catch (err) {
msg.channel.createMessage({
content: `:warning: An error has occurred:\n\`\`\`${err}\`\`\``,
allowedMentions: {
repliedUser: false,
},
messageReference: {
messageID: msg.id,
},
});
}
}
}
module.exports = CommandDispatcher;