ramirez/src/commands.js

191 lines
5.3 KiB
JavaScript

const { CommandManager, defaultParameterTypes, TypeConversionError, IParameter, ICommandConfig } = require("knub-command-manager");
const Eris = require("eris");
const config = require("./cfg");
const utils = require("./utils");
const threads = require("./data/threads");
const Thread = require("./data/Thread");
/**
* @callback CommandFn
* @param {Eris.Message} msg
* @param {object} args
*/
/**
* @callback InboxServerCommandHandler
* @param {Eris.Message} msg
* @param {object} args
* @param {Thread} [thread]
*/
/**
* @callback InboxThreadCommandHandler
* @param {Eris.Message} msg
* @param {object} args
* @param {Thread} thread
*/
/**
* @callback AddGlobalCommandFn
* @param {string} trigger
* @param {string} parameters
* @param {CommandFn} handler
* @param {ICommandConfig} commandConfig
*/
/**
* @callback AddInboxServerCommandFn
* @param {string} trigger
* @param {string} parameters
* @param {InboxServerCommandHandler} handler
* @param {ICommandConfig} commandConfig
*/
/**
* @callback AddInboxThreadCommandFn
* Add a command that can only be invoked in a thread on the inbox server
*
* @param {string} trigger
* @param {string} parameters
* @param {InboxThreadCommandHandler} handler
* @param {ICommandConfig} commandConfig
*/
/**
* @callback AddAliasFn
* @param {string} originalCmd
* @param {string} alias
*/
module.exports = {
createCommandManager(bot) {
const manager = new CommandManager({
prefix: config.prefix,
types: Object.assign({}, defaultParameterTypes, {
userId(value) {
const userId = utils.getUserMention(value);
if (! userId) throw new TypeConversionError();
return userId;
},
delay(value) {
const ms = utils.convertDelayStringToMS(value);
if (ms === null) throw new TypeConversionError();
return ms;
}
})
});
const handlers = {};
const aliasMap = new Map();
bot.on("messageCreate", async msg => {
if (msg.author.bot) return;
if (msg.author.id === bot.user.id) return;
if (! msg.content) return;
const matchedCommand = await manager.findMatchingCommand(msg.content, { msg });
if (matchedCommand === null) return;
if (matchedCommand.error !== undefined) {
utils.postError(msg.channel, matchedCommand.error);
return;
}
const allArgs = {};
for (const [name, arg] of Object.entries(matchedCommand.args)) {
allArgs[name] = arg.value;
}
for (const [name, opt] of Object.entries(matchedCommand.opts)) {
allArgs[name] = opt.value;
}
handlers[matchedCommand.id](msg, allArgs);
});
/**
* Add a command that can be invoked anywhere
* @type {AddGlobalCommandFn}
*/
const addGlobalCommand = (trigger, parameters, handler, commandConfig = {}) => {
let aliases = aliasMap.has(trigger) ? [...aliasMap.get(trigger)] : [];
if (commandConfig.aliases) aliases.push(...commandConfig.aliases);
const cmd = manager.add(trigger, parameters, { ...commandConfig, aliases });
handlers[cmd.id] = handler;
};
/**
* Add a command that can only be invoked on the inbox server
* @type {AddInboxServerCommandFn}
*/
const addInboxServerCommand = (trigger, parameters, handler, commandConfig = {}) => {
const aliases = aliasMap.has(trigger) ? [...aliasMap.get(trigger)] : [];
if (commandConfig.aliases) aliases.push(...commandConfig.aliases);
const cmd = manager.add(trigger, parameters, {
...commandConfig,
aliases,
preFilters: [
(_, context) => {
if (! utils.messageIsOnInboxServer(context.msg)) return false;
if (! utils.isStaff(context.msg.member)) return false;
return true;
}
]
});
handlers[cmd.id] = async (msg, args) => {
const thread = await threads.findOpenThreadByChannelId(msg.channel.id);
handler(msg, args, thread);
};
};
/**
* Add a command that can only be invoked in a thread on the inbox server
* @type {AddInboxThreadCommandFn}
*/
const addInboxThreadCommand = (trigger, parameters, handler, commandConfig = {}) => {
const aliases = aliasMap.has(trigger) ? [...aliasMap.get(trigger)] : [];
if (commandConfig.aliases) aliases.push(...commandConfig.aliases);
let thread;
const cmd = manager.add(trigger, parameters, {
...commandConfig,
aliases,
preFilters: [
async (_, context) => {
if (! utils.messageIsOnInboxServer(context.msg)) return false;
if (! utils.isStaff(context.msg.member)) return false;
thread = await threads.findOpenThreadByChannelId(context.msg.channel.id);
if (! thread) return false;
return true;
}
]
});
handlers[cmd.id] = async (msg, args) => {
handler(msg, args, thread);
};
};
/**
* @type {AddAliasFn}
*/
const addAlias = (originalCmd, alias) => {
if (! aliasMap.has(originalCmd)) {
aliasMap.set(originalCmd, new Set());
}
aliasMap.get(originalCmd).add(alias);
};
return {
manager,
addGlobalCommand,
addInboxServerCommand,
addInboxThreadCommand,
addAlias,
};
}
};