@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.
Files changed (121) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/LICENSE +21 -0
  3. package/README.md +295 -74
  4. package/lib/adapter.d.ts +39 -0
  5. package/lib/adapter.d.ts.map +1 -0
  6. package/{dist → lib}/adapter.js +20 -2
  7. package/lib/adapter.js.map +1 -0
  8. package/lib/app.d.ts +115 -0
  9. package/lib/app.d.ts.map +1 -0
  10. package/{dist → lib}/app.js +148 -78
  11. package/lib/app.js.map +1 -0
  12. package/lib/bot.d.ts +31 -0
  13. package/lib/bot.d.ts.map +1 -0
  14. package/lib/command.d.ts +32 -0
  15. package/lib/command.d.ts.map +1 -0
  16. package/lib/command.js +46 -0
  17. package/lib/command.js.map +1 -0
  18. package/lib/component.d.ts +107 -0
  19. package/lib/component.d.ts.map +1 -0
  20. package/lib/component.js +273 -0
  21. package/lib/component.js.map +1 -0
  22. package/{dist → lib}/config.d.ts.map +1 -1
  23. package/{dist → lib}/config.js +6 -9
  24. package/lib/config.js.map +1 -0
  25. package/lib/cron.d.ts +81 -0
  26. package/lib/cron.d.ts.map +1 -0
  27. package/lib/cron.js +159 -0
  28. package/lib/cron.js.map +1 -0
  29. package/lib/errors.d.ts +165 -0
  30. package/lib/errors.d.ts.map +1 -0
  31. package/lib/errors.js +306 -0
  32. package/lib/errors.js.map +1 -0
  33. package/lib/index.d.ts +15 -0
  34. package/lib/index.d.ts.map +1 -0
  35. package/lib/index.js +17 -0
  36. package/lib/index.js.map +1 -0
  37. package/lib/message.d.ts +44 -0
  38. package/lib/message.d.ts.map +1 -0
  39. package/lib/message.js +11 -0
  40. package/lib/message.js.map +1 -0
  41. package/lib/plugin.d.ts +50 -0
  42. package/lib/plugin.d.ts.map +1 -0
  43. package/lib/plugin.js +170 -0
  44. package/lib/plugin.js.map +1 -0
  45. package/lib/prompt.d.ts +116 -0
  46. package/lib/prompt.d.ts.map +1 -0
  47. package/lib/prompt.js +240 -0
  48. package/lib/prompt.js.map +1 -0
  49. package/lib/schema.d.ts +83 -0
  50. package/lib/schema.d.ts.map +1 -0
  51. package/lib/schema.js +245 -0
  52. package/lib/schema.js.map +1 -0
  53. package/{dist → lib}/types-generator.d.ts.map +1 -1
  54. package/{dist → lib}/types-generator.js +6 -3
  55. package/lib/types-generator.js.map +1 -0
  56. package/lib/types.d.ts +119 -0
  57. package/lib/types.d.ts.map +1 -0
  58. package/lib/utils.d.ts +52 -0
  59. package/lib/utils.d.ts.map +1 -0
  60. package/lib/utils.js +338 -0
  61. package/lib/utils.js.map +1 -0
  62. package/package.json +15 -9
  63. package/src/adapter.ts +25 -9
  64. package/src/app.ts +363 -258
  65. package/src/bot.ts +29 -8
  66. package/src/command.ts +50 -0
  67. package/src/component.ts +318 -0
  68. package/src/config.ts +9 -12
  69. package/src/cron.ts +176 -0
  70. package/src/errors.ts +365 -0
  71. package/src/index.ts +16 -13
  72. package/src/message.ts +44 -0
  73. package/src/plugin.ts +148 -66
  74. package/src/prompt.ts +290 -0
  75. package/src/schema.ts +273 -0
  76. package/src/types-generator.ts +7 -3
  77. package/src/types.ts +77 -30
  78. package/src/utils.ts +312 -0
  79. package/tests/adapter.test.ts +36 -22
  80. package/tests/app.test.ts +30 -0
  81. package/tests/command.test.ts +545 -0
  82. package/tests/component.test.ts +656 -0
  83. package/tests/config.test.ts +1 -1
  84. package/tests/errors.test.ts +311 -0
  85. package/tests/message.test.ts +402 -0
  86. package/tests/plugin.test.ts +275 -143
  87. package/tests/utils.test.ts +80 -0
  88. package/tsconfig.json +3 -4
  89. package/dist/adapter.d.ts +0 -22
  90. package/dist/adapter.d.ts.map +0 -1
  91. package/dist/adapter.js.map +0 -1
  92. package/dist/app.d.ts +0 -69
  93. package/dist/app.d.ts.map +0 -1
  94. package/dist/app.js.map +0 -1
  95. package/dist/bot.d.ts +0 -9
  96. package/dist/bot.d.ts.map +0 -1
  97. package/dist/config.js.map +0 -1
  98. package/dist/index.d.ts +0 -9
  99. package/dist/index.d.ts.map +0 -1
  100. package/dist/index.js +0 -12
  101. package/dist/index.js.map +0 -1
  102. package/dist/logger.d.ts +0 -3
  103. package/dist/logger.d.ts.map +0 -1
  104. package/dist/logger.js +0 -3
  105. package/dist/logger.js.map +0 -1
  106. package/dist/plugin.d.ts +0 -41
  107. package/dist/plugin.d.ts.map +0 -1
  108. package/dist/plugin.js +0 -95
  109. package/dist/plugin.js.map +0 -1
  110. package/dist/types-generator.js.map +0 -1
  111. package/dist/types.d.ts +0 -69
  112. package/dist/types.d.ts.map +0 -1
  113. package/src/logger.ts +0 -3
  114. package/tests/logger.test.ts +0 -170
  115. package/tsconfig.tsbuildinfo +0 -1
  116. /package/{dist → lib}/bot.js +0 -0
  117. /package/{dist → lib}/bot.js.map +0 -0
  118. /package/{dist → lib}/config.d.ts +0 -0
  119. /package/{dist → lib}/types-generator.d.ts +0 -0
  120. /package/{dist → lib}/types.js +0 -0
  121. /package/{dist → lib}/types.js.map +0 -0
