@zhin.js/core 1.0.0 → 1.0.1
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/CHANGELOG.md +9 -0
- package/LICENSE +21 -0
- package/README.md +295 -74
- package/lib/adapter.d.ts +39 -0
- package/lib/adapter.d.ts.map +1 -0
- package/{dist → lib}/adapter.js +20 -2
- package/lib/adapter.js.map +1 -0
- package/lib/app.d.ts +115 -0
- package/lib/app.d.ts.map +1 -0
- package/{dist → lib}/app.js +148 -78
- package/lib/app.js.map +1 -0
- package/lib/bot.d.ts +31 -0
- package/lib/bot.d.ts.map +1 -0
- package/lib/command.d.ts +32 -0
- package/lib/command.d.ts.map +1 -0
- package/lib/command.js +46 -0
- package/lib/command.js.map +1 -0
- package/lib/component.d.ts +107 -0
- package/lib/component.d.ts.map +1 -0
- package/lib/component.js +273 -0
- package/lib/component.js.map +1 -0
- package/{dist → lib}/config.d.ts.map +1 -1
- package/{dist → lib}/config.js +6 -9
- package/lib/config.js.map +1 -0
- package/lib/cron.d.ts +81 -0
- package/lib/cron.d.ts.map +1 -0
- package/lib/cron.js +159 -0
- package/lib/cron.js.map +1 -0
- package/lib/errors.d.ts +165 -0
- package/lib/errors.d.ts.map +1 -0
- package/lib/errors.js +306 -0
- package/lib/errors.js.map +1 -0
- package/lib/index.d.ts +15 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +17 -0
- package/lib/index.js.map +1 -0
- package/lib/message.d.ts +44 -0
- package/lib/message.d.ts.map +1 -0
- package/lib/message.js +11 -0
- package/lib/message.js.map +1 -0
- package/lib/plugin.d.ts +50 -0
- package/lib/plugin.d.ts.map +1 -0
- package/lib/plugin.js +170 -0
- package/lib/plugin.js.map +1 -0
- package/lib/prompt.d.ts +116 -0
- package/lib/prompt.d.ts.map +1 -0
- package/lib/prompt.js +240 -0
- package/lib/prompt.js.map +1 -0
- package/lib/schema.d.ts +83 -0
- package/lib/schema.d.ts.map +1 -0
- package/lib/schema.js +245 -0
- package/lib/schema.js.map +1 -0
- package/{dist → lib}/types-generator.d.ts.map +1 -1
- package/{dist → lib}/types-generator.js +6 -3
- package/lib/types-generator.js.map +1 -0
- package/lib/types.d.ts +119 -0
- package/lib/types.d.ts.map +1 -0
- package/lib/utils.d.ts +52 -0
- package/lib/utils.d.ts.map +1 -0
- package/lib/utils.js +338 -0
- package/lib/utils.js.map +1 -0
- package/package.json +15 -9
- package/src/adapter.ts +25 -9
- package/src/app.ts +363 -258
- package/src/bot.ts +29 -8
- package/src/command.ts +50 -0
- package/src/component.ts +318 -0
- package/src/config.ts +9 -12
- package/src/cron.ts +176 -0
- package/src/errors.ts +365 -0
- package/src/index.ts +16 -13
- package/src/message.ts +44 -0
- package/src/plugin.ts +148 -66
- package/src/prompt.ts +290 -0
- package/src/schema.ts +273 -0
- package/src/types-generator.ts +7 -3
- package/src/types.ts +77 -30
- package/src/utils.ts +312 -0
- package/tests/adapter.test.ts +36 -22
- package/tests/app.test.ts +30 -0
- package/tests/command.test.ts +545 -0
- package/tests/component.test.ts +656 -0
- package/tests/config.test.ts +1 -1
- package/tests/errors.test.ts +311 -0
- package/tests/message.test.ts +402 -0
- package/tests/plugin.test.ts +275 -143
- package/tests/utils.test.ts +80 -0
- package/tsconfig.json +3 -4
- package/dist/adapter.d.ts +0 -22
- package/dist/adapter.d.ts.map +0 -1
- package/dist/adapter.js.map +0 -1
- package/dist/app.d.ts +0 -69
- package/dist/app.d.ts.map +0 -1
- package/dist/app.js.map +0 -1
- package/dist/bot.d.ts +0 -9
- package/dist/bot.d.ts.map +0 -1
- package/dist/config.js.map +0 -1
- package/dist/index.d.ts +0 -9
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -12
- package/dist/index.js.map +0 -1
- package/dist/logger.d.ts +0 -3
- package/dist/logger.d.ts.map +0 -1
- package/dist/logger.js +0 -3
- package/dist/logger.js.map +0 -1
- package/dist/plugin.d.ts +0 -41
- package/dist/plugin.d.ts.map +0 -1
- package/dist/plugin.js +0 -95
- package/dist/plugin.js.map +0 -1
- package/dist/types-generator.js.map +0 -1
- package/dist/types.d.ts +0 -69
- package/dist/types.d.ts.map +0 -1
- package/src/logger.ts +0 -3
- package/tests/logger.test.ts +0 -170
- package/tsconfig.tsbuildinfo +0 -1
- /package/{dist → lib}/bot.js +0 -0
- /package/{dist → lib}/bot.js.map +0 -0
- /package/{dist → lib}/config.d.ts +0 -0
- /package/{dist → lib}/types-generator.d.ts +0 -0
- /package/{dist → lib}/types.js +0 -0
- /package/{dist → lib}/types.js.map +0 -0
package/lib/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,eAAe;AACf,cAAc,UAAU,CAAA;AACxB,cAAc,UAAU,CAAA;AACxB,cAAc,aAAa,CAAA;AAC3B,cAAc,cAAc,CAAA;AAC5B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,cAAc,CAAA;AAC5B,cAAc,aAAa,CAAA;AAC3B,cAAc,cAAc,CAAA;AAC5B,0CAA0C;AAC1C,cAAc,YAAY,CAAA;AAC1B,cAAc,YAAY,CAAA;AAC1B,cAAc,aAAa,CAAA,CAAE,WAAW;AACxC,cAAc,WAAW,CAAA;AACzB,cAAc,mBAAmB,CAAA;AAEjC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA"}
|
package/lib/message.d.ts
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { MaybePromise } from "@zhin.js/types";
|
|
2
|
+
import { MessageSegment, MessageSender, SendContent } from "./types";
|
|
3
|
+
/**
|
|
4
|
+
* 消息组件类型:用于自定义消息结构
|
|
5
|
+
*/
|
|
6
|
+
export type MessageComponent<T extends object> = (props: T & {
|
|
7
|
+
children: SendContent;
|
|
8
|
+
}) => MaybePromise<SendContent>;
|
|
9
|
+
/**
|
|
10
|
+
* 消息频道信息
|
|
11
|
+
*/
|
|
12
|
+
export interface MessageChannel {
|
|
13
|
+
id: string;
|
|
14
|
+
type: MessageType;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* 消息类型枚举
|
|
18
|
+
*/
|
|
19
|
+
export type MessageType = 'group' | 'private' | 'channel';
|
|
20
|
+
/**
|
|
21
|
+
* 消息基础结构
|
|
22
|
+
*/
|
|
23
|
+
export interface MessageBase {
|
|
24
|
+
$id: string;
|
|
25
|
+
$adapter: string;
|
|
26
|
+
$bot: string;
|
|
27
|
+
$content: MessageSegment[];
|
|
28
|
+
$sender: MessageSender;
|
|
29
|
+
$reply(content: SendContent, quote?: boolean | string): Promise<void>;
|
|
30
|
+
$channel: MessageChannel;
|
|
31
|
+
$timestamp: number;
|
|
32
|
+
$raw: string;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* 完整消息类型,支持扩展
|
|
36
|
+
*/
|
|
37
|
+
export type Message<T extends object = {}> = MessageBase & T;
|
|
38
|
+
export declare namespace Message {
|
|
39
|
+
/**
|
|
40
|
+
* 工具方法:合并自定义字段与基础消息结构
|
|
41
|
+
*/
|
|
42
|
+
function from<T extends object>(input: T, format: MessageBase): Message<T>;
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=message.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message.d.ts","sourceRoot":"","sources":["../src/message.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,YAAY,EAAC,MAAM,gBAAgB,CAAC;AAC5C,OAAO,EAAC,cAAc,EAAE,aAAa,EAAqB,WAAW,EAAC,MAAM,SAAS,CAAC;AAEtF;;GAEG;AACH,MAAM,MAAM,gBAAgB,CAAC,CAAC,SAAS,MAAM,IAAE,CAAC,KAAK,EAAC,CAAC,GAAC;IAAC,QAAQ,EAAC,WAAW,CAAA;CAAC,KAAG,YAAY,CAAC,WAAW,CAAC,CAAA;AAC1G;;GAEG;AACH,MAAM,WAAW,cAAc;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,WAAW,CAAC;CACrB;AACD;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG,OAAO,GAAG,SAAS,GAAG,SAAS,CAAA;AACzD;;GAEG;AACH,MAAM,WAAW,WAAW;IACxB,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAC,MAAM,CAAA;IACf,IAAI,EAAC,MAAM,CAAA;IACX,QAAQ,EAAE,cAAc,EAAE,CAAC;IAC3B,OAAO,EAAE,aAAa,CAAC;IACvB,MAAM,CAAC,OAAO,EAAC,WAAW,EAAC,KAAK,CAAC,EAAC,OAAO,GAAC,MAAM,GAAE,OAAO,CAAC,IAAI,CAAC,CAAA;IAC/D,QAAQ,EAAE,cAAc,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;CAChB;AACD;;GAEG;AACH,MAAM,MAAM,OAAO,CAAC,CAAC,SAAS,MAAM,GAAC,EAAE,IAAE,WAAW,GAAC,CAAC,CAAC;AACvD,yBAAiB,OAAO,CAAA;IACpB;;OAEG;IACH,SAAgB,IAAI,CAAC,CAAC,SAAS,MAAM,EAAE,KAAK,EAAC,CAAC,EAAC,MAAM,EAAC,WAAW,GAAE,OAAO,CAAC,CAAC,CAAC,CAE5E;CACJ"}
|
package/lib/message.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message.js","sourceRoot":"","sources":["../src/message.ts"],"names":[],"mappings":"AAoCA,MAAM,KAAW,OAAO,CAOvB;AAPD,WAAiB,OAAO;IACpB;;OAEG;IACH,SAAgB,IAAI,CAAmB,KAAO,EAAC,MAAkB;QAC7D,OAAO,MAAM,CAAC,MAAM,CAAC,KAAK,EAAC,MAAM,CAAC,CAAA;IACtC,CAAC;IAFe,YAAI,OAEnB,CAAA;AACL,CAAC,EAPgB,OAAO,KAAP,OAAO,QAOvB"}
|
package/lib/plugin.d.ts
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { MaybePromise } from '@zhin.js/types';
|
|
2
|
+
import { AdapterMessage, BeforeSendHandler, RegisteredAdapter, SendOptions } from "./types.js";
|
|
3
|
+
import { Message } from './message.js';
|
|
4
|
+
import { Dependency, Logger } from "@zhin.js/hmr";
|
|
5
|
+
import { App } from "./app";
|
|
6
|
+
import { MessageCommand } from "./command.js";
|
|
7
|
+
import { Component } from "./component.js";
|
|
8
|
+
import { Prompt } from "./prompt.js";
|
|
9
|
+
import { Schema } from '@zhin.js/database';
|
|
10
|
+
import { Cron } from './cron.js';
|
|
11
|
+
/** 消息中间件函数 */
|
|
12
|
+
export type MessageMiddleware<P extends RegisteredAdapter = RegisteredAdapter> = (message: Message<AdapterMessage<P>>, next: () => Promise<void>) => MaybePromise<void>;
|
|
13
|
+
/**
|
|
14
|
+
* 插件类:继承自 Dependency,提供机器人特定功能与生命周期管理。
|
|
15
|
+
* 支持命令注册、中间件、组件、定时任务、模型等。
|
|
16
|
+
*/
|
|
17
|
+
export declare class Plugin extends Dependency<Plugin> {
|
|
18
|
+
#private;
|
|
19
|
+
middlewares: MessageMiddleware<any>[];
|
|
20
|
+
components: Map<string, Component<any, any, any>>;
|
|
21
|
+
schemas: Map<string, Schema<any>>;
|
|
22
|
+
commands: MessageCommand[];
|
|
23
|
+
crons: Cron[];
|
|
24
|
+
/**
|
|
25
|
+
* 构造函数:初始化插件,注册消息事件、命令中间件、资源清理等
|
|
26
|
+
* @param parent 所属 App 实例
|
|
27
|
+
* @param name 插件名
|
|
28
|
+
* @param filePath 插件文件路径
|
|
29
|
+
*/
|
|
30
|
+
constructor(parent: Dependency<Plugin>, name: string, filePath: string);
|
|
31
|
+
cron(cronExpression: string, callback: () => void): this;
|
|
32
|
+
defineModel<S extends Record<string, any>>(name: string, schema: Schema<S>): this;
|
|
33
|
+
beforeSend(handler: BeforeSendHandler): void;
|
|
34
|
+
before(event: string, listener: (...args: any[]) => any): void;
|
|
35
|
+
/** 获取所属的App实例 */
|
|
36
|
+
get app(): App;
|
|
37
|
+
get logger(): Logger;
|
|
38
|
+
/** 添加组件 */
|
|
39
|
+
addComponent<T = {}, D = {}, P = Component.Props<T>>(component: Component<T, D, P>): void;
|
|
40
|
+
/** 添加中间件 */
|
|
41
|
+
addCommand(command: MessageCommand): void;
|
|
42
|
+
/** 添加中间件 */
|
|
43
|
+
addMiddleware<T extends RegisteredAdapter>(middleware: MessageMiddleware<T>): () => void;
|
|
44
|
+
prompt<P extends RegisteredAdapter>(message: Message<AdapterMessage<P>>): Prompt<P>;
|
|
45
|
+
/** 发送消息 */
|
|
46
|
+
sendMessage(options: SendOptions): Promise<void>;
|
|
47
|
+
/** 销毁插件 */
|
|
48
|
+
dispose(): void;
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=plugin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAKA,OAAO,EAAC,YAAY,EAAC,MAAM,gBAAgB,CAAA;AAC3C,OAAO,EAAC,cAAc,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,WAAW,EAAC,MAAM,YAAY,CAAC;AAC7F,OAAO,EAAC,OAAO,EAAC,MAAM,cAAc,CAAA;AACpC,OAAO,EAAC,UAAU,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,EAAC,GAAG,EAAC,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAC,cAAc,EAAC,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAC,SAAS,EAAC,MAAM,gBAAgB,CAAC;AAGzC,OAAO,EAAC,MAAM,EAAC,MAAM,aAAa,CAAC;AACnC,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC3C,OAAO,EAAE,IAAI,EAAC,MAAM,WAAW,CAAC;AAEhC,cAAc;AACd,MAAM,MAAM,iBAAiB,CAAC,CAAC,SAAS,iBAAiB,GAAC,iBAAiB,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,KAAK,YAAY,CAAC,IAAI,CAAC,CAAC;AAOtK;;;GAGG;AACH,qBAAa,MAAO,SAAQ,UAAU,CAAC,MAAM,CAAC;;IAC1C,WAAW,EAAE,iBAAiB,CAAC,GAAG,CAAC,EAAE,CAAM;IAC3C,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAa;IAC9D,OAAO,EAAE,GAAG,CAAC,MAAM,EAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAW;IAC3C,QAAQ,EAAC,cAAc,EAAE,CAAI;IAC7B,KAAK,EAAC,IAAI,EAAE,CAAI;IAEhB;;;;;OAKG;gBACS,MAAM,EAAE,UAAU,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;IAsDtE,IAAI,CAAC,cAAc,EAAC,MAAM,EAAC,QAAQ,EAAC,MAAI,IAAI;IAoB5C,WAAW,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAC,GAAG,CAAC,EAAE,IAAI,EAAC,MAAM,EAAC,MAAM,EAAC,MAAM,CAAC,CAAC,CAAC;IAItE,UAAU,CAAC,OAAO,EAAC,iBAAiB;IAGpC,MAAM,CAAC,KAAK,EAAC,MAAM,EAAC,QAAQ,EAAC,CAAC,GAAG,IAAI,EAAC,GAAG,EAAE,KAAG,GAAG;IAGjD,iBAAiB;IACjB,IAAI,GAAG,IAAI,GAAG,CAEb;IACD,IAAI,MAAM,IAAI,MAAM,CASnB;IACD,WAAW;IACX,YAAY,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,SAAS,EAAC,SAAS,CAAC,CAAC,EAAC,CAAC,EAAC,CAAC,CAAC;IAG/E,YAAY;IACZ,UAAU,CAAC,OAAO,EAAC,cAAc;IAIjC,YAAY;IACZ,aAAa,CAAC,CAAC,SAAS,iBAAiB,EAAE,UAAU,EAAE,iBAAiB,CAAC,CAAC,CAAC;IAO3E,MAAM,CAAC,CAAC,SAAS,iBAAiB,EAAE,OAAO,EAAC,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;IAMtE,WAAW;IACL,WAAW,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAgBtD,WAAW;IACX,OAAO,IAAI,IAAI;CAqBlB"}
|
package/lib/plugin.js
ADDED
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// 插件类型定义(定义插件中间件、生命周期、命令、组件等核心类型)
|
|
3
|
+
// ============================================================================
|
|
4
|
+
import { Dependency, } from "@zhin.js/hmr";
|
|
5
|
+
import { Component } from "./component.js";
|
|
6
|
+
import { PluginError, MessageError, errorManager } from './errors.js';
|
|
7
|
+
import { remove } from "./utils.js";
|
|
8
|
+
import { Prompt } from "./prompt.js";
|
|
9
|
+
import { Cron } from './cron.js';
|
|
10
|
+
// ============================================================================
|
|
11
|
+
// Plugin 类(插件的生命周期、命令/中间件/组件/定时任务等管理)
|
|
12
|
+
// ============================================================================
|
|
13
|
+
/**
|
|
14
|
+
* 插件类:继承自 Dependency,提供机器人特定功能与生命周期管理。
|
|
15
|
+
* 支持命令注册、中间件、组件、定时任务、模型等。
|
|
16
|
+
*/
|
|
17
|
+
export class Plugin extends Dependency {
|
|
18
|
+
middlewares = [];
|
|
19
|
+
components = new Map();
|
|
20
|
+
schemas = new Map();
|
|
21
|
+
commands = [];
|
|
22
|
+
crons = [];
|
|
23
|
+
#logger;
|
|
24
|
+
/**
|
|
25
|
+
* 构造函数:初始化插件,注册消息事件、命令中间件、资源清理等
|
|
26
|
+
* @param parent 所属 App 实例
|
|
27
|
+
* @param name 插件名
|
|
28
|
+
* @param filePath 插件文件路径
|
|
29
|
+
*/
|
|
30
|
+
constructor(parent, name, filePath) {
|
|
31
|
+
super(parent, name, filePath);
|
|
32
|
+
// 绑定消息事件,自动分发到命令和中间件
|
|
33
|
+
this.on('message.receive', this.#handleMessage.bind(this));
|
|
34
|
+
// 注册命令处理为默认中间件
|
|
35
|
+
this.addMiddleware(async (message, next) => {
|
|
36
|
+
for (const command of this.commands) {
|
|
37
|
+
const result = await command.handle(message);
|
|
38
|
+
if (result)
|
|
39
|
+
message.$reply(result);
|
|
40
|
+
}
|
|
41
|
+
return next();
|
|
42
|
+
});
|
|
43
|
+
// 发送前渲染组件
|
|
44
|
+
this.beforeSend((options) => Component.render(this.components, options));
|
|
45
|
+
// 资源清理:卸载时清空模型、定时任务等
|
|
46
|
+
this.on('dispose', () => {
|
|
47
|
+
for (const name of this.schemas.keys()) {
|
|
48
|
+
this.app.database?.models.delete(name);
|
|
49
|
+
}
|
|
50
|
+
this.schemas.clear();
|
|
51
|
+
for (const cron of this.crons) {
|
|
52
|
+
cron.dispose();
|
|
53
|
+
}
|
|
54
|
+
this.crons.length = 0;
|
|
55
|
+
});
|
|
56
|
+
// 挂载时启动定时任务
|
|
57
|
+
this.on('mounted', () => {
|
|
58
|
+
for (const cron of this.crons) {
|
|
59
|
+
cron.run();
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
async #handleMessage(message) {
|
|
64
|
+
try {
|
|
65
|
+
await this.#runMiddlewares(message, 0);
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
const messageError = new MessageError(`消息处理失败: ${error.message}`, message.$id, message.$channel.id, { pluginName: this.name, originalError: error });
|
|
69
|
+
await errorManager.handle(messageError);
|
|
70
|
+
// 可选:发送错误回复给用户
|
|
71
|
+
try {
|
|
72
|
+
await message.$reply('抱歉,处理您的消息时出现了错误。');
|
|
73
|
+
}
|
|
74
|
+
catch (replyError) {
|
|
75
|
+
// 静默处理回复错误,避免错误循环
|
|
76
|
+
// console.error 已替换为注释
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
cron(cronExpression, callback) {
|
|
81
|
+
const cronJob = new Cron(cronExpression, callback);
|
|
82
|
+
this.crons.push(cronJob);
|
|
83
|
+
return this;
|
|
84
|
+
}
|
|
85
|
+
async #runMiddlewares(message, index) {
|
|
86
|
+
if (index >= this.middlewares.length)
|
|
87
|
+
return;
|
|
88
|
+
const middleware = this.middlewares[index];
|
|
89
|
+
try {
|
|
90
|
+
await middleware(message, () => this.#runMiddlewares(message, index + 1));
|
|
91
|
+
}
|
|
92
|
+
catch (error) {
|
|
93
|
+
throw new PluginError(`中间件执行失败: ${error.message}`, this.name, { middlewareIndex: index, originalError: error });
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
defineModel(name, schema) {
|
|
97
|
+
this.schemas.set(name, schema);
|
|
98
|
+
return this;
|
|
99
|
+
}
|
|
100
|
+
beforeSend(handler) {
|
|
101
|
+
this.before('message.send', handler);
|
|
102
|
+
}
|
|
103
|
+
before(event, listener) {
|
|
104
|
+
this.on(`before-${event}`, listener);
|
|
105
|
+
}
|
|
106
|
+
/** 获取所属的App实例 */
|
|
107
|
+
get app() {
|
|
108
|
+
return this.parent;
|
|
109
|
+
}
|
|
110
|
+
get logger() {
|
|
111
|
+
if (this.#logger)
|
|
112
|
+
return this.#logger;
|
|
113
|
+
const names = [];
|
|
114
|
+
let temp = this;
|
|
115
|
+
while (temp.parent) {
|
|
116
|
+
names.unshift(temp.name);
|
|
117
|
+
temp = temp.parent;
|
|
118
|
+
}
|
|
119
|
+
return temp.getLogger(names.join('/'));
|
|
120
|
+
}
|
|
121
|
+
/** 添加组件 */
|
|
122
|
+
addComponent(component) {
|
|
123
|
+
this.components.set(component.name, component);
|
|
124
|
+
}
|
|
125
|
+
/** 添加中间件 */
|
|
126
|
+
addCommand(command) {
|
|
127
|
+
this.commands.push(command);
|
|
128
|
+
this.dispatch('command.add', command);
|
|
129
|
+
}
|
|
130
|
+
/** 添加中间件 */
|
|
131
|
+
addMiddleware(middleware) {
|
|
132
|
+
this.middlewares.push(middleware);
|
|
133
|
+
this.dispatch('middleware.add', middleware);
|
|
134
|
+
return () => {
|
|
135
|
+
remove(this.middlewares, middleware);
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
prompt(message) {
|
|
139
|
+
return new Prompt(this, message);
|
|
140
|
+
}
|
|
141
|
+
/** 发送消息 */
|
|
142
|
+
async sendMessage(options) {
|
|
143
|
+
try {
|
|
144
|
+
await this.app.sendMessage(options);
|
|
145
|
+
}
|
|
146
|
+
catch (error) {
|
|
147
|
+
const messageError = new MessageError(`发送消息失败: ${error.message}`, undefined, options.channel_id, { pluginName: this.name, sendOptions: options, originalError: error });
|
|
148
|
+
await errorManager.handle(messageError);
|
|
149
|
+
throw messageError;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
/** 销毁插件 */
|
|
153
|
+
dispose() {
|
|
154
|
+
try {
|
|
155
|
+
// 移除所有中间件
|
|
156
|
+
for (const middleware of this.middlewares) {
|
|
157
|
+
this.dispatch('middleware.remove', middleware);
|
|
158
|
+
}
|
|
159
|
+
this.middlewares = [];
|
|
160
|
+
// 调用父类的dispose方法
|
|
161
|
+
super.dispose();
|
|
162
|
+
}
|
|
163
|
+
catch (error) {
|
|
164
|
+
const pluginError = new PluginError(`插件销毁失败: ${error.message}`, this.name, { originalError: error });
|
|
165
|
+
errorManager.handle(pluginError).catch(console.error);
|
|
166
|
+
throw pluginError;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
//# sourceMappingURL=plugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.js","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"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"}
|
package/lib/prompt.d.ts
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { AdapterMessage, RegisteredAdapter } from './types.js';
|
|
2
|
+
import { Plugin } from './plugin.js';
|
|
3
|
+
import { Message } from './message.js';
|
|
4
|
+
import { Schema } from './schema.js';
|
|
5
|
+
/**
|
|
6
|
+
* Prompt类:用于实现机器人与用户的交互式提问与输入收集。
|
|
7
|
+
* 支持文本、数字、确认、列表、选项、Schema等多种输入类型,自动处理超时、默认值、格式化等。
|
|
8
|
+
* 典型用法:await new Prompt(plugin, event).text('请输入内容')
|
|
9
|
+
* @template P 适配器类型
|
|
10
|
+
*/
|
|
11
|
+
export declare class Prompt<P extends RegisteredAdapter> {
|
|
12
|
+
private plugin;
|
|
13
|
+
private event;
|
|
14
|
+
/**
|
|
15
|
+
* 构造函数
|
|
16
|
+
* @param plugin 所属插件实例
|
|
17
|
+
* @param event 当前消息事件
|
|
18
|
+
*/
|
|
19
|
+
constructor(plugin: Plugin, event: Message<AdapterMessage<P>>);
|
|
20
|
+
/**
|
|
21
|
+
* 获取当前会话唯一标识(适配器-机器人-频道-用户)
|
|
22
|
+
*/
|
|
23
|
+
private getChannelAddress;
|
|
24
|
+
/**
|
|
25
|
+
* 通用提问方法,支持自定义格式化、超时、默认值等
|
|
26
|
+
* @param config 提问配置
|
|
27
|
+
*/
|
|
28
|
+
private prompt;
|
|
29
|
+
/**
|
|
30
|
+
* 注册一次性消息中间件,等待用户输入或超时
|
|
31
|
+
* @param callback 输入回调
|
|
32
|
+
* @param timeout 超时时间(默认3分钟)
|
|
33
|
+
* @param timeoutText 超时提示
|
|
34
|
+
*/
|
|
35
|
+
middleware(callback: (input: string | Error) => any, timeout?: number, timeoutText?: string): void;
|
|
36
|
+
/**
|
|
37
|
+
* 文本输入
|
|
38
|
+
*/
|
|
39
|
+
text(tips: string, timeout?: number, defaultValue?: string, timeoutText?: string): Promise<string>;
|
|
40
|
+
/**
|
|
41
|
+
* 任意输入
|
|
42
|
+
*/
|
|
43
|
+
any(tips: string, timeout?: number, defaultValue?: string, timeoutText?: string): Promise<string>;
|
|
44
|
+
/**
|
|
45
|
+
* 数字输入
|
|
46
|
+
*/
|
|
47
|
+
number(tips: string, timeout?: number, defaultValue?: number, timeoutText?: string): Promise<number>;
|
|
48
|
+
/**
|
|
49
|
+
* 确认输入(如 yes/no)
|
|
50
|
+
*/
|
|
51
|
+
confirm(tips: string, condition?: string, timeout?: number, defaultValue?: boolean, timeoutText?: string): Promise<boolean>;
|
|
52
|
+
/**
|
|
53
|
+
* 列表输入,支持多值分隔
|
|
54
|
+
*/
|
|
55
|
+
list<T extends Prompt.SingleType = 'text'>(tips: string, config?: Prompt.ListConfig<T>, timeoutText?: string): Promise<Prompt.Result<T>[]>;
|
|
56
|
+
/**
|
|
57
|
+
* 返回常量值(用于Schema)
|
|
58
|
+
*/
|
|
59
|
+
const<T = any>(value: T): Promise<T>;
|
|
60
|
+
/**
|
|
61
|
+
* 选项选择,支持单选/多选
|
|
62
|
+
*/
|
|
63
|
+
pick<T extends Prompt.SingleType, M extends boolean = false>(tips: string, config: Prompt.PickConfig<T, M>, timeoutText?: string): Promise<Prompt.PickResult<T, M>>;
|
|
64
|
+
/**
|
|
65
|
+
* 基于Schema的选项选择
|
|
66
|
+
*/
|
|
67
|
+
pickValueWithSchema<T extends Schema>(schema: T): Promise<Schema.Types<T>>;
|
|
68
|
+
/**
|
|
69
|
+
* 批量Schema输入
|
|
70
|
+
*/
|
|
71
|
+
getValueWithSchemas<T extends Record<string, Schema>>(schemas: T): Promise<Schema.RecordTypes<T>>;
|
|
72
|
+
/**
|
|
73
|
+
* 单个Schema输入,自动分发到不同类型
|
|
74
|
+
*/
|
|
75
|
+
getValueWithSchema<T extends Schema>(schema: T): Promise<Schema.Types<T>>;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Prompt命名空间:类型辅助定义
|
|
79
|
+
*/
|
|
80
|
+
export declare namespace Prompt {
|
|
81
|
+
interface SingleMap {
|
|
82
|
+
text: string;
|
|
83
|
+
number: number;
|
|
84
|
+
boolean: boolean;
|
|
85
|
+
}
|
|
86
|
+
export interface ListConfig<T extends SingleType> {
|
|
87
|
+
type: T;
|
|
88
|
+
defaultValue?: SingleMap[T][];
|
|
89
|
+
separator?: string;
|
|
90
|
+
timeout?: number;
|
|
91
|
+
}
|
|
92
|
+
export interface PickConfig<T extends SingleType = SingleType, M extends boolean = false> {
|
|
93
|
+
type: T;
|
|
94
|
+
defaultValue?: PickResult<T, M>;
|
|
95
|
+
separator?: string;
|
|
96
|
+
timeout?: number;
|
|
97
|
+
options: PickOption<T>[];
|
|
98
|
+
multiple?: M;
|
|
99
|
+
}
|
|
100
|
+
export type PickOption<T extends SingleType = 'text'> = {
|
|
101
|
+
label: string;
|
|
102
|
+
value: SingleMap[T];
|
|
103
|
+
};
|
|
104
|
+
export type PickResult<T extends SingleType, M extends boolean> = M extends true ? Result<T>[] : Result<T>;
|
|
105
|
+
export type SingleType = keyof SingleMap;
|
|
106
|
+
export type Result<T extends SingleType> = SingleMap[T];
|
|
107
|
+
export type Config<R = any> = {
|
|
108
|
+
tips: string;
|
|
109
|
+
defaultValue?: R;
|
|
110
|
+
timeout?: number;
|
|
111
|
+
timeoutText?: string;
|
|
112
|
+
format: (input: string) => R;
|
|
113
|
+
};
|
|
114
|
+
export {};
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=prompt.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompt.d.ts","sourceRoot":"","sources":["../src/prompt.ts"],"names":[],"mappings":"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"}
|
package/lib/prompt.js
ADDED
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Prompt类:用于实现机器人与用户的交互式提问与输入收集。
|
|
3
|
+
* 支持文本、数字、确认、列表、选项、Schema等多种输入类型,自动处理超时、默认值、格式化等。
|
|
4
|
+
* 典型用法:await new Prompt(plugin, event).text('请输入内容')
|
|
5
|
+
* @template P 适配器类型
|
|
6
|
+
*/
|
|
7
|
+
export class Prompt {
|
|
8
|
+
plugin;
|
|
9
|
+
event;
|
|
10
|
+
/**
|
|
11
|
+
* 构造函数
|
|
12
|
+
* @param plugin 所属插件实例
|
|
13
|
+
* @param event 当前消息事件
|
|
14
|
+
*/
|
|
15
|
+
constructor(plugin, event) {
|
|
16
|
+
this.plugin = plugin;
|
|
17
|
+
this.event = event;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* 获取当前会话唯一标识(适配器-机器人-频道-用户)
|
|
21
|
+
*/
|
|
22
|
+
getChannelAddress(event) {
|
|
23
|
+
return `${event.$adapter}-${event.$bot}-${event.$channel.type}:${event.$channel.id}-${event.$sender.id}`;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* 通用提问方法,支持自定义格式化、超时、默认值等
|
|
27
|
+
* @param config 提问配置
|
|
28
|
+
*/
|
|
29
|
+
prompt(config) {
|
|
30
|
+
return new Promise((resolve, reject) => {
|
|
31
|
+
this.event.$reply(config.tips);
|
|
32
|
+
this.middleware(input => {
|
|
33
|
+
if (input instanceof Error) {
|
|
34
|
+
this.event.$reply(input.message);
|
|
35
|
+
if (config.defaultValue)
|
|
36
|
+
resolve(config.defaultValue);
|
|
37
|
+
else
|
|
38
|
+
reject(input);
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
resolve(config.format(input));
|
|
42
|
+
}, config.timeout, config.timeoutText);
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* 注册一次性消息中间件,等待用户输入或超时
|
|
47
|
+
* @param callback 输入回调
|
|
48
|
+
* @param timeout 超时时间(默认3分钟)
|
|
49
|
+
* @param timeoutText 超时提示
|
|
50
|
+
*/
|
|
51
|
+
middleware(callback, timeout = 3 * 60 * 1000, timeoutText = '输入超时') {
|
|
52
|
+
const middleware = (event, next) => {
|
|
53
|
+
if (this.getChannelAddress(event) !== this.getChannelAddress(this.event))
|
|
54
|
+
return next();
|
|
55
|
+
callback(event.$raw);
|
|
56
|
+
dispose();
|
|
57
|
+
clearTimeout(timer);
|
|
58
|
+
};
|
|
59
|
+
const dispose = this.plugin.addMiddleware(middleware);
|
|
60
|
+
const timer = setTimeout(() => {
|
|
61
|
+
dispose();
|
|
62
|
+
callback(new Error(timeoutText));
|
|
63
|
+
}, timeout);
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* 文本输入
|
|
67
|
+
*/
|
|
68
|
+
async text(tips, timeout, defaultValue = '', timeoutText) {
|
|
69
|
+
return this.prompt({
|
|
70
|
+
tips,
|
|
71
|
+
defaultValue,
|
|
72
|
+
timeoutText,
|
|
73
|
+
timeout,
|
|
74
|
+
format: (input) => input,
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* 任意输入
|
|
79
|
+
*/
|
|
80
|
+
async any(tips, timeout, defaultValue = '', timeoutText) {
|
|
81
|
+
return this.prompt({
|
|
82
|
+
tips,
|
|
83
|
+
defaultValue,
|
|
84
|
+
timeoutText,
|
|
85
|
+
timeout,
|
|
86
|
+
format: (input) => input,
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* 数字输入
|
|
91
|
+
*/
|
|
92
|
+
async number(tips, timeout, defaultValue = 0, timeoutText) {
|
|
93
|
+
return this.prompt({
|
|
94
|
+
tips,
|
|
95
|
+
defaultValue,
|
|
96
|
+
timeoutText,
|
|
97
|
+
timeout,
|
|
98
|
+
format: (input) => +input,
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* 确认输入(如 yes/no)
|
|
103
|
+
*/
|
|
104
|
+
async confirm(tips, condition = 'yes', timeout, defaultValue = false, timeoutText) {
|
|
105
|
+
return this.prompt({
|
|
106
|
+
tips: `${tips}\n输入“${condition}”以确认`,
|
|
107
|
+
defaultValue,
|
|
108
|
+
timeout,
|
|
109
|
+
timeoutText,
|
|
110
|
+
format: (input) => input === condition,
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* 列表输入,支持多值分隔
|
|
115
|
+
*/
|
|
116
|
+
async list(tips, config = { type: 'text' }, timeoutText) {
|
|
117
|
+
const separator = config.separator || ',';
|
|
118
|
+
return this.prompt({
|
|
119
|
+
tips: `${tips}\n值之间使用“${separator}”分隔`,
|
|
120
|
+
defaultValue: config.defaultValue || [],
|
|
121
|
+
timeout: config.timeout,
|
|
122
|
+
timeoutText,
|
|
123
|
+
format: (input) => input.split(separator).map(v => {
|
|
124
|
+
switch (config.type) {
|
|
125
|
+
case 'boolean':
|
|
126
|
+
return Boolean(v);
|
|
127
|
+
case 'number':
|
|
128
|
+
return +v;
|
|
129
|
+
case 'text':
|
|
130
|
+
return v;
|
|
131
|
+
}
|
|
132
|
+
}),
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* 返回常量值(用于Schema)
|
|
137
|
+
*/
|
|
138
|
+
async const(value) {
|
|
139
|
+
return value;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* 选项选择,支持单选/多选
|
|
143
|
+
*/
|
|
144
|
+
async pick(tips, config, timeoutText) {
|
|
145
|
+
const moreTextArr = config.options.map((o, idx) => {
|
|
146
|
+
return `${idx + 1}.${o.label}`;
|
|
147
|
+
});
|
|
148
|
+
const separator = config.separator || ',';
|
|
149
|
+
if (config.multiple)
|
|
150
|
+
moreTextArr.push(`多选请用“${separator}”分隔`);
|
|
151
|
+
return this.prompt({
|
|
152
|
+
tips: `${tips}\n${moreTextArr.join('\n')}`,
|
|
153
|
+
defaultValue: config.defaultValue,
|
|
154
|
+
timeout: config.timeout,
|
|
155
|
+
timeoutText,
|
|
156
|
+
format: (input) => {
|
|
157
|
+
if (!config.multiple)
|
|
158
|
+
return config.options.find((o, idx) => {
|
|
159
|
+
return idx + 1 === +input;
|
|
160
|
+
})?.value;
|
|
161
|
+
const pickIdx = input.split(separator).map(Number);
|
|
162
|
+
return config.options
|
|
163
|
+
.filter((o, idx) => {
|
|
164
|
+
return pickIdx.includes(idx + 1);
|
|
165
|
+
})
|
|
166
|
+
.map(o => o.value);
|
|
167
|
+
},
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* 基于Schema的选项选择
|
|
172
|
+
*/
|
|
173
|
+
async pickValueWithSchema(schema) {
|
|
174
|
+
return this.pick(schema.meta.description, {
|
|
175
|
+
type: '',
|
|
176
|
+
options: schema.meta.options.map(o => ({
|
|
177
|
+
label: o.label,
|
|
178
|
+
value: o.value,
|
|
179
|
+
})),
|
|
180
|
+
multiple: schema.meta.multiple,
|
|
181
|
+
defaultValue: schema.meta.default,
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* 批量Schema输入
|
|
186
|
+
*/
|
|
187
|
+
async getValueWithSchemas(schemas) {
|
|
188
|
+
const result = {};
|
|
189
|
+
for (const key of Object.keys(schemas)) {
|
|
190
|
+
const schema = schemas[key];
|
|
191
|
+
result[key] = await this.getValueWithSchema(schema);
|
|
192
|
+
}
|
|
193
|
+
return result;
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* 单个Schema输入,自动分发到不同类型
|
|
197
|
+
*/
|
|
198
|
+
async getValueWithSchema(schema) {
|
|
199
|
+
if (schema.meta.options)
|
|
200
|
+
return this.pickValueWithSchema(schema);
|
|
201
|
+
switch (schema.meta.type) {
|
|
202
|
+
case 'number':
|
|
203
|
+
return (await this.number(schema.meta.description));
|
|
204
|
+
case 'string':
|
|
205
|
+
return (await this.text(schema.meta.description));
|
|
206
|
+
case 'boolean':
|
|
207
|
+
return (await this.confirm(schema.meta.description));
|
|
208
|
+
case 'object':
|
|
209
|
+
if (schema.meta.description)
|
|
210
|
+
await this.event.$reply(schema.meta.description);
|
|
211
|
+
return (await this.getValueWithSchemas(schema.options.object));
|
|
212
|
+
case 'date':
|
|
213
|
+
return await this.prompt({
|
|
214
|
+
tips: schema.meta.description,
|
|
215
|
+
defaultValue: schema.meta.default || new Date(),
|
|
216
|
+
format: (input) => new Date(input),
|
|
217
|
+
});
|
|
218
|
+
case 'regexp':
|
|
219
|
+
return await this.prompt({
|
|
220
|
+
tips: schema.meta.description,
|
|
221
|
+
defaultValue: schema.meta.default || '',
|
|
222
|
+
format: (input) => new RegExp(input),
|
|
223
|
+
});
|
|
224
|
+
case 'const':
|
|
225
|
+
return await this.const(schema.meta.default);
|
|
226
|
+
case 'list':
|
|
227
|
+
const inner = schema.options.inner;
|
|
228
|
+
if (!['string', 'boolean', 'number'].includes(inner.meta.type))
|
|
229
|
+
throw new Error(`unsupported inner type :${inner.meta.type}`);
|
|
230
|
+
return (await this.list(schema.meta.description, {
|
|
231
|
+
type: inner.meta.type === 'string' ? 'text' : inner.meta.type,
|
|
232
|
+
defaultValue: schema.meta.default,
|
|
233
|
+
}));
|
|
234
|
+
case 'dict':
|
|
235
|
+
default:
|
|
236
|
+
throw new Error(`Unsupported schema input type: ${schema.meta.type}`);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
//# sourceMappingURL=prompt.js.map
|