Skip to content

Commit

Permalink
feat(cli): support $filter modifier
Browse files Browse the repository at this point in the history
  • Loading branch information
shigma committed Jun 17, 2022
1 parent 6f26772 commit b8ab3c8
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 54 deletions.
61 changes: 60 additions & 1 deletion packages/cli/src/worker/utils.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,72 @@
import { Context } from 'koishi'
import { Context, makeArray, MaybeArray } from 'koishi'

interface Modifier {
$filter?: Selection
$isolate?: string[]
}

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

export type SelectorType = typeof selectors[number]
export type SelectorValue = boolean | MaybeArray<string | number>
export type BaseSelection = { [K in SelectorType]?: SelectorValue }

interface Selection extends BaseSelection {
and?: Selection[]
or?: Selection[]
not?: Selection
}

export function select(root: Context, options: Selection) {
let ctx = root

// basic selectors
for (const type of selectors) {
const value = options[type]
if (value === true) {
ctx = ctx[type]()
} else if (value === false) {
ctx = ctx.exclude(ctx[type]())
} else if (value !== undefined) {
// we turn everything into string
ctx = ctx[type](...makeArray(value).map(item => '' + item))
}
}

// intersect
if (options.and) {
for (const selection of options.and) {
ctx = ctx.intersect(select(root, selection))
}
}

// union
if (options.or) {
let ctx2: Context = ctx.never()
for (const selection of options.or) {
ctx2 = ctx2.union(select(root, selection))
}
ctx = ctx.intersect(ctx2)
}

// exclude
if (options.not) {
ctx = ctx.exclude(select(root, options.not))
}

return ctx
}

export function patch(ctx: Context, config: Modifier) {
config ||= {}
const parent = Object.getPrototypeOf(ctx)

if (config.$filter) {
ctx.filter = parent.intersect(select(ctx.any(), config.$filter)).filter
} else {
delete ctx.filter
}

const oldMapping = { ...ctx }.mapping || {}
if (config.$isolate) {
ctx.mapping = parent.isolate(config.$isolate).mapping
Expand Down
54 changes: 1 addition & 53 deletions packages/core/src/selector.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Dict, Logger, makeArray, MaybeArray, remove } from '@koishijs/utils'
import { Dict, Logger, remove } from '@koishijs/utils'
import { Context, Events } from 'cordis'
import { Channel } from './database'
import { Session } from './protocol/session'
Expand All @@ -17,18 +17,6 @@ declare module 'cordis' {

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

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

export type SelectorType = typeof selectors[number]
export type SelectorValue = boolean | MaybeArray<string | number>
export type BaseSelection = { [K in SelectorType as `$${K}`]?: SelectorValue }

interface Selection extends BaseSelection {
$and?: Selection[]
$or?: Selection[]
$not?: Selection
}

export namespace SelectorService {
export interface Delegates {
logger(name: string): Logger
Expand Down Expand Up @@ -137,46 +125,6 @@ export class SelectorService {
return property(this.caller.exclude(property(this.caller, 'guildId')), 'userId', ...values)
}

select(options: Selection) {
let ctx: Context = this.caller

// basic selectors
for (const type of selectors) {
const value = options[`$${type}`] as SelectorValue
if (value === true) {
ctx = ctx[type]()
} else if (value === false) {
ctx = ctx.exclude(ctx[type]())
} else if (value !== undefined) {
// we turn everything into string
ctx = ctx[type](...makeArray(value).map(item => '' + item))
}
}

// intersect
if (options.$and) {
for (const selection of options.$and) {
ctx = ctx.intersect(this.select(selection))
}
}

// union
if (options.$or) {
let ctx2: Context = this.caller
for (const selection of options.$or) {
ctx2 = ctx2.union(this.select(selection))
}
ctx = ctx.intersect(ctx2)
}

// exclude
if (options.$not) {
ctx = ctx.exclude(this.select(options.$not))
}

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]
Expand Down

0 comments on commit b8ab3c8

Please sign in to comment.