package/src/errors.ts ADDED
@@ -0,0 +1,365 @@
1
+ // ============================================================================
2
+ // 错误处理系统
3
+ // ============================================================================
4
+
5
+ /**
6
+ * 基础错误类,所有自定义错误都应该继承此类
7
+ */
8
+ export class ZhinError extends Error {
9
+ public readonly code: string
10
+ public readonly timestamp: Date
11
+ public readonly context?: Record<string, any>
12
+
13
+ constructor(message: string, code: string = 'ZHIN_ERROR', context?: Record<string, any>) {
14
+ super(message)
15
+ this.name = this.constructor.name
16
+ this.code = code
17
+ this.timestamp = new Date()
18
+ this.context = context
19
+
20
+ // 确保错误堆栈正确显示
21
+ if (Error.captureStackTrace) {
22
+ Error.captureStackTrace(this, this.constructor)
23
+ }
24
+ }
25
+
26
+ /**
27
+ * 转换为JSON格式
28
+ */
29
+ toJSON() {
30
+ return {
31
+ name: this.name,
32
+ message: this.message,
33
+ code: this.code,
34
+ timestamp: this.timestamp.toISOString(),
35
+ context: this.context,
36
+ stack: this.stack
37
+ }
38
+ }
39
+
40
+ /**
41
+ * 转换为用户友好的格式
42
+ */
43
+ toUserString(): string {
44
+ return `[${this.code}] ${this.message}`
45
+ }
46
+ }
47
+
48
+ /**
49
+ * 配置相关错误
50
+ */
51
+ export class ConfigError extends ZhinError {
52
+ constructor(message: string, context?: Record<string, any>) {
53
+ super(message, 'CONFIG_ERROR', context)
54
+ }
55
+ }
56
+
57
+ /**
58
+ * 插件相关错误
59
+ */
60
+ export class PluginError extends ZhinError {
61
+ public readonly pluginName: string
62
+
63
+ constructor(message: string, pluginName: string, context?: Record<string, any>) {
64
+ super(message, 'PLUGIN_ERROR', { ...context, pluginName })
65
+ this.pluginName = pluginName
66
+ }
67
+ }
68
+
69
+ /**
70
+ * 适配器相关错误
71
+ */
72
+ export class AdapterError extends ZhinError {
73
+ public readonly adapterName: string
74
+ public readonly botName?: string
75
+
76
+ constructor(message: string, adapterName: string, botName?: string, context?: Record<string, any>) {
77
+ super(message, 'ADAPTER_ERROR', { ...context, adapterName, botName })
78
+ this.adapterName = adapterName
79
+ this.botName = botName
80
+ }
81
+ }
82
+
83
+ /**
84
+ * 连接相关错误
85
+ */
86
+ export class ConnectionError extends ZhinError {
87
+ public readonly retryable: boolean
88
+
89
+ constructor(message: string, retryable: boolean = true, context?: Record<string, any>) {
90
+ super(message, 'CONNECTION_ERROR', { ...context, retryable })
91
+ this.retryable = retryable
92
+ }
93
+ }
94
+
95
+ /**
96
+ * 消息处理错误
97
+ */
98
+ export class MessageError extends ZhinError {
99
+ public readonly messageId?: string
100
+ public readonly channelId?: string
101
+
102
+ constructor(message: string, messageId?: string, channelId?: string, context?: Record<string, any>) {
103
+ super(message, 'MESSAGE_ERROR', { ...context, messageId, channelId })
104
+ this.messageId = messageId
105
+ this.channelId = channelId
106
+ }
107
+ }
108
+
109
+ /**
110
+ * 上下文相关错误
111
+ */
112
+ export class ContextError extends ZhinError {
113
+ public readonly contextName: string
114
+
115
+ constructor(message: string, contextName: string, context?: Record<string, any>) {
116
+ super(message, 'CONTEXT_ERROR', { ...context, contextName })
117
+ this.contextName = contextName
118
+ }
119
+ }
120
+
121
+ /**
122
+ * 验证错误
123
+ */
124
+ export class ValidationError extends ZhinError {
125
+ public readonly field?: string
126
+ public readonly value?: any
127
+
128
+ constructor(message: string, field?: string, value?: any, context?: Record<string, any>) {
129
+ super(message, 'VALIDATION_ERROR', { ...context, field, value })
130
+ this.field = field
131
+ this.value = value
132
+ }
133
+ }
134
+
135
+ /**
136
+ * 权限错误
137
+ */
138
+ export class PermissionError extends ZhinError {
139
+ public readonly userId?: string
140
+ public readonly requiredPermission?: string
141
+
142
+ constructor(message: string, userId?: string, requiredPermission?: string, context?: Record<string, any>) {
143
+ super(message, 'PERMISSION_ERROR', { ...context, userId, requiredPermission })
144
+ this.userId = userId
145
+ this.requiredPermission = requiredPermission
146
+ }
147
+ }
148
+
149
+ /**
150
+ * 超时错误
151
+ */
152
+ export class TimeoutError extends ZhinError {
153
+ public readonly timeoutMs: number
154
+
155
+ constructor(message: string, timeoutMs: number, context?: Record<string, any>) {
156
+ super(message, 'TIMEOUT_ERROR', { ...context, timeoutMs })
157
+ this.timeoutMs = timeoutMs
158
+ }
159
+ }
160
+
161
+ /**
162
+ * 错误处理器接口
163
+ */
164
+ export interface ErrorHandler {
165
+ (error: Error, context?: Record<string, any>): void | Promise<void>
166
+ }
167
+
168
+ /**
169
+ * 错误管理器
170
+ */
171
+ export class ErrorManager {
172
+ private handlers: Map<string, ErrorHandler[]> = new Map()
173
+ private globalHandlers: ErrorHandler[] = []
174
+
175
+ /**
176
+ * 注册错误处理器
177
+ */
178
+ register(errorType: string, handler: ErrorHandler): void {
179
+ if (!this.handlers.has(errorType)) {
180
+ this.handlers.set(errorType, [])
181
+ }
182
+ this.handlers.get(errorType)!.push(handler)
183
+ }
184
+
185
+ /**
186
+ * 注册全局错误处理器
187
+ */
188
+ registerGlobal(handler: ErrorHandler): void {
189
+ this.globalHandlers.push(handler)
190
+ }
191
+
192
+ /**
193
+ * 处理错误
194
+ */
195
+ async handle(error: Error, context?: Record<string, any>): Promise<void> {
196
+ // 首先调用全局处理器
197
+ for (const handler of this.globalHandlers) {
198
+ try {
199
+ await handler(error, context)
200
+ } catch (handlerError) {
201
+ // console.error 已替换为注释
202
+ }
203
+ }
204
+
205
+ // 然后调用特定类型的处理器
206
+ const errorType = error.constructor.name
207
+ const handlers = this.handlers.get(errorType) || []
208
+
209
+ for (const handler of handlers) {
210
+ try {
211
+ await handler(error, context)
212
+ } catch (handlerError) {
213
+ // console.error 已替换为注释
214
+ }
215
+ }
216
+ }
217
+
218
+ /**
219
+ * 移除错误处理器
220
+ */
221
+ unregister(errorType: string, handler: ErrorHandler): boolean {
222
+ const handlers = this.handlers.get(errorType)
223
+ if (handlers) {
224
+ const index = handlers.indexOf(handler)
225
+ if (index !== -1) {
226
+ handlers.splice(index, 1)
227
+ return true
228
+ }
229
+ }
230
+ return false
231
+ }
232
+
233
+ /**
234
+ * 清理所有处理器
235
+ */
236
+ clear(): void {
237
+ this.handlers.clear()
238
+ this.globalHandlers.length = 0
239
+ }
240
+ }
241
+
242
+ /**
243
+ * 错误重试工具
244
+ */
245
+ export class RetryManager {
246
+ /**
247
+ * 执行重试逻辑
248
+ */
249
+ static async retry<T>(
250
+ fn: () => Promise<T>,
251
+ options: {
252
+ maxRetries?: number
253
+ delay?: number
254
+ exponentialBackoff?: boolean
255
+ retryCondition?: (error: Error) => boolean
256
+ } = {}
257
+ ): Promise<T> {
258
+ const {
259
+ maxRetries = 3,
260
+ delay = 1000,
261
+ exponentialBackoff = true,
262
+ retryCondition = () => true
263
+ } = options
264
+
265
+ let lastError: Error
266
+
267
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
268
+ try {
269
+ return await fn()
270
+ } catch (error) {
271
+ lastError = error as Error
272
+
273
+ // 如果是最后一次尝试或不满足重试条件,直接抛出错误
274
+ if (attempt === maxRetries || !retryCondition(lastError)) {
275
+ throw lastError
276
+ }
277
+
278
+ // 计算延迟时间
279
+ const currentDelay = exponentialBackoff
280
+ ? delay * Math.pow(2, attempt)
281
+ : delay
282
+
283
+ // 等待后重试
284
+ await new Promise(resolve => setTimeout(resolve, currentDelay))
285
+ }
286
+ }
287
+
288
+ throw lastError!
289
+ }
290
+ }
291
+
292
+ /**
293
+ * 断路器模式实现
294
+ */
295
+ export class CircuitBreaker {
296
+ private failures: number = 0
297
+ private lastFailureTime: number = 0
298
+ private state: 'CLOSED' | 'OPEN' | 'HALF_OPEN' = 'CLOSED'
299
+
300
+ constructor(
301
+ private failureThreshold: number = 5,
302
+ private timeoutMs: number = 60000,
303
+ private monitoringPeriodMs: number = 10000
304
+ ) {}
305
+
306
+ /**
307
+ * 执行受保护的操作
308
+ */
309
+ async execute<T>(fn: () => Promise<T>): Promise<T> {
310
+ if (this.state === 'OPEN') {
311
+ if (Date.now() - this.lastFailureTime > this.timeoutMs) {
312
+ this.state = 'HALF_OPEN'
313
+ } else {
314
+ throw new Error('Circuit breaker is OPEN')
315
+ }
316
+ }
317
+
318
+ try {
319
+ const result = await fn()
320
+ this.onSuccess()
321
+ return result
322
+ } catch (error) {
323
+ this.onFailure()
324
+ throw error
325
+ }
326
+ }
327
+
328
+ private onSuccess(): void {
329
+ this.failures = 0
330
+ this.state = 'CLOSED'
331
+ }
332
+
333
+ private onFailure(): void {
334
+ this.failures++
335
+ this.lastFailureTime = Date.now()
336
+
337
+ if (this.failures >= this.failureThreshold) {
338
+ this.state = 'OPEN'
339
+ }
340
+ }
341
+
342
+ /**
343
+ * 获取断路器状态
344
+ */
345
+ getState(): 'CLOSED' | 'OPEN' | 'HALF_OPEN' {
346
+ return this.state
347
+ }
348
+
349
+ /**
350
+ * 重置断路器
351
+ */
352
+ reset(): void {
353
+ this.failures = 0
354
+ this.lastFailureTime = 0
355
+ this.state = 'CLOSED'
356
+ }
357
+ }
358
+
359
+ // 默认错误管理器实例
360
+ export const errorManager = new ErrorManager()
361
+
362
+ // 默认错误处理器
363
+ errorManager.registerGlobal((error, context) => {
364
+ // Default error handler - logs to console
365
+ })
package/src/index.ts CHANGED
@@ -1,14 +1,17 @@
1
- // ============================================================================
2
- // Zhin Bot Framework - HMR Edition
3
- // ============================================================================
4
-
5
- // 核心系统
6
- export type { Bot } from './bot.js';
7
- export { loadConfig, saveConfig, createDefaultConfig } from './config.js';
8
- export * from './types.js';
9
- export * from './config.js';
1
+ // Core exports
2
+ export * from './app.js'
3
+ export * from './bot.js'
4
+ export * from './plugin.js'
5
+ export * from './command.js'
6
+ export * from './component.js'
10
7
  export * from './adapter.js'
