Skip to content

Commit

Permalink
refa: update cordis version
Browse files Browse the repository at this point in the history
  • Loading branch information
shigma committed Jun 17, 2022
1 parent c59cccf commit e668129
Show file tree
Hide file tree
Showing 12 changed files with 114 additions and 60 deletions.
2 changes: 1 addition & 1 deletion packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/command/command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ export class Command<U extends User.Field = never, G extends Channel.Field = nev

match(session: Session) {
const { authority = Infinity } = (session.user || {}) as User
return this.ctx.match(session) && this.config.authority <= authority
return this.ctx.filter(session) && this.config.authority <= authority
}

getConfig<K extends keyof Command.Config>(key: K, session: Session): Exclude<Command.Config[K], (session: Session) => any> {
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/command/runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/protocol/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
8 changes: 1 addition & 7 deletions packages/core/src/protocol/session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<any, any>

declare module 'cordis' {
namespace Lifecycle {
interface Session extends KoishiSession {}
}

interface Events extends Record<`${Genres}-${Actions}`, SessionEventCallback> {
'message': SessionEventCallback
'message-deleted': SessionEventCallback
Expand Down Expand Up @@ -423,7 +417,7 @@ export class Session<U extends User.Field = never, G extends Channel.Field = nev
}

const { command } = argv
if (!command.ctx.match(this)) return ''
if (!command.ctx.filter(this)) return ''

if (this.app.database) {
if (this.subtype === 'group') {
Expand Down
74 changes: 69 additions & 5 deletions packages/core/src/selector.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,22 @@
import { Dict, Logger, makeArray, MaybeArray, remove } from '@koishijs/utils'
import { Context } from 'cordis'
import { Context, Events } from 'cordis'
import { Channel } from './database'
import { Session } from './protocol/session'

declare module 'cordis' {
interface Context extends SelectorService.Delegates {
$selector: SelectorService
}

namespace Context {
interface Meta {
filter: Filter
}
}
}

export type Filter = (session: Session) => boolean

const selectors = ['user', 'guild', 'channel', 'self', 'private', 'platform'] as const

export type SelectorType = typeof selectors[number]
Expand All @@ -24,35 +32,81 @@ 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
channel(...values: string[]): Context
platform(...values: string[]): Context
private(...values: string[]): Context
select(options: Selection): Context
before<K extends BeforeEventName>(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<string[]>
broadcast(channels: readonly string[], content: string, forced?: boolean): Promise<string[]>
}
}

type OmitSubstring<S extends string, T extends string> = S extends `${infer L}${T}${infer R}` ? `${L}${R}` : never
type BeforeEventName = OmitSubstring<keyof Events & string, 'before-'>

export type BeforeEventMap = { [E in keyof Events & string as OmitSubstring<E, 'before-'>]: Events[E] }

function property<K extends keyof Session>(ctx: Context, key: K, ...values: Session[K][]) {
return ctx.intersect((session: Session) => {
return values.length ? values.includes(session[key]) : !!session[key]
})
}

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) {
Expand Down Expand Up @@ -123,6 +177,12 @@ export class SelectorService {
return ctx
}

before<K extends BeforeEventName>(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)
Expand Down Expand Up @@ -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',
],
})
64 changes: 32 additions & 32 deletions packages/core/tests/selector.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
})
})
2 changes: 1 addition & 1 deletion plugins/common/help/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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')
}
Expand Down
4 changes: 2 additions & 2 deletions plugins/frontend/insight/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ class Insight extends DataService<Insight.Payload> {
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)
}

Expand Down
8 changes: 2 additions & 6 deletions plugins/frontend/manager/src/packages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,20 +34,16 @@ class PackageProvider extends DataService<Dict<PackageProvider.Data>> {
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
})
Expand Down
4 changes: 2 additions & 2 deletions plugins/frontend/manager/src/writer.ts
Original file line number Diff line number Diff line change
@@ -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' {
Expand Down Expand Up @@ -181,7 +181,7 @@ class ConfigWriter extends DataService<App.Config> {
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]
Expand Down

0 comments on commit e668129

Please sign in to comment.