From e66812997924963286dc76b9055b4900bed506db Mon Sep 17 00:00:00 2001 From: Shigma Date: Fri, 17 Jun 2022 16:00:29 +0800 Subject: [PATCH] refa: update cordis version --- packages/core/package.json | 2 +- packages/core/src/command/command.ts | 2 +- packages/core/src/command/runtime.ts | 2 +- packages/core/src/index.ts | 2 +- packages/core/src/protocol/index.ts | 2 +- packages/core/src/protocol/session.ts | 8 +-- packages/core/src/selector.ts | 74 ++++++++++++++++++++++-- packages/core/tests/selector.spec.ts | 64 ++++++++++---------- plugins/common/help/src/index.ts | 2 +- plugins/frontend/insight/src/index.ts | 4 +- plugins/frontend/manager/src/packages.ts | 8 +-- plugins/frontend/manager/src/writer.ts | 4 +- 12 files changed, 114 insertions(+), 60 deletions(-) diff --git a/packages/core/package.json b/packages/core/package.json index beae44be42..6f609e21c7 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -36,7 +36,7 @@ }, "dependencies": { "@koishijs/utils": "^5.4.5", - "cordis": "^1.4.3", + "cordis": "^1.5.0", "fastest-levenshtein": "^1.0.12", "minato": "^1.2.0" } diff --git a/packages/core/src/command/command.ts b/packages/core/src/command/command.ts index bf153034db..1b156044fe 100644 --- a/packages/core/src/command/command.ts +++ b/packages/core/src/command/command.ts @@ -189,7 +189,7 @@ export class Command(key: K, session: Session): Exclude any> { diff --git a/packages/core/src/command/runtime.ts b/packages/core/src/command/runtime.ts index d270869213..4f97da546a 100644 --- a/packages/core/src/command/runtime.ts +++ b/packages/core/src/command/runtime.ts @@ -22,7 +22,7 @@ export default function runtime(ctx: Context) { if (parsed.prefix || quote) return for (const shortcut of ctx.$commander._shortcuts) { const { name, fuzzy, command, prefix, options = {}, args = [] } = shortcut - if (prefix && !parsed.appel || !command.ctx.match(session)) continue + if (prefix && !parsed.appel || !command.ctx.filter(session)) continue if (typeof name === 'string') { if (!fuzzy && content !== name || !content.startsWith(name)) continue const message = content.slice(name.length) diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 219154801d..aa338ac8cd 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -8,9 +8,9 @@ export * from 'cordis' export * from 'minato' export * from './i18n' export * from './database' +export * from './selector' export * from './protocol' export * from './command' -export * from './selector' const version: string = require('../package.json').version export { version } diff --git a/packages/core/src/protocol/index.ts b/packages/core/src/protocol/index.ts index 4578a3ec16..ecdae028c0 100644 --- a/packages/core/src/protocol/index.ts +++ b/packages/core/src/protocol/index.ts @@ -167,7 +167,7 @@ export class Internal { // preparation this._sessions[session.id] = session const queue: Next.Queue = this._hooks - .filter(([context]) => context.match(session)) + .filter(([context]) => context.filter(session)) .map(([, middleware]) => middleware.bind(null, session)) // execute middlewares diff --git a/packages/core/src/protocol/session.ts b/packages/core/src/protocol/session.ts index a227a175e6..e6aa8e1da8 100644 --- a/packages/core/src/protocol/session.ts +++ b/packages/core/src/protocol/session.ts @@ -10,13 +10,7 @@ type Genres = 'friend' | 'channel' | 'guild' | 'guild-member' | 'guild-role' | ' type Actions = 'added' | 'deleted' | 'updated' type SessionEventCallback = (session: Session) => void -type KoishiSession = Session - declare module 'cordis' { - namespace Lifecycle { - interface Session extends KoishiSession {} - } - interface Events extends Record<`${Genres}-${Actions}`, SessionEventCallback> { 'message': SessionEventCallback 'message-deleted': SessionEventCallback @@ -423,7 +417,7 @@ export class Session boolean + const selectors = ['user', 'guild', 'channel', 'self', 'private', 'platform'] as const export type SelectorType = typeof selectors[number] @@ -24,6 +32,11 @@ interface Selection extends BaseSelection { export namespace SelectorService { export interface Delegates { logger(name: string): Logger + any(): Context + never(): Context + union(arg: Filter | Context): Context + intersect(arg: Filter | Context): Context + exclude(arg: Filter | Context): Context user(...values: string[]): Context self(...values: string[]): Context guild(...values: string[]): Context @@ -31,6 +44,7 @@ export namespace SelectorService { platform(...values: string[]): Context private(...values: string[]): Context select(options: Selection): Context + before(name: K, listener: BeforeEventMap[K], append?: boolean): () => boolean setTimeout(callback: (...args: any[]) => void, ms: number, ...args: any[]): () => boolean setInterval(callback: (...args: any[]) => void, ms: number, ...args: any[]): () => boolean broadcast(content: string, forced?: boolean): Promise @@ -38,6 +52,11 @@ export namespace SelectorService { } } +type OmitSubstring = S extends `${infer L}${T}${infer R}` ? `${L}${R}` : never +type BeforeEventName = OmitSubstring + +export type BeforeEventMap = { [E in keyof Events & string as OmitSubstring]: Events[E] } + function property(ctx: Context, key: K, ...values: Session[K][]) { return ctx.intersect((session: Session) => { return values.length ? values.includes(session[key]) : !!session[key] @@ -45,14 +64,49 @@ function property(ctx: Context, key: K, ...values: Sess } export class SelectorService { - constructor(private ctx: Context) { - ctx.on('internal/warn', (format, ...args) => { + constructor(private app: Context) { + app.filter = () => true + + app.on('internal/warning', (format, ...args) => { this.logger('app').warn(format, ...args) }) + + app.on('internal/runtime', (runtime) => { + if (!runtime.uid) return + runtime.context.filter = (session) => { + return runtime.children.some(p => p.context.filter(session)) + } + }) } protected get caller(): Context { - return this[Context.current] || this.ctx + return this[Context.current] || this.app + } + + any() { + return this.caller.extend({ filter: () => true }) + } + + never() { + return this.caller.extend({ filter: () => false }) + } + + union(arg: Filter | Context) { + const caller = this.caller + const filter = typeof arg === 'function' ? arg : arg.filter + return this.caller.extend({ filter: s => caller.filter(s) || filter(s) }) + } + + intersect(arg: Filter | Context) { + const caller = this.caller + const filter = typeof arg === 'function' ? arg : arg.filter + return this.caller.extend({ filter: s => caller.filter(s) && filter(s) }) + } + + exclude(arg: Filter | Context) { + const caller = this.caller + const filter = typeof arg === 'function' ? arg : arg.filter + return this.caller.extend({ filter: s => caller.filter(s) && !filter(s) }) } logger(name: string) { @@ -123,6 +177,12 @@ export class SelectorService { return ctx } + before(name: K, listener: BeforeEventMap[K], append = false) { + const seg = (name as string).split('/') + seg[seg.length - 1] = 'before-' + seg[seg.length - 1] + return this.caller.on(seg.join('/') as keyof Events, listener, !append) + } + private createTimerDispose(timer: NodeJS.Timeout) { const dispose = () => { clearTimeout(timer) @@ -170,5 +230,9 @@ export class SelectorService { Context.service('$selector', { constructor: SelectorService, - methods: ['logger', 'user', 'self', 'guild', 'channel', 'platform', 'private', 'select', 'setTimeout', 'setInterval', 'broadcast'], + methods: [ + 'any', 'never', 'union', 'intersect', 'exclude', 'select', + 'user', 'self', 'guild', 'channel', 'platform', 'private', + 'before', 'logger', 'setTimeout', 'setInterval', 'broadcast', + ], }) diff --git a/packages/core/tests/selector.spec.ts b/packages/core/tests/selector.spec.ts index 792cb6635f..8fed49610f 100644 --- a/packages/core/tests/selector.spec.ts +++ b/packages/core/tests/selector.spec.ts @@ -9,52 +9,52 @@ const privateSession = app.mock.session({ userId: '123', subtype: 'private' }) describe('Selector API', () => { it('root context', () => { - expect(app.match(guildSession)).to.be.true - expect(app.match(privateSession)).to.be.true + expect(app.filter(guildSession)).to.be.true + expect(app.filter(privateSession)).to.be.true }) it('context.prototype.user', () => { - expect(app.user().match(guildSession)).to.be.true - expect(app.user().match(privateSession)).to.be.true - expect(app.user('123').match(guildSession)).to.be.true - expect(app.user('123').match(privateSession)).to.be.true - expect(app.user('456').match(guildSession)).to.be.false - expect(app.user('456').match(privateSession)).to.be.false + expect(app.user().filter(guildSession)).to.be.true + expect(app.user().filter(privateSession)).to.be.true + expect(app.user('123').filter(guildSession)).to.be.true + expect(app.user('123').filter(privateSession)).to.be.true + expect(app.user('456').filter(guildSession)).to.be.false + expect(app.user('456').filter(privateSession)).to.be.false }) it('context.prototype.private', () => { - expect(app.private().match(guildSession)).to.be.false - expect(app.private().match(privateSession)).to.be.true - expect(app.private().user('123').match(guildSession)).to.be.false - expect(app.private().user('123').match(privateSession)).to.be.true - expect(app.private().user('456').match(guildSession)).to.be.false - expect(app.private().user('456').match(privateSession)).to.be.false + expect(app.private().filter(guildSession)).to.be.false + expect(app.private().filter(privateSession)).to.be.true + expect(app.private().user('123').filter(guildSession)).to.be.false + expect(app.private().user('123').filter(privateSession)).to.be.true + expect(app.private().user('456').filter(guildSession)).to.be.false + expect(app.private().user('456').filter(privateSession)).to.be.false }) it('context.prototype.guild', () => { - expect(app.guild().match(guildSession)).to.be.true - expect(app.guild().match(privateSession)).to.be.false - expect(app.guild('123').match(guildSession)).to.be.false - expect(app.guild('123').match(privateSession)).to.be.false - expect(app.guild('456').match(guildSession)).to.be.true - expect(app.guild('456').match(privateSession)).to.be.false + expect(app.guild().filter(guildSession)).to.be.true + expect(app.guild().filter(privateSession)).to.be.false + expect(app.guild('123').filter(guildSession)).to.be.false + expect(app.guild('123').filter(privateSession)).to.be.false + expect(app.guild('456').filter(guildSession)).to.be.true + expect(app.guild('456').filter(privateSession)).to.be.false }) it('context chaining', () => { - expect(app.guild('456').user('123').match(guildSession)).to.be.true - expect(app.guild('456').user('456').match(guildSession)).to.be.false - expect(app.guild('123').user('123').match(guildSession)).to.be.false - expect(app.user('123').guild('456').match(guildSession)).to.be.true - expect(app.user('456').guild('456').match(guildSession)).to.be.false - expect(app.user('123').guild('123').match(guildSession)).to.be.false + expect(app.guild('456').user('123').filter(guildSession)).to.be.true + expect(app.guild('456').user('456').filter(guildSession)).to.be.false + expect(app.guild('123').user('123').filter(guildSession)).to.be.false + expect(app.user('123').guild('456').filter(guildSession)).to.be.true + expect(app.user('456').guild('456').filter(guildSession)).to.be.false + expect(app.user('123').guild('123').filter(guildSession)).to.be.false }) it('context intersection', () => { - expect(app.guild('456', '789').guild('123', '456').match(guildSession)).to.be.true - expect(app.guild('456', '789').guild('123', '789').match(guildSession)).to.be.false - expect(app.guild('123', '789').guild('123', '456').match(guildSession)).to.be.false - expect(app.user('123', '789').user('123', '456').match(guildSession)).to.be.true - expect(app.user('456', '789').user('123', '456').match(guildSession)).to.be.false - expect(app.user('123', '789').user('456', '789').match(guildSession)).to.be.false + expect(app.guild('456', '789').guild('123', '456').filter(guildSession)).to.be.true + expect(app.guild('456', '789').guild('123', '789').filter(guildSession)).to.be.false + expect(app.guild('123', '789').guild('123', '456').filter(guildSession)).to.be.false + expect(app.user('123', '789').user('123', '456').filter(guildSession)).to.be.true + expect(app.user('456', '789').user('123', '456').filter(guildSession)).to.be.false + expect(app.user('123', '789').user('456', '789').filter(guildSession)).to.be.false }) }) diff --git a/plugins/common/help/src/index.ts b/plugins/common/help/src/index.ts index 44d71e9c06..92cad0118d 100644 --- a/plugins/common/help/src/index.ts +++ b/plugins/common/help/src/index.ts @@ -77,7 +77,7 @@ export function apply(ctx: Context, config: Config = {}) { } const command = findCommand(target) - if (!command?.ctx.match(session)) { + if (!command?.ctx.filter(session)) { if (!ctx.$suggest) { return session.text('.suggest-prefix') } diff --git a/plugins/frontend/insight/src/index.ts b/plugins/frontend/insight/src/index.ts index 9df9c63f63..290bb465f7 100644 --- a/plugins/frontend/insight/src/index.ts +++ b/plugins/frontend/insight/src/index.ts @@ -42,8 +42,8 @@ class Insight extends DataService { prod: resolve(__dirname, '../dist'), }) - ctx.on('plugin-added', this.update) - ctx.on('plugin-removed', this.update) + ctx.on('internal/fork', this.update) + ctx.on('internal/runtime', this.update) ctx.on('internal/service', this.update) } diff --git a/plugins/frontend/manager/src/packages.ts b/plugins/frontend/manager/src/packages.ts index a678d7a7ab..21e872dfb5 100644 --- a/plugins/frontend/manager/src/packages.ts +++ b/plugins/frontend/manager/src/packages.ts @@ -34,20 +34,16 @@ class PackageProvider extends DataService> { constructor(ctx: Context, config: PackageProvider.Config) { super(ctx, 'packages', { authority: 4 }) - this.ctx.on('plugin-added', async (state) => { + this.ctx.on('internal/runtime', (state) => { this.updatePackage(state.plugin, state.uid) }) - - this.ctx.on('plugin-removed', async (state) => { - this.updatePackage(state.plugin, null) - }) } get registry() { return this.ctx.app.registry } - private async updatePackage(plugin: Plugin, id: number) { + private updatePackage(plugin: Plugin, id: number) { const entry = Object.keys(require.cache).find((key) => { return ns.unwrapExports(require.cache[key].exports) === plugin }) diff --git a/plugins/frontend/manager/src/writer.ts b/plugins/frontend/manager/src/writer.ts index dbaf2e4942..4dd822243c 100644 --- a/plugins/frontend/manager/src/writer.ts +++ b/plugins/frontend/manager/src/writer.ts @@ -1,5 +1,5 @@ import { DataService } from '@koishijs/plugin-console' -import { Adapter, App, Bot, Context, Fork, remove } from 'koishi' +import { Adapter, App, Bot, Context, remove, State } from 'koishi' import { Loader } from '@koishijs/cli' declare module '@koishijs/plugin-console' { @@ -181,7 +181,7 @@ class ConfigWriter extends DataService { this.loader.writeConfig() } - private locate(name: string, parent: Fork): Fork { + private locate(name: string, parent: State): State { for (const key in parent.config) { const value = parent.config[key] const fork = parent[Loader.kRecord][key]