11
- export * from './plugin.js';
12
- // HMR Bot系统 (主要API)
13
- export * from './app.js';
14
- export * from '@zhin.js/hmr';
8
+ export * from './config.js'
9
+ export * from './message.js'
10
+ // Logger moved to @zhin.js/logger package
11
+ export * from './types.js'
12
+ export * from './utils.js'
13
+ export * from './errors.js' // 导出错误处理系统
14
+ export * from './cron.js'
15
+ export * from '@zhin.js/database'
16
+
17
+ export { Dependency } from '@zhin.js/hmr'
package/src/message.ts ADDED
@@ -0,0 +1,44 @@
1
+ import {MaybePromise} from "@zhin.js/types";
2
+ import {MessageSegment, MessageSender, RegisteredAdapter, SendContent} from "./types";
3
+
4
+ /**
5
+ * 消息组件类型:用于自定义消息结构
6
+ */
7
+ export type MessageComponent<T extends object>=(props:T&{children:SendContent})=>MaybePromise<SendContent>
8
+ /**
9
+ * 消息频道信息
10
+ */
11
+ export interface MessageChannel{
12
+ id: string;
13
+ type: MessageType;
14
+ }
15
+ /**
16
+ * 消息类型枚举
17
+ */
18
+ export type MessageType = 'group' | 'private' | 'channel'
19
+ /**
20
+ * 消息基础结构
21
+ */
22
+ export interface MessageBase {
23
+ $id: string;
24
+ $adapter:string
25
+ $bot:string
26
+ $content: MessageSegment[];
27
+ $sender: MessageSender;
28
+ $reply(content:SendContent,quote?:boolean|string):Promise<void>
29
+ $channel: MessageChannel;
30
+ $timestamp: number;
31
+ $raw: string;
32
+ }
33
+ /**
34
+ * 完整消息类型,支持扩展
35
+ */
36
+ export type Message<T extends object={}>=MessageBase&T;
37
+ export namespace Message{
38
+ /**
39
+ * 工具方法:合并自定义字段与基础消息结构
40
+ */
41
+ export function from<T extends object>(input:T,format:MessageBase):Message<T>{
42
+ return Object.assign(input,format)
43
+ }
44
+ }
package/src/plugin.ts CHANGED
@@ -1,52 +1,123 @@
1
1
  // ============================================================================
