diff --git a/permissions/plugin.json b/permissions/plugin.json index ae5717b..4cec034 100644 --- a/permissions/plugin.json +++ b/permissions/plugin.json @@ -3,7 +3,7 @@ "name": "permissions", "description": "Official permissions system for commands", "tags": ["api", "permissions"], - "version": "0.0.0", + "version": "0.1.0", "dependencies": ["control?"], "npmDependencies": [] } diff --git a/permissions/plugin.ts b/permissions/plugin.ts index 21ac694..2fa417a 100644 --- a/permissions/plugin.ts +++ b/permissions/plugin.ts @@ -26,14 +26,34 @@ import { fullIDMatcher } from '@squeebot/core/lib/common'; } */ +declare type RoleReceiver = (msg: IMessage) => string[]; + @Configurable({users: {}, rooms: {}}) class PermissionsPlugin extends Plugin { + public roleReceivers: Map = new Map(); + + registerRoleReceiver(plugin: string, fn: RoleReceiver): void { + if (this.roleReceivers.has(plugin)) { + return; + } + + this.roleReceivers.set(plugin, fn); + } + userPermitted(msg: IMessage, required: string[]): boolean { // Boot all guests instantly if (msg.guest === true) { return false; } + // Receive permissions from a role fetching function registered by + // a service or service adapter + const rr = this.roleReceivers.get(msg.source.plugin.manifest.name); + const userRoles = []; + if (rr) { + userRoles.push(...rr(msg)); + } + const userFull = msg.fullSenderID; const roomFull = msg.fullRoomID; if (!userFull || !roomFull) { @@ -46,18 +66,10 @@ class PermissionsPlugin extends Plugin { const users = this.config.config.rooms[ch]; for (const user in users) { if (fullIDMatcher(userFull, user)) { - const perms = users[user]; - if (perms.indexOf('*') !== -1) { - return true; - } + const perms = [...users[user], ...userRoles]; let has = false; for (const perm of required) { - if (perm === '*') { - has = true; - break; - } - if (perms.indexOf(perm) !== -1) { has = true; break; @@ -82,11 +94,6 @@ class PermissionsPlugin extends Plugin { let has = false; for (const perm of required) { - if (perm === '*') { - has = true; - break; - } - if (perms.indexOf(perm) !== -1) { has = true; break; @@ -110,6 +117,14 @@ class PermissionsPlugin extends Plugin { this.emit('pluginUnloaded', this)); } } + + @EventListener('pluginUnloaded') + unloadedEventHandler(plugin: string | Plugin): void { + const str = (typeof plugin === 'string' ? plugin : plugin.manifest.name); + if (this.roleReceivers.has(str)) { + this.roleReceivers.delete(str); + } + } } module.exports = PermissionsPlugin; diff --git a/simplecommands/plugin.json b/simplecommands/plugin.json index 2ac76b3..b256817 100644 --- a/simplecommands/plugin.json +++ b/simplecommands/plugin.json @@ -3,7 +3,7 @@ "name": "simplecommands", "description": "Official Simplistic Commands API for Squeebot 3", "tags": ["handler", "commands", "api"], - "version": "1.1.0", + "version": "1.1.1", "dependencies": ["control?", "permissions?"], "npmDependencies": [] } diff --git a/simplecommands/plugin.ts b/simplecommands/plugin.ts index d426b53..0c84d97 100644 --- a/simplecommands/plugin.ts +++ b/simplecommands/plugin.ts @@ -53,7 +53,6 @@ const rates: {[key: string]: Rate} = {}; prefix: { '*': '!' }, - keywords: ['squeebot'], rateLimits: [], channelMatching: false, }) @@ -238,83 +237,6 @@ class SqueebotCommandsAPIPlugin extends Plugin { // Done } - public async handleKeywords( - msg: IMessage, - keyword: string, - plugins: string[], - msr: MessageResolver): Promise { - const text = msg.text.toLowerCase(); - - // Only pass command specs which have `match` and match rooms - let matching = []; - for (const spec of this.commands) { - if (!spec.match) { - continue; - } - - if (plugins.length && plugins.indexOf(spec.plugin) === -1) { - continue; - } - - if (typeof spec.match === 'function') { - try { - const match = spec.match(msg); - if (match == null) { - continue; - } - spec.tempargv = match; - } catch (e) {} - } else { - const rgx = text.match(spec.match); - if (rgx == null) { - continue; - } - spec.tempargv = rgx.slice(1); - } - - matching.push(spec); - } - - matching = this.roomMatcher(msg, matching); - - // Nothing matches room requirements - if (!matching.length) { - return; - } - - // Iteration 2: Sort the array so that the ones that had room matching come up first - const sorted = []; - for (const spec of matching) { - if (spec.source) { - sorted.push(spec); - continue; - } - sorted.push(spec); - } - - // Iteration 3: Match permissions for user - const permitted = this.permissionMatcher(msg, sorted); - - // Rate limit check - if (permitted.length && - this.config.get('rateLimits', []).length && - this.doLimiting(msg.fullRoomID!, msg.fullSenderID!)) { - logger.warn('[%s] User %s rate limited', this.name, msg.fullSenderID); - return; - } - - // Start executing - for (const spec of permitted) { - const success = await spec.execute(msg, msr, spec, keyword, - ...(spec.tempargv ? spec.tempargv : [])); - if (success) { - break; - } - } - - // Done - } - @EventListener('message') public digest(msg: IMessage, chan: IChannel, msr: MessageResolver): void { if (msg.type !== EMessageType.message) { @@ -328,18 +250,6 @@ class SqueebotCommandsAPIPlugin extends Plugin { const text = msg.text; const prefixes = this.config.config.prefix; - const keywords = this.config.config.keywords; - - // Attempt to match keywords - if (keywords && keywords.length) { - for (const kw of keywords) { - if (text.toLowerCase().match(kw) != null) { - this.handleKeywords(msg, kw, allowedPlugins, msr).catch(e => - logger.error('[%s] Command handler threw an error:', this.name, e.stack)); - return; - } - } - } if (!prefixes) { return;