diff options
Diffstat (limited to 'src/commands.js')
| -rw-r--r-- | src/commands.js | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/src/commands.js b/src/commands.js new file mode 100644 index 0000000..59c6506 --- /dev/null +++ b/src/commands.js @@ -0,0 +1,130 @@ +const { CommandManager, defaultParameterTypes, TypeConversionError } = require('knub-command-manager'); +const config = require('./config'); +const utils = require('./utils'); +const threads = require('./data/threads'); + +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 + */ + 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 + */ + 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 + */ + 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); + }; + }; + + const addAlias = (originalCmd, alias) => { + if (! aliasMap.has(originalCmd)) { + aliasMap.set(originalCmd, new Set()); + } + + aliasMap.get(originalCmd).add(alias); + }; + + return { + manager, + addGlobalCommand, + addInboxServerCommand, + addInboxThreadCommand, + addAlias, + }; + } +}; |