2
- // 插件类型定义
2
+ // 插件类型定义(定义插件中间件、生命周期、命令、组件等核心类型)
3
3
  // ============================================================================
4
4
 
5
5
 
6
6
  import {MaybePromise} from '@zhin.js/types'
7
- import { Message, BeforeSendHandler, SendOptions} from "./types";
7
+ import {AdapterMessage, BeforeSendHandler, RegisteredAdapter, SendOptions} from "./types.js";
8
+ import {Message} from './message.js'
8
9
  import {Dependency, Logger,} from "@zhin.js/hmr";
9
10
  import {App} from "./app";
11
+ import {MessageCommand} from "./command.js";
12
+ import {Component} from "./component.js";
13
+ import { PluginError, MessageError, errorManager } from './errors.js';
14
+ import {remove} from "./utils.js";
15
+ import {Prompt} from "./prompt.js";
16
+ import { Schema } from '@zhin.js/database';
17
+ import { Cron} from './cron.js';
10
18
 
11
19
  /** 消息中间件函数 */
12
- export type MessageMiddleware = (message: Message, next: () => Promise<void>) => MaybePromise<void>;
13
-
14
- /** 事件监听器函数 */
15
- export type EventListener<T = any> = (data: T) => void | Promise<void>;
16
-
17
- /** 定时任务配置 */
18
- export interface CronJob {
19
- name: string;
20
- schedule: string; // cron 表达式
21
- handler: () => void | Promise<void>;
22
- enabled?: boolean;
23
- }
20
+ export type MessageMiddleware<P extends RegisteredAdapter=RegisteredAdapter> = (message: Message<AdapterMessage<P>>, next: () => Promise<void>) => MaybePromise<void>;
24
21
 
