cnmc-bot/lib/middleware.js
2020-09-06 21:06:34 +02:00

145 lines
No EOL
4.3 KiB
JavaScript

module.exports = class Router {
/**
* @type {{
path: string,
callback: function(Message): boolean | string,
break: boolean,
opts: {
guildOnly: boolean,
permissions: string[],
clientPermissions: string[],
ownerOnly: boolean
}
}[]} middlewares
*/
middlewares = [];
constructor(name) {
this.name = name;
}
/**
* Registers a command
* @param {string} path command format
* @param {function(Message): boolean | string} callback to call on match
* @param {{
guildOnly: boolean,
permissions: string[],
clientPermissions: string[]
}} opts options to use
*/
command(path, callback, opts = {}) {
this.middlewares.push({
path,
callback,
opts,
break: true
});
return this;
}
/**
* Registers a middleware
* @param {string} path
* @param {function|Router} router
* @param {{
guildOnly: boolean,
permissions: string[],
clientPermissions: string[]
}} opts
*/
use(path, router, opts = {}) {
if(typeof path !== "string") {
[router, opts] = [path, router];
path = "";
}
if(typeof router === "function") {
this.middlewares.push({
path,
callback: router,
opts,
break: false
});
return this;
}
if(router instanceof Router) {
this.middlewares.push({
callback: (...args) => router.message(...args),
path: (path).trim(),
opts: Object.assign(router.opts, opts),
break: opts ? !!opts.break : false
})
return this;
}
if(!router.middlewares) throw new Error("Unknown middleware type");
for(var middleware of router.middlewares) {
this.middlewares.push({
...middleware,
path: (path + " " + middleware.path).trim(),
opts: Object.assign({}, middleware.opts, opts)
});
}
return this;
}
processPath(path, content) {
if(!path) return {};
var segments = path.split(" ");
var contentSegments = content.split(" ");
if(!contentSegments) return null;
if(segments.length > contentSegments.length) return null;
var args = {};
for(var segmentID in segments) {
var segment = segments[segmentID];
if(segment.startsWith(":")) {
args[segment.substr(1)] = contentSegments[segmentID];
} else if(segment !== contentSegments[segmentID]) return null;
}
var keys = segments.filter(segment => segment.startsWith(":")).map(segment => segment.substr(1));
if(contentSegments.length > segments.length && keys.length) {
args[keys[keys.length - 1]] += contentSegments.splice(segments.length).join(" ");
}
return args;
}
/**
*
* @param {Message} msg
* @param {{
guildOnly: boolean,
permissions: string[],
clientPermissions: string[]
}} opts options to use
*/
async checkOpts(msg, opts) {
if(!opts) return true;
if(!msg.guild && opts.guildOnly) return false;
if(opts.permissions && msg.member)
for(var permission of opts.permissions)
if(!msg.member.hasPermission(permission)) return false;
if(opts.clientPermissions && msg.guild.me)
for(var permission of opts.clientPermissions)
if(!msg.guild.me.hasPermission(permission)) return false;
return true;
}
async message(msg) {
var middlewares = this.middlewares;
for(var middleware of middlewares) {
var args = this.processPath(middleware.path, msg.content);
if(args === null) continue;
if(!this.checkOpts(msg, middleware.opts)) continue;
var result = await middleware.callback(msg, args);
if(typeof result === "string") {
await msg.channel.send(result);
}
if(middleware.break || result === false) {
return false;
}
}
}
}