@chatluna/patchbay 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +57 -2
- package/lib/apply.d.ts +5 -0
- package/lib/apply.js +59 -0
- package/lib/cli.d.ts +2 -0
- package/lib/cli.js +33 -0
- package/lib/index.d.ts +4 -0
- package/lib/index.js +4 -0
- package/lib/manifest.d.ts +24 -0
- package/lib/manifest.js +13 -0
- package/lib/patch.d.ts +7 -0
- package/lib/patch.js +43 -0
- package/lib/sync.d.ts +31 -0
- package/lib/sync.js +144 -0
- package/package.json +54 -4
- package/patchbay.json +68 -0
- package/patches/@cordisjs+plugin-cli-cordis@1.0.5.patch +56 -0
- package/patches/@cordisjs+plugin-database@4.1.1.patch +15 -0
- package/patches/@cordisjs+plugin-http@1.5.2.patch +13 -0
- package/patches/@cordisjs+plugin-loader@1.0.0-rc.9.patch +82 -0
- package/patches/@cordisjs+plugin-server@1.7.0.patch +22 -0
- package/patches/@cordisjs+unyaml@2.0.3.patch +69 -0
- package/patches/@koishijs+core@4.18.11.patch +1092 -0
- package/patches/@satorijs+core@4.6.1.patch +584 -0
- package/patches/koishi-plugin-adapter-onebot@6.9.5.patch +194 -0
|
@@ -0,0 +1,1092 @@
|
|
|
1
|
+
diff --git a/lib/index.d.ts b/lib/index.d.ts
|
|
2
|
+
index b0e0826..004cff1 100644
|
|
3
|
+
--- a/lib/index.d.ts
|
|
4
|
+
+++ b/lib/index.d.ts
|
|
5
|
+
@@ -1,17 +1,15 @@
|
|
6
|
+
import * as utils from '@koishijs/utils';
|
|
7
|
+
-import * as minato from 'minato';
|
|
8
|
+
+import * as minato from '@cordisjs/plugin-database';
|
|
9
|
+
import * as satori from '@satorijs/core';
|
|
10
|
+
import * as cordis from 'cordis';
|
|
11
|
+
import { Dict, Awaitable, Promisify } from 'cosmokit';
|
|
12
|
+
-import { Driver, FlatKeys, FlatPick, Update, Eval } from 'minato';
|
|
13
|
+
+import { Driver, FlatKeys, FlatPick, Update, Eval } from '@cordisjs/plugin-database';
|
|
14
|
+
import { Fragment, EventOptions, Hook, h, Schema, Universal, Bot, HTTP } from '@satorijs/core';
|
|
15
|
+
import { LocaleTree } from '@koishijs/i18n-utils';
|
|
16
|
+
import { Disposable, GetEvents, Parameters, ReturnType, ThisType } from 'cordis';
|
|
17
|
+
import { version } from '../package';
|
|
18
|
+
export interface Context {
|
|
19
|
+
- [minato.Types]: Types;
|
|
20
|
+
- [minato.Tables]: Tables;
|
|
21
|
+
- [Context.Database]: Context.Database<this>;
|
|
22
|
+
+ database: KoishiDatabase & minato.Database<Tables, Types, Context>;
|
|
23
|
+
broadcast(content: Fragment, forced?: boolean): Promise<string[]>;
|
|
24
|
+
broadcast(channels: readonly string[], content: Fragment, forced?: boolean): Promise<string[]>;
|
|
25
|
+
}
|
|
26
|
+
@@ -76,7 +74,7 @@ export namespace Channel {
|
|
27
|
+
type Field = keyof Channel;
|
|
28
|
+
type Observed<K extends Field = Field> = utils.Observed<Pick<Channel, K>, Promise<void>>;
|
|
29
|
+
}
|
|
30
|
+
-declare interface KoishiDatabase extends minato.Database<Tables, Types, Context> {
|
|
31
|
+
+declare interface KoishiDatabase {
|
|
32
|
+
}
|
|
33
|
+
declare class KoishiDatabase {
|
|
34
|
+
ctx: Context;
|
|
35
|
+
@@ -103,13 +101,13 @@ export interface Context {
|
|
36
|
+
}): () => boolean;
|
|
37
|
+
}
|
|
38
|
+
export interface Events {
|
|
39
|
+
- 'before-attach-channel'(session: Session, fields: Set<Channel.Field>): void;
|
|
40
|
+
- 'attach-channel'(session: Session): Awaitable<void | boolean>;
|
|
41
|
+
- 'before-attach-user'(session: Session, fields: Set<User.Field>): void;
|
|
42
|
+
- 'attach-user'(session: Session): Awaitable<void | boolean>;
|
|
43
|
+
- 'before-attach'(session: Session): void;
|
|
44
|
+
- 'attach'(session: Session): void;
|
|
45
|
+
- 'middleware'(session: Session): void;
|
|
46
|
+
+ 'before-attach-channel'(session: satori.Session, fields: Set<Channel.Field>): void;
|
|
47
|
+
+ 'attach-channel'(session: satori.Session): Awaitable<void | boolean>;
|
|
48
|
+
+ 'before-attach-user'(session: satori.Session, fields: Set<User.Field>): void;
|
|
49
|
+
+ 'attach-user'(session: satori.Session): Awaitable<void | boolean>;
|
|
50
|
+
+ 'before-attach'(session: satori.Session): void;
|
|
51
|
+
+ 'attach'(session: satori.Session): void;
|
|
52
|
+
+ 'middleware'(session: satori.Session): void;
|
|
53
|
+
}
|
|
54
|
+
export class SessionError extends Error {
|
|
55
|
+
path: string | string[];
|
|
56
|
+
@@ -219,7 +217,9 @@ export namespace I18n {
|
|
57
|
+
const Config: Schema<Config>;
|
|
58
|
+
}
|
|
59
|
+
export interface Context {
|
|
60
|
+
- permissions: Permissions;
|
|
61
|
+
+ // chatluna: `permissions` is provided by @chatluna/permission and typed by
|
|
62
|
+
+ // its own cordis augmentation; koishi's Permissions class does not run.
|
|
63
|
+
+ permissions: any;
|
|
64
|
+
}
|
|
65
|
+
export interface Events {
|
|
66
|
+
'internal/permission'(): void;
|
|
67
|
+
@@ -470,6 +470,10 @@ export namespace Command {
|
|
68
|
+
handleError?: boolean | ((error: Error, argv: Argv) => Awaitable<void | Fragment>);
|
|
69
|
+
/** enable slash command */
|
|
70
|
+
slash?: boolean;
|
|
71
|
+
+ /** exclude the command from listings; plugins like help read this */
|
|
72
|
+
+ hidden?: boolean;
|
|
73
|
+
+ /** chatluna: plugin or module that registered the command */
|
|
74
|
+
+ owner?: string;
|
|
75
|
+
}
|
|
76
|
+
const Config: Schema<Config>;
|
|
77
|
+
}
|
|
78
|
+
@@ -479,7 +483,7 @@ export interface Context {
|
|
79
|
+
command<D extends string>(def: D, desc: string, config?: Command.Config): Command<never, never, Argv.ArgumentType<D>>;
|
|
80
|
+
}
|
|
81
|
+
export interface Events {
|
|
82
|
+
- 'before-parse'(content: string, session: Session): Argv;
|
|
83
|
+
+ 'before-parse'(content: string, session: satori.Session): Argv;
|
|
84
|
+
'command-added'(command: Command): void;
|
|
85
|
+
'command-updated'(command: Command): void;
|
|
86
|
+
'command-removed'(command: Command): void;
|
|
87
|
+
@@ -680,6 +684,39 @@ declare module '@satorijs/core' {
|
|
88
|
+
interface Events {
|
|
89
|
+
'internal/schema'(name: string): void;
|
|
90
|
+
}
|
|
91
|
+
+ // chatluna: upstream declares the session extension members on koishi's own
|
|
92
|
+
+ // Session interface; ChatLuna types sessions as satori.Session, so merge the
|
|
93
|
+
+ // members here. Parameter types are widened to `any` where the koishi
|
|
94
|
+
+ // interface binds session generics: both directions must stay assignable
|
|
95
|
+
+ // under strictFunctionTypes + exactOptionalPropertyTypes.
|
|
96
|
+
+ interface Session {
|
|
97
|
+
+ argv?: Argv<any, any>;
|
|
98
|
+
+ user?: User.Observed<any>;
|
|
99
|
+
+ channel?: Channel.Observed<any>;
|
|
100
|
+
+ guild?: Channel.Observed<any>;
|
|
101
|
+
+ permissions: string[];
|
|
102
|
+
+ scope?: string;
|
|
103
|
+
+ response?: () => Promise<Fragment>;
|
|
104
|
+
+ resolve<T, R extends any[]>(source: T | Eval.Expr | ((session: any, ...args: R) => T), ...args: R): T extends Eval.Expr ? Eval<T> : T extends (...args: any[]) => any ? ReturnType<T> : T;
|
|
105
|
+
+ stripped: Stripped;
|
|
106
|
+
+ username: string;
|
|
107
|
+
+ send(fragment: Fragment, options?: Universal.SendOptions): Promise<string[]>;
|
|
108
|
+
+ cancelQueued(delay?: number): void;
|
|
109
|
+
+ sendQueued(content: Fragment, delay?: number): Promise<string[]>;
|
|
110
|
+
+ getChannel(...args: any[]): Promise<any>;
|
|
111
|
+
+ observeChannel(fields?: Iterable<Channel.Field>): Promise<any>;
|
|
112
|
+
+ getUser(...args: any[]): Promise<any>;
|
|
113
|
+
+ observeUser(fields?: Iterable<User.Field>): Promise<any>;
|
|
114
|
+
+ withScope(scope: string, callback: () => any): Promise<any>;
|
|
115
|
+
+ resolveScope(path: string): string;
|
|
116
|
+
+ text(path: string | string[], params?: object): string;
|
|
117
|
+
+ i18n(path: string | string[], params?: object): h[];
|
|
118
|
+
+ collect(...args: any[]): Set<any>;
|
|
119
|
+
+ execute(content: string | Argv<any, any>, next?: any): Promise<h[]>;
|
|
120
|
+
+ middleware(middleware: any): () => boolean;
|
|
121
|
+
+ prompt(...args: any[]): Promise<any>;
|
|
122
|
+
+ suggest(options: SuggestOptions): Promise<string>;
|
|
123
|
+
+ }
|
|
124
|
+
}
|
|
125
|
+
export class SchemaService {
|
|
126
|
+
ctx: Context;
|
|
127
|
+
@@ -689,19 +726,83 @@ export class SchemaService {
|
|
128
|
+
get(name: string): Schema;
|
|
129
|
+
set(name: string, schema: Schema): void;
|
|
130
|
+
}
|
|
131
|
+
-export type EffectScope = cordis.EffectScope<Context>;
|
|
132
|
+
-export type ForkScope = cordis.ForkScope<Context>;
|
|
133
|
+
-export type MainScope = cordis.MainScope<Context>;
|
|
134
|
+
+export type EffectScope = Context;
|
|
135
|
+
+export type ForkScope = Context;
|
|
136
|
+
+export type MainScope = Context;
|
|
137
|
+
export { Adapter, Bot, Element, h, HTTP, Logger, MessageEncoder, Messenger, Quester, Schema, segment, Universal, z } from '@satorijs/core';
|
|
138
|
+
export type { Component, Fragment, Render } from '@satorijs/core';
|
|
139
|
+
export { resolveConfig } from 'cordis';
|
|
140
|
+
-export type { Disposable, ScopeStatus, Plugin } from 'cordis';
|
|
141
|
+
+export type { Disposable, Plugin } from 'cordis';
|
|
142
|
+
declare module 'cordis' {
|
|
143
|
+
namespace Plugin {
|
|
144
|
+
interface Object {
|
|
145
|
+
filter?: boolean;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
+ // chatluna: koishi's accessor members are declared on its own Context
|
|
149
|
+
+ // interface upstream; ChatLuna code types contexts as cordis.Context, so
|
|
150
|
+
+ // mirror the members here.
|
|
151
|
+
+ interface Context {
|
|
152
|
+
+ koishi: Koishi;
|
|
153
|
+
+ database: KoishiDatabase & minato.Database;
|
|
154
|
+
+ broadcast(content: Fragment, forced?: boolean): Promise<string[]>;
|
|
155
|
+
+ broadcast(channels: readonly string[], content: Fragment, forced?: boolean): Promise<string[]>;
|
|
156
|
+
+ $processor: Processor;
|
|
157
|
+
+ middleware(middleware: (session: any, next: Next) => Awaitable<any>, prepend?: boolean): () => boolean;
|
|
158
|
+
+ match(pattern: string | RegExp, response: Fragment, options?: Matcher.Options & {
|
|
159
|
+
+ i18n?: false;
|
|
160
|
+
+ }): () => boolean;
|
|
161
|
+
+ match(pattern: string, response: string, options?: Matcher.Options & {
|
|
162
|
+
+ i18n: true;
|
|
163
|
+
+ }): () => boolean;
|
|
164
|
+
+ i18n: I18n;
|
|
165
|
+
+ // chatluna: `permissions` is provided by @chatluna/permission and typed by
|
|
166
|
+
+ // its own cordis augmentation; koishi's Permissions class does not run.
|
|
167
|
+
+ $commander: Commander;
|
|
168
|
+
+ command<D extends string>(def: D, config?: Command.Config): Command<never, never, Argv.ArgumentType<D>>;
|
|
169
|
+
+ command<D extends string>(def: D, desc: string, config?: Command.Config): Command<never, never, Argv.ArgumentType<D>>;
|
|
170
|
+
+ schema: SchemaService;
|
|
171
|
+
+ $filter: FilterService;
|
|
172
|
+
+ filter: Filter;
|
|
173
|
+
+ any(): this;
|
|
174
|
+
+ never(): this;
|
|
175
|
+
+ union(arg: Filter | this): this;
|
|
176
|
+
+ intersect(arg: Filter | this): this;
|
|
177
|
+
+ exclude(arg: Filter | this): this;
|
|
178
|
+
+ user(...values: string[]): this;
|
|
179
|
+
+ self(...values: string[]): this;
|
|
180
|
+
+ guild(...values: string[]): this;
|
|
181
|
+
+ channel(...values: string[]): this;
|
|
182
|
+
+ platform(...values: string[]): this;
|
|
183
|
+
+ private(...values: string[]): this;
|
|
184
|
+
+ model: minato.Database;
|
|
185
|
+
+ http: Quester;
|
|
186
|
+
+ server: any;
|
|
187
|
+
+ before<K extends BeforeEventName>(name: K, listener: BeforeEventMap[K], append?: boolean): () => boolean;
|
|
188
|
+
+ /** @deprecated use `ctx.root` instead */
|
|
189
|
+
+ readonly app: this;
|
|
190
|
+
+ /** @deprecated use `koishi.config` instead */
|
|
191
|
+
+ readonly options: any;
|
|
192
|
+
+ }
|
|
193
|
+
+ interface Events<C> {
|
|
194
|
+
+ 'before-attach-channel'(session: satori.Session, fields: Set<Channel.Field>): void;
|
|
195
|
+
+ 'attach-channel'(session: satori.Session): Awaitable<void | boolean>;
|
|
196
|
+
+ 'before-attach-user'(session: satori.Session, fields: Set<User.Field>): void;
|
|
197
|
+
+ 'attach-user'(session: satori.Session): Awaitable<void | boolean>;
|
|
198
|
+
+ 'before-attach'(session: satori.Session): void;
|
|
199
|
+
+ 'attach'(session: satori.Session): void;
|
|
200
|
+
+ 'middleware'(session: satori.Session): void;
|
|
201
|
+
+ 'internal/i18n'(): void;
|
|
202
|
+
+ 'internal/permission'(): void;
|
|
203
|
+
+ 'before-parse'(content: string, session: satori.Session): Argv;
|
|
204
|
+
+ 'command-added'(command: Command): void;
|
|
205
|
+
+ 'command-updated'(command: Command): void;
|
|
206
|
+
+ 'command-removed'(command: Command): void;
|
|
207
|
+
+ 'command-error'(argv: Argv, error: any): void;
|
|
208
|
+
+ 'command/before-execute'(argv: Argv): Awaitable<void | Fragment>;
|
|
209
|
+
+ 'command/before-attach-channel'(argv: Argv, fields: Set<Channel.Field>): void;
|
|
210
|
+
+ 'command/before-attach-user'(argv: Argv, fields: Set<User.Field>): void;
|
|
211
|
+
+ }
|
|
212
|
+
}
|
|
213
|
+
export interface EnvData {
|
|
214
|
+
}
|
|
215
|
+
@@ -713,10 +814,18 @@ type BeforeEventMap = {
|
|
216
|
+
export interface Events<C extends Context = Context> extends cordis.Events<C> {
|
|
217
|
+
}
|
|
218
|
+
export interface Context {
|
|
219
|
+
- [Context.events]: Events<this>;
|
|
220
|
+
- [Context.session]: Session<never, never, this>;
|
|
221
|
+
koishi: Koishi;
|
|
222
|
+
}
|
|
223
|
+
+export class Koishi extends cordis.Service<Context.Config> {
|
|
224
|
+
+ bot: KoishiBot;
|
|
225
|
+
+ database: KoishiDatabase;
|
|
226
|
+
+ session: KoishiSession<never, never, Context>;
|
|
227
|
+
+ readonly config: Context.Config;
|
|
228
|
+
+ get commander(): Commander;
|
|
229
|
+
+ static get Config(): Schema<Context.Config>;
|
|
230
|
+
+ constructor(ctx: Context, config?: Context.Config);
|
|
231
|
+
+}
|
|
232
|
+
+export default Koishi;
|
|
233
|
+
export class Context extends satori.Context {
|
|
234
|
+
static shadow: symbol;
|
|
235
|
+
constructor(config?: Context.Config);
|
|
236
|
+
@@ -724,12 +833,6 @@ export class Context extends satori.Context {
|
|
237
|
+
get app(): this;
|
|
238
|
+
/** @deprecated use `koishi.config` instead */
|
|
239
|
+
get options(): any;
|
|
240
|
+
- /** @deprecated */
|
|
241
|
+
- waterfall<K extends keyof GetEvents<this>>(name: K, ...args: Parameters<GetEvents<this>[K]>): Promisify<ReturnType<GetEvents<this>[K]>>;
|
|
242
|
+
- waterfall<K extends keyof GetEvents<this>>(thisArg: ThisType<GetEvents<this>[K]>, name: K, ...args: Parameters<GetEvents<this>[K]>): Promisify<ReturnType<GetEvents<this>[K]>>;
|
|
243
|
+
- /** @deprecated */
|
|
244
|
+
- chain<K extends keyof GetEvents<this>>(name: K, ...args: Parameters<GetEvents<this>[K]>): ReturnType<GetEvents<this>[K]>;
|
|
245
|
+
- chain<K extends keyof GetEvents<this>>(thisArg: ThisType<GetEvents<this>[K]>, name: K, ...args: Parameters<GetEvents<this>[K]>): ReturnType<GetEvents<this>[K]>;
|
|
246
|
+
before<K extends BeforeEventName>(name: K, listener: BeforeEventMap[K], append?: boolean): () => boolean;
|
|
247
|
+
}
|
|
248
|
+
export namespace Context {
|
|
249
|
+
@@ -764,8 +867,7 @@ export namespace Context {
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
-export abstract class Service<T = any, C extends Context = Context> extends satori.Service<T, C> {
|
|
254
|
+
- [satori.Service.setup](): void;
|
|
255
|
+
+export abstract class Service<T = any, C extends Context = Context> extends cordis.Service<T> {
|
|
256
|
+
}
|
|
257
|
+
export { Context as App };
|
|
258
|
+
export function defineConfig(config: Context.Config): Context.Config;
|
|
259
|
+
@@ -784,5 +886,5 @@ declare class KoishiBot {
|
|
260
|
+
broadcast(channels: (string | [string, string] | Session)[], content: Fragment, delay?: any): Promise<string[]>;
|
|
261
|
+
}
|
|
262
|
+
export * from '@koishijs/utils';
|
|
263
|
+
-export * from 'minato';
|
|
264
|
+
+export * from '@cordisjs/plugin-database';
|
|
265
|
+
export { version };
|
|
266
|
+
diff --git a/lib/index.mjs b/lib/index.mjs
|
|
267
|
+
index b99cd02..2d446d8 100644
|
|
268
|
+
--- a/lib/index.mjs
|
|
269
|
+
+++ b/lib/index.mjs
|
|
270
|
+
@@ -2,16 +2,120 @@ var __defProp = Object.defineProperty;
|
|
271
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
272
|
+
|
|
273
|
+
// src/index.ts
|
|
274
|
+
-import { version } from "../package.json";
|
|
275
|
+
-export * from "@koishijs/utils";
|
|
276
|
+
-export * from "minato";
|
|
277
|
+
+// chatluna: hardcode the version; importing ../package.json needs a JSON import
|
|
278
|
+
+// attribute that the published bundle does not carry.
|
|
279
|
+
+const version = "4.18.11";
|
|
280
|
+
+// chatluna: `export *` from the CJS @koishijs/utils makes require(esm) return a
|
|
281
|
+
+// facade that drops every `export {}` name below, and Node's named-export
|
|
282
|
+
+// analysis also misses the utils' cosmokit re-exports. Re-export the detected
|
|
283
|
+
+// utils-own names explicitly and let cosmokit carry the rest.
|
|
284
|
+
+import {
|
|
285
|
+
+ assertProperty as assertProperty0,
|
|
286
|
+
+ coerce as coerce0,
|
|
287
|
+
+ defineEnumProperty as defineEnumProperty0,
|
|
288
|
+
+ enumKeys as enumKeys0,
|
|
289
|
+
+ escapeRegExp as escapeRegExp0,
|
|
290
|
+
+ extend as extend0,
|
|
291
|
+
+ interpolate as interpolate0,
|
|
292
|
+
+ isInteger as isInteger0,
|
|
293
|
+
+ isType as isType0,
|
|
294
|
+
+ merge as merge0,
|
|
295
|
+
+ observe as observe0,
|
|
296
|
+
+ renameProperty as renameProperty0,
|
|
297
|
+
+ sleep as sleep0
|
|
298
|
+
+} from "@koishijs/utils";
|
|
299
|
+
+import Random0 from "@koishijs/utils";
|
|
300
|
+
+export {
|
|
301
|
+
+ assertProperty0 as assertProperty,
|
|
302
|
+
+ coerce0 as coerce,
|
|
303
|
+
+ defineEnumProperty0 as defineEnumProperty,
|
|
304
|
+
+ enumKeys0 as enumKeys,
|
|
305
|
+
+ escapeRegExp0 as escapeRegExp,
|
|
306
|
+
+ extend0 as extend,
|
|
307
|
+
+ interpolate0 as interpolate,
|
|
308
|
+
+ isInteger0 as isInteger,
|
|
309
|
+
+ isType0 as isType,
|
|
310
|
+
+ merge0 as merge,
|
|
311
|
+
+ observe0 as observe,
|
|
312
|
+
+ renameProperty0 as renameProperty,
|
|
313
|
+
+ sleep0 as sleep
|
|
314
|
+
+};
|
|
315
|
+
+export const Random = Random0.Random;
|
|
316
|
+
+export * from "cosmokit";
|
|
317
|
+
+export * from "@cordisjs/plugin-database";
|
|
318
|
+
|
|
319
|
+
// src/context.ts
|
|
320
|
+
import { defineProperty as defineProperty6, Time as Time3 } from "cosmokit";
|
|
321
|
+
import { HTTP, Schema as Schema5 } from "@satorijs/core";
|
|
322
|
+
import * as satori from "@satorijs/core";
|
|
323
|
+
import * as cordis from "cordis";
|
|
324
|
+
-import * as minato from "minato";
|
|
325
|
+
+import { getTraceable, symbols as cordisSymbols } from "cordis";
|
|
326
|
+
+import * as minato from "@cordisjs/plugin-database";
|
|
327
|
+
+
|
|
328
|
+
+// chatluna: Cordis 4 bridge. Cordis 3 symbols/services that Koishi relies on are
|
|
329
|
+
+// re-created here; the Context class itself is patched further below.
|
|
330
|
+
+const kContextCurrent = Symbol.for("koishi.current");
|
|
331
|
+
+function kFilterHooks(hooks, thisArg) {
|
|
332
|
+
+ return (hooks || []).filter((hook) => hook.global || !hook.ctx?.[cordis.Context.filter] || hook.ctx[cordis.Context.filter](thisArg));
|
|
333
|
+
+}
|
|
334
|
+
+function kRegister(ctx, hooks, name, callback, options = {}) {
|
|
335
|
+
+ const hook = { ctx, callback, prepend: options.prepend === true };
|
|
336
|
+
+ if (hook.prepend) hooks.unshift(hook);
|
|
337
|
+
+ else hooks.push(hook);
|
|
338
|
+
+ return ctx.effect(() => () => {
|
|
339
|
+
+ const index = hooks.indexOf(hook);
|
|
340
|
+
+ if (index >= 0) hooks.splice(index, 1);
|
|
341
|
+
+ }, `koishi ${name}`);
|
|
342
|
+
+}
|
|
343
|
+
+function kCollect(ctx, dispose) {
|
|
344
|
+
+ return ctx.effect(() => dispose, "koishi collect");
|
|
345
|
+
+}
|
|
346
|
+
+// Cordis 3 `ctx.mixin(object, map)` pulled members off the object; Cordis 4 only
|
|
347
|
+
+// accepts a service name. Define the same flat accessors (`ctx['session.send']`)
|
|
348
|
+
+// that session/bot/database trackers then resolve.
|
|
349
|
+
+// Cordis 4 has no `ready` event; fire when the registering fiber goes ACTIVE.
|
|
350
|
+
+function kOnReady(ctx, cb) {
|
|
351
|
+
+ if (ctx.fiber.state === 2) { setTimeout(cb, 0); return () => {}; }
|
|
352
|
+
+ const off = ctx.on("internal/status", (fiber) => {
|
|
353
|
+
+ if (fiber === ctx.fiber && fiber.state === 2) { off(); Promise.resolve().then(cb); }
|
|
354
|
+
+ });
|
|
355
|
+
+ return off;
|
|
356
|
+
+}
|
|
357
|
+
+function kMixinFrom(ctx, source, mixins) {
|
|
358
|
+
+ return ctx.effect(() => {
|
|
359
|
+
+ const entries = Array.isArray(mixins) ? mixins.map((key) => [key, key]) : Object.entries(mixins);
|
|
360
|
+
+ // Session/bot/database proxies resolve `session.<key>` accessors with the
|
|
361
|
+
+ // tracked object as `symbols.receiver`; evaluate the member against it so
|
|
362
|
+
+ // extension methods (stripped, send, ...) see the session as `this`.
|
|
363
|
+
+ const define = (key, name) => ctx.reflect.accessor(name, {
|
|
364
|
+
+ get(receiver) {
|
|
365
|
+
+ const target = receiver ?? source;
|
|
366
|
+
+ const value = Reflect.get(source, key, target);
|
|
367
|
+
+ return typeof value === "function" ? value.bind(target) : value;
|
|
368
|
+
+ },
|
|
369
|
+
+ set(value, receiver) {
|
|
370
|
+
+ return Reflect.set(source, key, value, receiver ?? source);
|
|
371
|
+
+ }
|
|
372
|
+
+ });
|
|
373
|
+
+ const disposables = entries.map(([key, name]) => define(key, name));
|
|
374
|
+
+ // Methods on the service object that sessions call internally
|
|
375
|
+
+ // (e.g. session.stripped -> this._stripNickname) also need `session.<key>`
|
|
376
|
+
+ // accessors. Register every prototype member under the same prefix.
|
|
377
|
+
+ const prefix = entries[0]?.[1].split(".", 1)[0];
|
|
378
|
+
+ if (prefix) {
|
|
379
|
+
+ const declared = new Set(entries.map(([, name]) => name));
|
|
380
|
+
+ for (let proto = Object.getPrototypeOf(source); proto && proto !== Object.prototype; proto = Object.getPrototypeOf(proto)) {
|
|
381
|
+
+ for (const key of Object.getOwnPropertyNames(proto)) {
|
|
382
|
+
+ const name = `${prefix}.${key}`;
|
|
383
|
+
+ if (key === "constructor" || declared.has(name) || name in ctx.reflect.props) continue;
|
|
384
|
+
+ declared.add(name);
|
|
385
|
+
+ disposables.push(define(key, name));
|
|
386
|
+
+ }
|
|
387
|
+
+ }
|
|
388
|
+
+ }
|
|
389
|
+
+ return disposables;
|
|
390
|
+
+ }, "koishi mixin");
|
|
391
|
+
+}
|
|
392
|
+
|
|
393
|
+
// src/filter.ts
|
|
394
|
+
import { defineProperty } from "cosmokit";
|
|
395
|
+
@@ -24,35 +128,38 @@ __name(property, "property");
|
|
396
|
+
var FilterService = class {
|
|
397
|
+
constructor(ctx) {
|
|
398
|
+
this.ctx = ctx;
|
|
399
|
+
- defineProperty(this, Context.current, ctx);
|
|
400
|
+
- ctx.filter = () => true;
|
|
401
|
+
- ctx.on("internal/runtime", (runtime) => {
|
|
402
|
+
- if (!runtime.uid) return;
|
|
403
|
+
- runtime.ctx.filter = (session) => {
|
|
404
|
+
- return runtime.children.some((p) => p.ctx.filter(session));
|
|
405
|
+
+ defineProperty(this, kContextCurrent, ctx);
|
|
406
|
+
+ ctx.root[cordisSymbols.filter] ??= () => true;
|
|
407
|
+
+ ctx.on("internal/plugin", (fiber) => {
|
|
408
|
+
+ if (!fiber.uid) return;
|
|
409
|
+
+ const parentFilter = fiber.ctx[cordisSymbols.filter] ?? (() => true);
|
|
410
|
+
+ fiber.ctx[cordisSymbols.filter] = (session) => {
|
|
411
|
+
+ return parentFilter(session);
|
|
412
|
+
};
|
|
413
|
+
});
|
|
414
|
+
}
|
|
415
|
+
static {
|
|
416
|
+
__name(this, "FilterService");
|
|
417
|
+
}
|
|
418
|
+
+ // chatluna: resolve `this.ctx` to the calling plugin so its registrations are disposed with it.
|
|
419
|
+
+ [cordisSymbols.tracker] = { property: "ctx" };
|
|
420
|
+
any() {
|
|
421
|
+
- return this.ctx.extend({ filter: /* @__PURE__ */ __name(() => true, "filter") });
|
|
422
|
+
+ return this.ctx.extend({ [cordisSymbols.filter]: () => true });
|
|
423
|
+
}
|
|
424
|
+
never() {
|
|
425
|
+
- return this.ctx.extend({ filter: /* @__PURE__ */ __name(() => false, "filter") });
|
|
426
|
+
+ return this.ctx.extend({ [cordisSymbols.filter]: () => false });
|
|
427
|
+
}
|
|
428
|
+
union(arg) {
|
|
429
|
+
- const filter2 = typeof arg === "function" ? arg : arg.filter;
|
|
430
|
+
- return this.ctx.extend({ filter: /* @__PURE__ */ __name((s) => this.ctx.filter(s) || filter2(s), "filter") });
|
|
431
|
+
+ const filter2 = typeof arg === "function" ? arg : arg[cordisSymbols.filter];
|
|
432
|
+
+ return this.ctx.extend({ [cordisSymbols.filter]: (s) => this.ctx[cordisSymbols.filter](s) || filter2(s) });
|
|
433
|
+
}
|
|
434
|
+
intersect(arg) {
|
|
435
|
+
- const filter2 = typeof arg === "function" ? arg : arg.filter;
|
|
436
|
+
- return this.ctx.extend({ filter: /* @__PURE__ */ __name((s) => this.ctx.filter(s) && filter2(s), "filter") });
|
|
437
|
+
+ const filter2 = typeof arg === "function" ? arg : arg[cordisSymbols.filter];
|
|
438
|
+
+ return this.ctx.extend({ [cordisSymbols.filter]: (s) => this.ctx[cordisSymbols.filter](s) && filter2(s) });
|
|
439
|
+
}
|
|
440
|
+
exclude(arg) {
|
|
441
|
+
- const filter2 = typeof arg === "function" ? arg : arg.filter;
|
|
442
|
+
- return this.ctx.extend({ filter: /* @__PURE__ */ __name((s) => this.ctx.filter(s) && !filter2(s), "filter") });
|
|
443
|
+
+ const filter2 = typeof arg === "function" ? arg : arg[cordisSymbols.filter];
|
|
444
|
+
+ return this.ctx.extend({ [cordisSymbols.filter]: (s) => this.ctx[cordisSymbols.filter](s) && !filter2(s) });
|
|
445
|
+
}
|
|
446
|
+
user(...values) {
|
|
447
|
+
return property(this.ctx, "userId", ...values);
|
|
448
|
+
@@ -422,8 +529,8 @@ var Argv;
|
|
449
|
+
})(Argv || (Argv = {}));
|
|
450
|
+
|
|
451
|
+
// src/middleware.ts
|
|
452
|
+
-import { coerce, makeArray, Random } from "@koishijs/utils";
|
|
453
|
+
-import { defineProperty as defineProperty2, Time } from "cosmokit";
|
|
454
|
+
+import { coerce, Random as Random2 } from "@koishijs/utils";
|
|
455
|
+
+import { defineProperty as defineProperty2, makeArray, Time } from "cosmokit";
|
|
456
|
+
import { h as h2 } from "@satorijs/core";
|
|
457
|
+
|
|
458
|
+
// src/database.ts
|
|
459
|
+
@@ -446,7 +553,7 @@ var Channel;
|
|
460
|
+
var KoishiDatabase = class {
|
|
461
|
+
constructor(ctx) {
|
|
462
|
+
this.ctx = ctx;
|
|
463
|
+
- ctx.mixin(this, {
|
|
464
|
+
+ kMixinFrom(ctx, this, {
|
|
465
|
+
getUser: "database.getUser",
|
|
466
|
+
setUser: "database.setUser",
|
|
467
|
+
createUser: "database.createUser",
|
|
468
|
+
@@ -607,37 +714,29 @@ var Next;
|
|
469
|
+
Next2.compose = compose;
|
|
470
|
+
__name(compose, "compose");
|
|
471
|
+
})(Next || (Next = {}));
|
|
472
|
+
-var Processor = class {
|
|
473
|
+
- constructor(ctx) {
|
|
474
|
+
- this.ctx = ctx;
|
|
475
|
+
- defineProperty2(this, Context.current, ctx);
|
|
476
|
+
- this.middleware(this.attach.bind(this), true);
|
|
477
|
+
- ctx.on("message", this._handleMessage.bind(this));
|
|
478
|
+
- ctx.before("attach-user", (session, fields) => {
|
|
479
|
+
- session.collect("user", session.argv, fields);
|
|
480
|
+
- });
|
|
481
|
+
- ctx.before("attach-channel", (session, fields) => {
|
|
482
|
+
- session.collect("channel", session.argv, fields);
|
|
483
|
+
- });
|
|
484
|
+
- ctx.component("execute", async (attrs, children, session) => {
|
|
485
|
+
+// chatluna: session components must wait for the satori service; ctx.component is
|
|
486
|
+
+// only reachable through its mixin, which lands when the satori fiber applies.
|
|
487
|
+
+function installComponents(ctx) {
|
|
488
|
+
+ ctx.inject(["satori"], (sub) => {
|
|
489
|
+
+ sub.component("execute", async (attrs, children, session) => {
|
|
490
|
+
return session.execute(children.join(""), true);
|
|
491
|
+
}, { session: true });
|
|
492
|
+
- ctx.component("prompt", async (attrs, children, session) => {
|
|
493
|
+
+ sub.component("prompt", async (attrs, children, session) => {
|
|
494
|
+
await session.send(children);
|
|
495
|
+
return session.prompt();
|
|
496
|
+
}, { session: true });
|
|
497
|
+
- ctx.component("i18n", async (attrs, children, session) => {
|
|
498
|
+
+ sub.component("i18n", async (attrs, children, session) => {
|
|
499
|
+
return session.i18n(attrs.path, children);
|
|
500
|
+
}, { session: true });
|
|
501
|
+
- ctx.component("random", async (attrs, children) => {
|
|
502
|
+
- return Random.pick(children);
|
|
503
|
+
+ sub.component("random", async (attrs, children) => {
|
|
504
|
+
+ return Random2.pick(children);
|
|
505
|
+
});
|
|
506
|
+
- ctx.component("plural", async (attrs, children) => {
|
|
507
|
+
+ sub.component("plural", async (attrs, children) => {
|
|
508
|
+
const path2 = attrs.count in children ? attrs.count : children.length - 1;
|
|
509
|
+
return children[path2];
|
|
510
|
+
});
|
|
511
|
+
const units = ["day", "hour", "minute", "second"];
|
|
512
|
+
- ctx.component("i18n:time", (attrs, children, session) => {
|
|
513
|
+
+ sub.component("i18n:time", (attrs, children, session) => {
|
|
514
|
+
let ms = +attrs.value;
|
|
515
|
+
for (let index = 0; index < 3; index++) {
|
|
516
|
+
const major = Time[units[index]];
|
|
517
|
+
@@ -653,6 +752,21 @@ var Processor = class {
|
|
518
|
+
}
|
|
519
|
+
return Math.round(ms / Time.second) + " " + session.text("general.second");
|
|
520
|
+
}, { session: true });
|
|
521
|
+
+ });
|
|
522
|
+
+}
|
|
523
|
+
+var Processor = class {
|
|
524
|
+
+ constructor(ctx) {
|
|
525
|
+
+ this.ctx = ctx;
|
|
526
|
+
+ defineProperty2(this, kContextCurrent, ctx);
|
|
527
|
+
+ this.middleware(this.attach.bind(this), true);
|
|
528
|
+
+ ctx.on("message", this._handleMessage.bind(this));
|
|
529
|
+
+ ctx.before("attach-user", (session, fields) => {
|
|
530
|
+
+ session.collect("user", session.argv, fields);
|
|
531
|
+
+ });
|
|
532
|
+
+ ctx.before("attach-channel", (session, fields) => {
|
|
533
|
+
+ session.collect("channel", session.argv, fields);
|
|
534
|
+
+ });
|
|
535
|
+
+ installComponents(ctx);
|
|
536
|
+
ctx.before("attach", (session) => {
|
|
537
|
+
for (const matcher of this._matchers) {
|
|
538
|
+
this._executeMatcher(session, matcher);
|
|
539
|
+
@@ -663,6 +777,8 @@ var Processor = class {
|
|
540
|
+
static {
|
|
541
|
+
__name(this, "Processor");
|
|
542
|
+
}
|
|
543
|
+
+ // chatluna: resolve `this.ctx` to the calling plugin so its registrations are disposed with it.
|
|
544
|
+
+ [cordisSymbols.tracker] = { property: "ctx" };
|
|
545
|
+
_hooks = [];
|
|
546
|
+
_sessions = /* @__PURE__ */ Object.create(null);
|
|
547
|
+
_matchers = /* @__PURE__ */ new Set();
|
|
548
|
+
@@ -670,12 +786,12 @@ var Processor = class {
|
|
549
|
+
if (typeof options !== "object") {
|
|
550
|
+
options = { prepend: options };
|
|
551
|
+
}
|
|
552
|
+
- return this.ctx.lifecycle.register("middleware", this._hooks, middleware, options);
|
|
553
|
+
+ return kRegister(this.ctx, this._hooks, "middleware", middleware, options);
|
|
554
|
+
}
|
|
555
|
+
match(pattern, response, options) {
|
|
556
|
+
const matcher = { ...options, context: this.ctx, pattern, response };
|
|
557
|
+
this._matchers.add(matcher);
|
|
558
|
+
- return this.ctx.collect("shortcut", () => {
|
|
559
|
+
+ return kCollect(this.ctx, () => {
|
|
560
|
+
return this._matchers.delete(matcher);
|
|
561
|
+
});
|
|
562
|
+
}
|
|
563
|
+
@@ -683,7 +799,7 @@ var Processor = class {
|
|
564
|
+
const { stripped, quote } = session;
|
|
565
|
+
const { appel, context, i18n, regex, fuzzy, pattern, response } = matcher;
|
|
566
|
+
if ((appel || stripped.hasAt) && !stripped.appel) return;
|
|
567
|
+
- if (!context.filter(session)) return;
|
|
568
|
+
+ if (!(context[cordisSymbols.filter]?.(session) ?? true)) return;
|
|
569
|
+
let content = stripped.content;
|
|
570
|
+
if (quote?.content) content += " " + quote.content;
|
|
571
|
+
let params = null;
|
|
572
|
+
@@ -724,7 +840,7 @@ var Processor = class {
|
|
573
|
+
}
|
|
574
|
+
async attach(session, next) {
|
|
575
|
+
this.ctx.emit(session, "before-attach", session);
|
|
576
|
+
- if (this.ctx.database) {
|
|
577
|
+
+ if (this.ctx.get("database", false)) {
|
|
578
|
+
if (!session.isDirect) {
|
|
579
|
+
const channelFields = /* @__PURE__ */ new Set(["flag", "assignee", "guildId", "permissions", "locales"]);
|
|
580
|
+
this.ctx.emit("before-attach-channel", session, channelFields);
|
|
581
|
+
@@ -747,7 +863,7 @@ var Processor = class {
|
|
582
|
+
async _handleMessage(session) {
|
|
583
|
+
if (session.selfId === session.userId) return;
|
|
584
|
+
this._sessions[session.id] = session;
|
|
585
|
+
- const queue = this.ctx.lifecycle.filterHooks(this._hooks, session).map(({ callback }) => callback.bind(null, session));
|
|
586
|
+
+ const queue = kFilterHooks(this._hooks, session).map(({ callback }) => callback.bind(null, session));
|
|
587
|
+
let index = 0;
|
|
588
|
+
const next = /* @__PURE__ */ __name(async (callback) => {
|
|
589
|
+
try {
|
|
590
|
+
@@ -778,7 +894,14 @@ ${stack}`);
|
|
591
|
+
await session.user?.$update();
|
|
592
|
+
await session.channel?.$update();
|
|
593
|
+
await session.guild?.$update();
|
|
594
|
+
- this.ctx.emit(session, "middleware", session);
|
|
595
|
+
+ // chatluna: a throwing 'middleware' listener must not reject
|
|
596
|
+
+ // _handleMessage — the emit call site `void`s it, so a throw would escape
|
|
597
|
+
+ // as an unhandledRejection for every inbound message.
|
|
598
|
+
+ try {
|
|
599
|
+
+ this.ctx.emit(session, "middleware", session);
|
|
600
|
+
+ } catch (error) {
|
|
601
|
+
+ this.ctx.logger("session").warn(error);
|
|
602
|
+
+ }
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
};
|
|
606
|
+
@@ -843,7 +966,7 @@ var Command = class _Command extends Argv.CommandBase {
|
|
607
|
+
ctx.$commander._commandList.push(this);
|
|
608
|
+
}
|
|
609
|
+
get caller() {
|
|
610
|
+
- return this[Context.current] || this.ctx;
|
|
611
|
+
+ return this[kContextCurrent] || this.ctx;
|
|
612
|
+
}
|
|
613
|
+
get displayName() {
|
|
614
|
+
return Object.keys(this._aliases)[0];
|
|
615
|
+
@@ -971,7 +1094,7 @@ var Command = class _Command extends Argv.CommandBase {
|
|
616
|
+
return this;
|
|
617
|
+
}
|
|
618
|
+
match(session) {
|
|
619
|
+
- return this.ctx.filter(session);
|
|
620
|
+
+ return this.ctx[cordisSymbols.filter]?.(session) ?? true;
|
|
621
|
+
}
|
|
622
|
+
check(callback, append = false) {
|
|
623
|
+
return this.before(callback, append);
|
|
624
|
+
@@ -982,7 +1105,7 @@ var Command = class _Command extends Argv.CommandBase {
|
|
625
|
+
} else {
|
|
626
|
+
this._checkers.unshift(callback);
|
|
627
|
+
}
|
|
628
|
+
- this.caller.scope.disposables?.push(() => remove(this._checkers, callback));
|
|
629
|
+
+ this.caller.effect(() => () => remove(this._checkers, callback));
|
|
630
|
+
return this;
|
|
631
|
+
}
|
|
632
|
+
action(callback, prepend = false) {
|
|
633
|
+
@@ -991,7 +1114,7 @@ var Command = class _Command extends Argv.CommandBase {
|
|
634
|
+
} else {
|
|
635
|
+
this._actions.push(callback);
|
|
636
|
+
}
|
|
637
|
+
- this.caller.scope.disposables?.push(() => remove(this._actions, callback));
|
|
638
|
+
+ this.caller.effect(() => () => remove(this._actions, callback));
|
|
639
|
+
return this;
|
|
640
|
+
}
|
|
641
|
+
/** @deprecated */
|
|
642
|
+
@@ -1095,7 +1218,9 @@ __name(toStringType, "toStringType");
|
|
643
|
+
// src/command/validate.ts
|
|
644
|
+
import { isNullable as isNullable2 } from "cosmokit";
|
|
645
|
+
function validate(ctx) {
|
|
646
|
+
- ctx.permissions.define("command:(name)", {
|
|
647
|
+
+ const permissions = ctx.get("permissions", false);
|
|
648
|
+
+ if (!permissions) return;
|
|
649
|
+
+ permissions.define("command:(name)", {
|
|
650
|
+
depends: /* @__PURE__ */ __name(({ name }) => {
|
|
651
|
+
const command = ctx.$commander.get(name);
|
|
652
|
+
if (!command) return;
|
|
653
|
+
@@ -1110,7 +1235,7 @@ function validate(ctx) {
|
|
654
|
+
return ctx.$commander._commandList.map((command) => `command:${command.name}`);
|
|
655
|
+
}, "list")
|
|
656
|
+
});
|
|
657
|
+
- ctx.permissions.define("command:(name):option:(name2)", {
|
|
658
|
+
+ permissions.define("command:(name):option:(name2)", {
|
|
659
|
+
depends: /* @__PURE__ */ __name(({ name, name2 }) => {
|
|
660
|
+
return ctx.$commander.get(name)?._options[name2]?.dependencies;
|
|
661
|
+
}, "depends"),
|
|
662
|
+
@@ -1130,13 +1255,13 @@ function validate(ctx) {
|
|
663
|
+
return command.config.showWarning ? session.text(message, param) : "";
|
|
664
|
+
}
|
|
665
|
+
__name(sendHint, "sendHint");
|
|
666
|
+
- const permissions = [`command:${command.name}`];
|
|
667
|
+
+ const required = [`command:${command.name}`];
|
|
668
|
+
for (const option of Object.values(command._options)) {
|
|
669
|
+
if (option.name in options) {
|
|
670
|
+
- permissions.push(`command:${command.name}:option:${option.name}`);
|
|
671
|
+
+ required.push(`command:${command.name}:option:${option.name}`);
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
- if (!await ctx.permissions.test(permissions, session)) {
|
|
675
|
+
+ if (!await permissions.test(required, session)) {
|
|
676
|
+
return sendHint("internal.low-authority");
|
|
677
|
+
}
|
|
678
|
+
}, true);
|
|
679
|
+
@@ -1182,7 +1307,7 @@ var Commander = class {
|
|
680
|
+
constructor(ctx, config = {}) {
|
|
681
|
+
this.ctx = ctx;
|
|
682
|
+
this.config = config;
|
|
683
|
+
- defineProperty3(this, Context.current, ctx);
|
|
684
|
+
+ defineProperty3(this, kContextCurrent, ctx);
|
|
685
|
+
ctx.plugin(validate);
|
|
686
|
+
ctx.before("parse", (content, session) => {
|
|
687
|
+
const { isDirect, stripped: { prefix, appel } } = session;
|
|
688
|
+
@@ -1255,7 +1380,7 @@ var Commander = class {
|
|
689
|
+
permissions: Schema2.array(String).role("perms").default(["authority:0"]).description("权限继承。"),
|
|
690
|
+
dependencies: Schema2.array(String).role("perms").description("权限依赖。")
|
|
691
|
+
}), 1e3);
|
|
692
|
+
- ctx.on("ready", () => {
|
|
693
|
+
+ kOnReady(ctx, () => {
|
|
694
|
+
const bots = ctx.bots.filter((v) => v.status === Universal3.Status.ONLINE && v.updateCommands);
|
|
695
|
+
bots.forEach((bot) => this.updateCommands(bot));
|
|
696
|
+
});
|
|
697
|
+
@@ -1334,6 +1459,8 @@ var Commander = class {
|
|
698
|
+
static {
|
|
699
|
+
__name(this, "Commander");
|
|
700
|
+
}
|
|
701
|
+
+ // chatluna: resolve `this.ctx` to the calling plugin so its registrations are disposed with it.
|
|
702
|
+
+ [cordisSymbols.tracker] = { property: "ctx" };
|
|
703
|
+
_commandList = [];
|
|
704
|
+
defineElementDomain(name, key = name, type = name) {
|
|
705
|
+
this.domain(name, (source, session) => {
|
|
706
|
+
@@ -1456,13 +1583,14 @@ var Commander = class {
|
|
707
|
+
});
|
|
708
|
+
Object.assign(parent.config, config);
|
|
709
|
+
created.forEach((command) => this.ctx.emit("command-added", command));
|
|
710
|
+
- parent[Context.current] = this.ctx;
|
|
711
|
+
- if (root) this.ctx.collect(`command <${root.name}>`, () => root.dispose());
|
|
712
|
+
+ parent[kContextCurrent] = this.ctx;
|
|
713
|
+
+ if (root) kCollect(this.ctx, () => root.dispose());
|
|
714
|
+
return parent;
|
|
715
|
+
}
|
|
716
|
+
domain(name, transform, options) {
|
|
717
|
+
const service = "domain:" + name;
|
|
718
|
+
- if (!transform) return this.ctx.get(service);
|
|
719
|
+
+ if (!transform) return this.ctx.get(service, false);
|
|
720
|
+
+ this.ctx.provide(service, { transform, ...options });
|
|
721
|
+
return this.ctx.set(service, { transform, ...options });
|
|
722
|
+
}
|
|
723
|
+
resolveDomain(type) {
|
|
724
|
+
@@ -1570,6 +1698,8 @@ var I18n = class {
|
|
725
|
+
static {
|
|
726
|
+
__name(this, "I18n");
|
|
727
|
+
}
|
|
728
|
+
+ // chatluna: resolve `this.ctx` to the calling plugin so its registrations are disposed with it.
|
|
729
|
+
+ [cordisSymbols.tracker] = { property: "ctx" };
|
|
730
|
+
_data = {};
|
|
731
|
+
_presets = {};
|
|
732
|
+
locales;
|
|
733
|
+
@@ -1613,7 +1743,7 @@ var I18n = class {
|
|
734
|
+
const dict = this._data[locale] ||= {};
|
|
735
|
+
const paths = [...typeof args[0] === "string" ? this.set(locale, args[0] + ".", args[1]) : this.set(locale, "", args[0])];
|
|
736
|
+
this.ctx.emit("internal/i18n");
|
|
737
|
+
- return this.ctx.collect("i18n", () => {
|
|
738
|
+
+ return kCollect(this.ctx, () => {
|
|
739
|
+
for (const path2 of paths) {
|
|
740
|
+
delete dict[path2];
|
|
741
|
+
}
|
|
742
|
+
@@ -1680,7 +1810,7 @@ var I18n = class {
|
|
743
|
+
import { observe } from "@koishijs/utils";
|
|
744
|
+
import { isNullable as isNullable4, makeArray as makeArray2 } from "cosmokit";
|
|
745
|
+
import { h as h5, Logger as Logger3 } from "@satorijs/core";
|
|
746
|
+
-import { executeEval, isEvalExpr } from "minato";
|
|
747
|
+
+import { executeEval, isEvalExpr } from "@cordisjs/plugin-database";
|
|
748
|
+
var logger3 = new Logger3("session");
|
|
749
|
+
function collectFields(argv, collectors, fields) {
|
|
750
|
+
for (const collector of collectors) {
|
|
751
|
+
@@ -1700,7 +1830,8 @@ var KoishiSession = class {
|
|
752
|
+
__name(this, "KoishiSession");
|
|
753
|
+
}
|
|
754
|
+
constructor(ctx) {
|
|
755
|
+
- ctx.mixin(this, {
|
|
756
|
+
+ this.ctx = ctx;
|
|
757
|
+
+ kMixinFrom(ctx, this, {
|
|
758
|
+
resolve: "session.resolve",
|
|
759
|
+
stripped: "session.stripped",
|
|
760
|
+
username: "session.username",
|
|
761
|
+
@@ -1969,7 +2100,7 @@ var KoishiSession = class {
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
const { command } = argv;
|
|
765
|
+
- if (!command.ctx.filter(this)) return [];
|
|
766
|
+
+ if (!(command.ctx[cordisSymbols.filter]?.(this) ?? true)) return [];
|
|
767
|
+
if (this.app.database) {
|
|
768
|
+
if (!this.isDirect) {
|
|
769
|
+
await this.observeChannel(this.collect("channel", argv, /* @__PURE__ */ new Set(["permissions", "locales"])));
|
|
770
|
+
@@ -2058,8 +2189,7 @@ var logger4 = new Logger4("app");
|
|
771
|
+
var Permissions = class {
|
|
772
|
+
constructor(ctx) {
|
|
773
|
+
this.ctx = ctx;
|
|
774
|
+
- defineProperty4(this, Context.current, ctx);
|
|
775
|
+
- ctx.alias("permissions", ["perms"]);
|
|
776
|
+
+ defineProperty4(this, kContextCurrent, ctx);
|
|
777
|
+
this.define("authority:(value)", {
|
|
778
|
+
check: /* @__PURE__ */ __name(({ value }, { user }) => {
|
|
779
|
+
return !user || user.authority >= +value;
|
|
780
|
+
@@ -2076,6 +2206,8 @@ var Permissions = class {
|
|
781
|
+
static {
|
|
782
|
+
__name(this, "Permissions");
|
|
783
|
+
}
|
|
784
|
+
+ // chatluna: resolve `this.ctx` to the calling plugin so its registrations are disposed with it.
|
|
785
|
+
+ [cordisSymbols.tracker] = { property: "ctx" };
|
|
786
|
+
store = [];
|
|
787
|
+
define(pattern, options) {
|
|
788
|
+
const entry = {
|
|
789
|
+
@@ -2167,7 +2299,8 @@ var KoishiBot = class {
|
|
790
|
+
__name(this, "KoishiBot");
|
|
791
|
+
}
|
|
792
|
+
constructor(ctx) {
|
|
793
|
+
- ctx.mixin(this, {
|
|
794
|
+
+ this.ctx = ctx;
|
|
795
|
+
+ kMixinFrom(ctx, this, {
|
|
796
|
+
getGuildMemberMap: "bot.getGuildMemberMap",
|
|
797
|
+
broadcast: "bot.broadcast"
|
|
798
|
+
});
|
|
799
|
+
@@ -2238,9 +2371,11 @@ var SchemaService = class {
|
|
800
|
+
static {
|
|
801
|
+
__name(this, "SchemaService");
|
|
802
|
+
}
|
|
803
|
+
+ // chatluna: resolve `this.ctx` to the calling plugin so its registrations are disposed with it.
|
|
804
|
+
+ [cordisSymbols.tracker] = { property: "ctx" };
|
|
805
|
+
_data = /* @__PURE__ */ Object.create(null);
|
|
806
|
+
extend(name, schema, order = 0) {
|
|
807
|
+
- const caller = this[Context.current];
|
|
808
|
+
+ const caller = this.ctx;
|
|
809
|
+
const target = this.get(name);
|
|
810
|
+
const index = target.list.findIndex((a) => a[kSchemaOrder] < order);
|
|
811
|
+
schema[kSchemaOrder] = order;
|
|
812
|
+
@@ -2250,7 +2385,7 @@ var SchemaService = class {
|
|
813
|
+
target.list.push(schema);
|
|
814
|
+
}
|
|
815
|
+
this.ctx.emit("internal/schema", name);
|
|
816
|
+
- caller?.on("dispose", () => {
|
|
817
|
+
+ caller?.effect(() => () => {
|
|
818
|
+
remove3(target.list, schema);
|
|
819
|
+
this.ctx.emit("internal/schema", name);
|
|
820
|
+
});
|
|
821
|
+
@@ -2259,10 +2394,10 @@ var SchemaService = class {
|
|
822
|
+
return this._data[name] ||= Schema4.intersect([]);
|
|
823
|
+
}
|
|
824
|
+
set(name, schema) {
|
|
825
|
+
- const caller = this[Context.current];
|
|
826
|
+
+ const caller = this.ctx;
|
|
827
|
+
this._data[name] = schema;
|
|
828
|
+
this.ctx.emit("internal/schema", name);
|
|
829
|
+
- caller?.on("dispose", () => {
|
|
830
|
+
+ caller?.effect(() => () => {
|
|
831
|
+
delete this._data[name];
|
|
832
|
+
this.ctx.emit("internal/schema", name);
|
|
833
|
+
});
|
|
834
|
+
@@ -2272,6 +2407,95 @@ var SchemaService = class {
|
|
835
|
+
// src/context.ts
|
|
836
|
+
import { Adapter as Adapter2, Bot as Bot3, Element, h as h6, HTTP as HTTP2, Logger as Logger5, MessageEncoder, Messenger, Quester, Schema as Schema6, segment, Universal as Universal5, z } from "@satorijs/core";
|
|
837
|
+
import { resolveConfig } from "cordis";
|
|
838
|
+
+// chatluna: install Koishi capabilities onto an existing Cordis 4 context.
|
|
839
|
+
+// Called from Koishi's constructor; Context's own constructor delegates here too.
|
|
840
|
+
+function installKoishi(ctx, config) {
|
|
841
|
+
+ // Cordis 3 compat accessors: resolve lazily through the accessing fiber so
|
|
842
|
+
+ // lifecycle-scoped APIs (before/on) bind to the caller, not this service.
|
|
843
|
+
+ ctx.accessor("before", {
|
|
844
|
+
+ get() {
|
|
845
|
+
+ const self = this;
|
|
846
|
+
+ return (name, listener, append = false) => {
|
|
847
|
+
+ const seg = name.split("/");
|
|
848
|
+
+ seg[seg.length - 1] = "before-" + seg[seg.length - 1];
|
|
849
|
+
+ return self.on(seg.join("/"), listener, !append);
|
|
850
|
+
+ };
|
|
851
|
+
+ }
|
|
852
|
+
+ });
|
|
853
|
+
+ ctx.accessor("filter", {
|
|
854
|
+
+ get() {
|
|
855
|
+
+ const self = this;
|
|
856
|
+
+ return (session) => self[cordisSymbols.filter]?.(session) ?? true;
|
|
857
|
+
+ }
|
|
858
|
+
+ });
|
|
859
|
+
+ ctx.accessor("app", {
|
|
860
|
+
+ get() {
|
|
861
|
+
+ return this[cordis.Context.root] ?? this;
|
|
862
|
+
+ }
|
|
863
|
+
+ });
|
|
864
|
+
+ ctx.accessor("root", {
|
|
865
|
+
+ get() {
|
|
866
|
+
+ return this[cordis.Context.root] ?? this;
|
|
867
|
+
+ }
|
|
868
|
+
+ });
|
|
869
|
+
+ // Koishi plugins read app-level settings through ctx.config / ctx.root.config;
|
|
870
|
+
+ // both resolve to the Koishi service config regardless of the accessing fiber.
|
|
871
|
+
+ ctx.accessor("config", {
|
|
872
|
+
+ get() {
|
|
873
|
+
+ return this.get("koishi", false)?.config ?? this.fiber?.config;
|
|
874
|
+
+ }
|
|
875
|
+
+ });
|
|
876
|
+
+ ctx.accessor("options", {
|
|
877
|
+
+ get() {
|
|
878
|
+
+ return this.get("koishi", false)?.config ?? this.fiber?.config;
|
|
879
|
+
+ }
|
|
880
|
+
+ });
|
|
881
|
+
+ ctx.accessor("collect", {
|
|
882
|
+
+ get() {
|
|
883
|
+
+ const self = this;
|
|
884
|
+
+ return (_name, dispose) => kCollect(self, dispose);
|
|
885
|
+
+ }
|
|
886
|
+
+ });
|
|
887
|
+
+ ctx.accessor("scope", {
|
|
888
|
+
+ get() {
|
|
889
|
+
+ return this.fiber;
|
|
890
|
+
+ }
|
|
891
|
+
+ });
|
|
892
|
+
+ // Cordis 3 resolved ctx.<service> against a global service set; cordis 4 only
|
|
893
|
+
+ // resolves provisions of the accessing fiber's ancestors and declared injects.
|
|
894
|
+
+ // Restore the global lookup so koishi internals (ctx.model, ctx.bots,
|
|
895
|
+
+ // ctx.permissions, ...) work on every fiber regardless of inject declarations.
|
|
896
|
+
+ ctx.events.on("internal/get", (self, name, error, next) => self.get(name, false) ?? next());
|
|
897
|
+
+ // Mount satori and minato as direct service constructions rather than plugin
|
|
898
|
+
+ // fibers: ctx.plugin applies asynchronously, but koishi internals touch
|
|
899
|
+
+ // ctx.model and ctx.component during construction. Providing them on this
|
|
900
|
+
+ // fiber also makes them reachable through locate() for every koishi plugin.
|
|
901
|
+
+ if (!ctx.get("satori", false)) new satori.Satori(ctx);
|
|
902
|
+
+ ctx.mixin("$processor", ["match", "middleware"]);
|
|
903
|
+
+ ctx.mixin("$filter", [
|
|
904
|
+
+ "any",
|
|
905
|
+
+ "never",
|
|
906
|
+
+ "union",
|
|
907
|
+
+ "intersect",
|
|
908
|
+
+ "exclude",
|
|
909
|
+
+ "user",
|
|
910
|
+
+ "self",
|
|
911
|
+
+ "guild",
|
|
912
|
+
+ "channel",
|
|
913
|
+
+ "platform",
|
|
914
|
+
+ "private"
|
|
915
|
+
+ ]);
|
|
916
|
+
+ ctx.mixin("$commander", ["command"]);
|
|
917
|
+
+ ctx.provide("$filter", new FilterService(ctx));
|
|
918
|
+
+ ctx.provide("schema", new SchemaService(ctx));
|
|
919
|
+
+ ctx.provide("$processor", new Processor(ctx));
|
|
920
|
+
+ ctx.provide("i18n", new I18n(ctx, config.i18n));
|
|
921
|
+
+ ctx.provide("$commander", new Commander(ctx, config));
|
|
922
|
+
+ // chatluna: `http`/`server` come from @cordisjs/plugin-http and
|
|
923
|
+
+ // @cordisjs/plugin-server mounted by the host, `model` from the manifest's
|
|
924
|
+
+ // @cordisjs/plugin-database (the Koishi service injects it), and
|
|
925
|
+
+ // `permissions` from @chatluna/permission instead of koishi's own implementations.
|
|
926
|
+
+}
|
|
927
|
+
var Context = class extends satori.Context {
|
|
928
|
+
static {
|
|
929
|
+
__name(this, "Context");
|
|
930
|
+
@@ -2279,31 +2503,8 @@ var Context = class extends satori.Context {
|
|
931
|
+
static shadow = /* @__PURE__ */ Symbol.for("session.shadow");
|
|
932
|
+
constructor(config = {}) {
|
|
933
|
+
super(config);
|
|
934
|
+
- this.mixin("$processor", ["match", "middleware"]);
|
|
935
|
+
- this.mixin("$filter", [
|
|
936
|
+
- "any",
|
|
937
|
+
- "never",
|
|
938
|
+
- "union",
|
|
939
|
+
- "intersect",
|
|
940
|
+
- "exclude",
|
|
941
|
+
- "user",
|
|
942
|
+
- "self",
|
|
943
|
+
- "guild",
|
|
944
|
+
- "channel",
|
|
945
|
+
- "platform",
|
|
946
|
+
- "private"
|
|
947
|
+
- ]);
|
|
948
|
+
- this.mixin("$commander", ["command"]);
|
|
949
|
+
- this.provide("$filter", new FilterService(this), true);
|
|
950
|
+
- this.provide("schema", new SchemaService(this), true);
|
|
951
|
+
- this.provide("$processor", new Processor(this), true);
|
|
952
|
+
- this.provide("i18n", new I18n(this, this.config.i18n), true);
|
|
953
|
+
- this.provide("permissions", new Permissions(this), true);
|
|
954
|
+
- this.provide("model", void 0, true);
|
|
955
|
+
- this.provide("http", void 0, true);
|
|
956
|
+
- this.provide("$commander", new Commander(this, this.config), true);
|
|
957
|
+
- this.plugin(minato.Database);
|
|
958
|
+
- this.plugin(Koishi, this.config);
|
|
959
|
+
+ installKoishi(this, config);
|
|
960
|
+
+ this.plugin(Koishi, config);
|
|
961
|
+
}
|
|
962
|
+
/** @deprecated use `ctx.root` instead */
|
|
963
|
+
get app() {
|
|
964
|
+
@@ -2313,25 +2514,6 @@ var Context = class extends satori.Context {
|
|
965
|
+
get options() {
|
|
966
|
+
return this.root.config;
|
|
967
|
+
}
|
|
968
|
+
- async waterfall(...args) {
|
|
969
|
+
- const thisArg = typeof args[0] === "object" || typeof args[0] === "function" ? args.shift() : null;
|
|
970
|
+
- const name = args.shift();
|
|
971
|
+
- for (const hook of this.lifecycle.filterHooks(this.lifecycle._hooks[name] || [], thisArg)) {
|
|
972
|
+
- const result = await hook.callback.apply(thisArg, args);
|
|
973
|
+
- args[0] = result;
|
|
974
|
+
- }
|
|
975
|
+
- return args[0];
|
|
976
|
+
- }
|
|
977
|
+
- chain(...args) {
|
|
978
|
+
- const thisArg = typeof args[0] === "object" || typeof args[0] === "function" ? args.shift() : null;
|
|
979
|
+
- const name = args.shift();
|
|
980
|
+
- for (const hook of this.lifecycle.filterHooks(this.lifecycle._hooks[name] || [], thisArg)) {
|
|
981
|
+
- const result = hook.callback.apply(thisArg, args);
|
|
982
|
+
- args[0] = result;
|
|
983
|
+
- }
|
|
984
|
+
- return args[0];
|
|
985
|
+
- }
|
|
986
|
+
- /* eslint-enable max-len */
|
|
987
|
+
before(name, listener, append = false) {
|
|
988
|
+
const seg = name.split("/");
|
|
989
|
+
seg[seg.length - 1] = "before-" + seg[seg.length - 1];
|
|
990
|
+
@@ -2339,19 +2521,36 @@ var Context = class extends satori.Context {
|
|
991
|
+
}
|
|
992
|
+
};
|
|
993
|
+
var Koishi = class extends cordis.Service {
|
|
994
|
+
- constructor(ctx, config) {
|
|
995
|
+
- super(ctx, "koishi", true);
|
|
996
|
+
+ // KoishiDatabase extends ctx.model on construction; only the manifest's database plugin owns it.
|
|
997
|
+
+ static inject = ["model"];
|
|
998
|
+
+ // Context.Config's intersect list is populated after this class is defined;
|
|
999
|
+
+ // defer to it through a getter.
|
|
1000
|
+
+ static get Config() {
|
|
1001
|
+
+ return Context.Config;
|
|
1002
|
+
+ }
|
|
1003
|
+
+ get commander() {
|
|
1004
|
+
+ return this.ctx.get("$commander", false);
|
|
1005
|
+
+ }
|
|
1006
|
+
+ constructor(ctx, config = {}) {
|
|
1007
|
+
+ super(ctx, "koishi");
|
|
1008
|
+
this.config = config;
|
|
1009
|
+
+ // The service mounts Koishi onto whatever Cordis 4 context loaded it,
|
|
1010
|
+
+ // rather than requiring a Koishi-flavored root Context. installKoishi must
|
|
1011
|
+
+ // run before the mixin fields: KoishiDatabase touches ctx.model.
|
|
1012
|
+
+ installKoishi(ctx, config);
|
|
1013
|
+
+ this.bot = new bot_default(this.ctx);
|
|
1014
|
+
+ this.database = new database_default(this.ctx);
|
|
1015
|
+
+ this.session = new session_default(this.ctx);
|
|
1016
|
+
}
|
|
1017
|
+
static {
|
|
1018
|
+
__name(this, "Koishi");
|
|
1019
|
+
}
|
|
1020
|
+
- bot = new bot_default(this.ctx);
|
|
1021
|
+
- database = new database_default(this.ctx);
|
|
1022
|
+
- session = new session_default(this.ctx);
|
|
1023
|
+
+ bot;
|
|
1024
|
+
+ database;
|
|
1025
|
+
+ session;
|
|
1026
|
+
};
|
|
1027
|
+
-satori.Session.prototype[Context.filter] = function(ctx) {
|
|
1028
|
+
- return ctx.filter(this);
|
|
1029
|
+
+satori.Session.prototype[cordis.Context.filter] = function(ctx) {
|
|
1030
|
+
+ return ctx[cordisSymbols.filter]?.(this) ?? true;
|
|
1031
|
+
};
|
|
1032
|
+
((Context3) => {
|
|
1033
|
+
Context3.Config = Schema5.intersect([
|
|
1034
|
+
@@ -2399,12 +2598,15 @@ var Service3 = class extends satori.Service {
|
|
1035
|
+
this.ctx = new Context();
|
|
1036
|
+
}
|
|
1037
|
+
};
|
|
1038
|
+
+const Session = satori.Session;
|
|
1039
|
+
function defineConfig(config) {
|
|
1040
|
+
return config;
|
|
1041
|
+
}
|
|
1042
|
+
__name(defineConfig, "defineConfig");
|
|
1043
|
+
export {
|
|
1044
|
+
Adapter2 as Adapter,
|
|
1045
|
+
+ Koishi,
|
|
1046
|
+
+ Koishi as default,
|
|
1047
|
+
Context as App,
|
|
1048
|
+
Argv,
|
|
1049
|
+
Bot3 as Bot,
|
|
1050
|
+
@@ -2426,6 +2628,7 @@ export {
|
|
1051
|
+
Schema6 as Schema,
|
|
1052
|
+
SchemaService,
|
|
1053
|
+
Service3 as Service,
|
|
1054
|
+
+ Session,
|
|
1055
|
+
SessionError,
|
|
1056
|
+
SharedCache,
|
|
1057
|
+
Universal5 as Universal,
|
|
1058
|
+
diff --git a/package.json b/package.json
|
|
1059
|
+
index 7775412..0d49847 100644
|
|
1060
|
+
--- a/package.json
|
|
1061
|
+
+++ b/package.json
|
|
1062
|
+
@@ -2,7 +2,7 @@
|
|
1063
|
+
"name": "@koishijs/core",
|
|
1064
|
+
"description": "Core Features for Koishi",
|
|
1065
|
+
"version": "4.18.11",
|
|
1066
|
+
- "main": "lib/index.cjs",
|
|
1067
|
+
+ "main": "lib/index.mjs",
|
|
1068
|
+
"module": "lib/index.mjs",
|
|
1069
|
+
"typings": "lib/index.d.ts",
|
|
1070
|
+
"files": [
|
|
1071
|
+
@@ -37,9 +37,18 @@
|
|
1072
|
+
"@koishijs/i18n-utils": "^1.0.1",
|
|
1073
|
+
"@koishijs/utils": "^7.2.1",
|
|
1074
|
+
"@satorijs/core": "^4.6.0",
|
|
1075
|
+
- "cordis": "^3.18.1",
|
|
1076
|
+
+ "cordis": "^4.0.0-rc.8",
|
|
1077
|
+
"cosmokit": "^1.8.1",
|
|
1078
|
+
"fastest-levenshtein": "^1.0.16",
|
|
1079
|
+
- "minato": "^3.7.0"
|
|
1080
|
+
+ "@cordisjs/plugin-database": "4.1.1"
|
|
1081
|
+
+ },
|
|
1082
|
+
+ "exports": {
|
|
1083
|
+
+ ".": {
|
|
1084
|
+
+ "types": "./lib/index.d.ts",
|
|
1085
|
+
+ "require": "./lib/index.mjs",
|
|
1086
|
+
+ "import": "./lib/index.mjs"
|
|
1087
|
+
+ },
|
|
1088
|
+
+ "./src/*": "./src/*",
|
|
1089
|
+
+ "./package.json": "./package.json"
|
|
1090
|
+
}
|
|
1091
|
+
}
|
|
1092
|
+
|