25
22
 
26
23
  // ============================================================================
27
- // Plugin
24
+ // Plugin 类(插件的生命周期、命令/中间件/组件/定时任务等管理)
28
25
  // ============================================================================
29
26
 
30
27
  /**
31
- * 插件类:继承自Dependency,提供机器人特定功能
28
+ * 插件类:继承自 Dependency,提供机器人特定功能与生命周期管理。
29
+ * 支持命令注册、中间件、组件、定时任务、模型等。
32
30
  */
33
31
  export class Plugin extends Dependency<Plugin> {
34
- middlewares: MessageMiddleware[] = [];
35
- eventListeners = new Map<string, EventListener[]>();
36
- cronJobs = new Map<string, CronJob>();
37
-
32
+ middlewares: MessageMiddleware<any>[] = [];
33
+ components: Map<string, Component<any, any, any>> = new Map();
34
+ schemas: Map<string,Schema<any>>=new Map();
35
+ commands:MessageCommand[]=[];
36
+ crons:Cron[]=[];
38
37
  #logger?:Logger
38
+ /**
39
+ * 构造函数:初始化插件,注册消息事件、命令中间件、资源清理等
40
+ * @param parent 所属 App 实例
41
+ * @param name 插件名
42
+ * @param filePath 插件文件路径
43
+ */
39
44
  constructor(parent: Dependency<Plugin>, name: string, filePath: string) {
40
45
  super(parent, name, filePath);
46
+ // 绑定消息事件,自动分发到命令和中间件
41
47
  this.on('message.receive',this.#handleMessage.bind(this))
48
+ // 注册命令处理为默认中间件
49
+ this.addMiddleware(async (message,next)=>{
50
+ for(const command of this.commands){
51
+ const result=await command.handle(message);
52
+ if(result) message.$reply(result);
53
+ }
54
+ return next()
55
+ });
56
+ // 发送前渲染组件
57
+ this.beforeSend((options)=>Component.render(this.components,options))
58
+ // 资源清理:卸载时清空模型、定时任务等
59
+ this.on('dispose',()=>{
60
+ for(const name of this.schemas.keys()){
61
+ this.app.database?.models.delete(name);
62
+ }
63
+ this.schemas.clear();
64
+ for(const cron of this.crons){
65
+ cron.dispose();
66
+ }
67
+ this.crons.length = 0;
68
+ });
69
+ // 挂载时启动定时任务
70
+ this.on('mounted',()=>{
71
+ for(const cron of this.crons){
72
+ cron.run();
73
+ }
74
+ });
42
75
  }
43
- #handleMessage(message:Message){
44
- const next=async (index:number)=>{
45
- if(!this.middlewares[index]) return
46
- const middleware=this.middlewares[index]
47
- middleware(message,()=>next(index+1))
76
+ async #handleMessage(message: Message) {
77
+ try {
78
+ await this.#runMiddlewares(message, 0)
79
+ } catch (error) {
80
+ const messageError = new MessageError(
81
+ `消息处理失败: ${(error as Error).message}`,
82
+ message.$id,
83
+ message.$channel.id,
84
+ { pluginName: this.name, originalError: error }
85
+ )
86
+
87
+ await errorManager.handle(messageError)
88
+
89
+ // 可选:发送错误回复给用户
90
+ try {
91
+ await message.$reply('抱歉,处理您的消息时出现了错误。')
92
+ } catch (replyError) {
93
+ // 静默处理回复错误,避免错误循环
94
+ // console.error 已替换为注释
95
+ }
96
+ }
97
+ }
98
+ cron(cronExpression:string,callback:()=>void){
99
+ const cronJob = new Cron(cronExpression,callback);
100
+ this.crons.push(cronJob);
101
+ return this;
102
+ }
103
+ async #runMiddlewares(message: Message, index: number): Promise<void> {
104
+ if (index >= this.middlewares.length) return
105
+
106
+ const middleware = this.middlewares[index]
107
+
108
+ try {
109
+ await middleware(message, () => this.#runMiddlewares(message, index + 1))
110
+ } catch (error) {
111
+ throw new PluginError(
112
+ `中间件执行失败: ${(error as Error).message}`,
113
+ this.name,
114
+ { middlewareIndex: index, originalError: error }
115
+ )
48
116
  }
49
- next(0)
117
+ }
118
+ defineModel<S extends Record<string,any>>(name:string,schema:Schema<S>){
119
+ this.schemas.set(name,schema);
120
+ return this;
50
121
  }
51
122
  beforeSend(handler:BeforeSendHandler){
52
123
  this.before('message.send',handler)
@@ -60,63 +131,74 @@ export class Plugin extends Dependency<Plugin> {
60
131
  }
61
132
  get logger(): Logger {
62
133
  if(this.#logger) return this.#logger
63
- const names = [this.name];
134
+ const names = [];
64
135
  let temp=this as Dependency<Plugin>
65
136
  while(temp.parent){
66
- names.unshift(temp.parent.name)
137
+ names.unshift(temp.name)
67
138
  temp=temp.parent
68
139
  }
69
- return this.#logger=this.app.getLogger(...names)
140
+ return temp.getLogger(names.join('/'))
141
+ }
142
+ /** 添加组件 */
143
+ addComponent<T = {}, D = {}, P = Component.Props<T>>(component:Component<T,D,P>){
144
+ this.components.set(component.name,component);
70
145
  }
71
-
72
146
  /** 添加中间件 */
73
- addMiddleware(middleware: MessageMiddleware): void {
147
+ addCommand(command:MessageCommand){
148
+ this.commands.push(command);
149
+ this.dispatch('command.add',command);
150
+ }
151
+ /** 添加中间件 */
152
+ addMiddleware<T extends RegisteredAdapter>(middleware: MessageMiddleware<T>) {
74
153
  this.middlewares.push(middleware);
75
154
  this.dispatch('middleware.add',middleware)
76
- }
77
-
78
- /** 添加事件监听器 */
79
- addEventListener<T = any>(event: string, listener: EventListener<T>): void {
80
- if (!this.eventListeners.has(event)) {
81
- this.eventListeners.set(event, []);
155
+ return ()=>{
156
+ remove(this.middlewares,middleware)
82
157
  }
83
- this.eventListeners.get(event)!.push(listener);
84
- this.dispatch('listener.add',event,listener)
85
158
  }
86
-
87
- /** 添加定时任务 */
88
- addCronJob(job: CronJob): void {
89
- this.cronJobs.set(job.name, job);
90
- this.dispatch('cron-job.add',job)
159
+ prompt<P extends RegisteredAdapter>(message:Message<AdapterMessage<P>>){
160
+ return new Prompt<P>(this,message)
91
161
  }
162
+
163
+
164
+
92
165
  /** 发送消息 */
93
- async sendMessage(options:SendOptions): Promise<void> {
94
- await this.app.sendMessage(options);
166
+ async sendMessage(options: SendOptions): Promise<void> {
167
+ try {
168
+ await this.app.sendMessage(options);
169
+ } catch (error) {
170
+ const messageError = new MessageError(
171
+ `发送消息失败: ${(error as Error).message}`,
172
+ undefined,
173
+ (options as any).channel_id,
174
+ { pluginName: this.name, sendOptions: options, originalError: error }
175
+ )
176
+
177
+ await errorManager.handle(messageError)
178
+ throw messageError
179
+ }
95
180
  }
96
181
 
97
182
  /** 销毁插件 */
98
183
  dispose(): void {
99
- // 移除所有中间件
100
- for (const middleware of this.middlewares) {
101
- this.dispatch('middleware.remove', middleware)
102
- }
103
- this.middlewares = []
104
-
105
- // 移除所有事件监听器
106
- for (const [event, listeners] of this.eventListeners) {
107
- for (const listener of listeners) {
108
- this.dispatch('listener.remove', event, listener)
184
+ try {
185
+ // 移除所有中间件
186
+ for (const middleware of this.middlewares) {
187
+ this.dispatch('middleware.remove', middleware)
109
188
  }
189
+ this.middlewares = []
190
+
191
+ // 调用父类的dispose方法
192
+ super.dispose()
193
+ } catch (error) {
194
+ const pluginError = new PluginError(
195
+ `插件销毁失败: ${(error as Error).message}`,
196
+ this.name,
197
+ { originalError: error }
198
+ )
199
+
200
+ errorManager.handle(pluginError).catch(console.error)
201
+ throw pluginError
110
202
  }
111
- this.eventListeners.clear()
112
-
113
- // 移除所有定时任务
114
- for (const [name, job] of this.cronJobs) {
115
- this.dispatch('cron-job.remove', job)
116
- }
117
- this.cronJobs.clear()
118
-
119
- // 调用父类的dispose方法
120
- super.dispose()
121
203
  }
122
204
  }