@zhin.js/core 1.0.1 → 1.0.3
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 +16 -0
- package/lib/app.d.ts +10 -2
- package/lib/app.d.ts.map +1 -1
- package/lib/app.js +27 -2
- package/lib/app.js.map +1 -1
- package/lib/bot.d.ts +4 -2
- package/lib/bot.d.ts.map +1 -1
- package/lib/command.d.ts +2 -1
- package/lib/command.d.ts.map +1 -1
- package/lib/command.js.map +1 -1
- package/lib/component.d.ts +22 -102
- package/lib/component.d.ts.map +1 -1
- package/lib/component.js +438 -242
- package/lib/component.js.map +1 -1
- package/lib/jsx-dev-runtime.d.ts +3 -0
- package/lib/jsx-dev-runtime.d.ts.map +1 -0
- package/lib/jsx-dev-runtime.js +3 -0
- package/lib/jsx-dev-runtime.js.map +1 -0
- package/lib/jsx-runtime.d.ts +12 -0
- package/lib/jsx-runtime.d.ts.map +1 -0
- package/lib/jsx-runtime.js +11 -0
- package/lib/jsx-runtime.js.map +1 -0
- package/lib/jsx.d.ts +32 -0
- package/lib/jsx.d.ts.map +1 -0
- package/lib/jsx.js +57 -0
- package/lib/jsx.js.map +1 -0
- package/lib/log-transport.d.ts +37 -0
- package/lib/log-transport.d.ts.map +1 -0
- package/lib/log-transport.js +136 -0
- package/lib/log-transport.js.map +1 -0
- package/lib/message.d.ts +10 -7
- package/lib/message.d.ts.map +1 -1
- package/lib/message.js.map +1 -1
- package/lib/models/system-log.d.ts +11 -0
- package/lib/models/system-log.d.ts.map +1 -0
- package/lib/models/system-log.js +9 -0
- package/lib/models/system-log.js.map +1 -0
- package/lib/plugin.d.ts +4 -3
- package/lib/plugin.d.ts.map +1 -1
- package/lib/plugin.js +12 -2
- package/lib/plugin.js.map +1 -1
- package/lib/prompt.d.ts.map +1 -1
- package/lib/prompt.js +3 -2
- package/lib/prompt.js.map +1 -1
- package/lib/types.d.ts +13 -15
- package/lib/types.d.ts.map +1 -1
- package/lib/utils.d.ts.map +1 -1
- package/lib/utils.js +3 -1
- package/lib/utils.js.map +1 -1
- package/package.json +16 -4
- package/src/app.ts +37 -4
- package/src/bot.ts +5 -3
- package/src/command.ts +2 -1
- package/src/component.ts +523 -280
- package/src/jsx-dev-runtime.ts +2 -0
- package/src/jsx-runtime.ts +12 -0
- package/src/jsx.d.ts +52 -0
- package/src/jsx.ts +92 -0
- package/src/log-transport.ts +163 -0
- package/src/message.ts +8 -5
- package/src/models/system-log.ts +20 -0
- package/src/plugin.ts +19 -5
- package/src/prompt.ts +3 -2
- package/src/types.ts +13 -13
- package/src/utils.ts +6 -5
- package/tests/component-new.test.ts +348 -0
- package/tests/expression-evaluation.test.ts +258 -0
- package/tests/plugin.test.ts +26 -17
- package/tests/component.test.ts +0 -656
package/src/jsx.d.ts
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { SendContent } from './types.js';
|
|
2
|
+
import { Component,ComponentContext } from './component.js';
|
|
3
|
+
import { MessageElement } from './types.js';
|
|
4
|
+
|
|
5
|
+
declare global {
|
|
6
|
+
namespace JSX {
|
|
7
|
+
interface Element {
|
|
8
|
+
type: string | Component<any>;
|
|
9
|
+
data: Record<string, any>;
|
|
10
|
+
children?: JSXChildren;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
interface ElementClass {
|
|
14
|
+
render(props: any, context?: ComponentContext): MaybePromise<SendContent>;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
interface ElementAttributesProperty {
|
|
18
|
+
data: {};
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
interface ElementChildrenAttribute {
|
|
22
|
+
children: {};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
interface IntrinsicElements {
|
|
26
|
+
// 简化的组件元素
|
|
27
|
+
fetch: JSXFetchElement;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// 简化的组件属性接口
|
|
33
|
+
interface JSXBaseElement {
|
|
34
|
+
children?: JSXChildren;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
interface JSXFetchElement extends JSXBaseElement {
|
|
38
|
+
url?: string;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// JSX 子元素类型
|
|
42
|
+
type JSXChildren = MessageElement | string | number | boolean | null | undefined | JSXChildren[];
|
|
43
|
+
|
|
44
|
+
// JSX 元素类型
|
|
45
|
+
type JSXElement = {
|
|
46
|
+
type: string | Component<any>;
|
|
47
|
+
data: Record<string, any>;
|
|
48
|
+
children?: JSXChildren;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
// 类型辅助
|
|
52
|
+
type MaybePromise<T> = T | Promise<T>;
|
package/src/jsx.ts
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { MaybePromise } from '@zhin.js/types';
|
|
2
|
+
import { SendContent,MessageElement } from './types.js';
|
|
3
|
+
import { MessageComponent } from './message.js';
|
|
4
|
+
import { Component, ComponentContext } from './component.js';
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
// JSX 子元素类型
|
|
8
|
+
export type JSXChildren = MessageElement | string | number | boolean | null | undefined | JSXChildren[];
|
|
9
|
+
|
|
10
|
+
// JSX 元素类型
|
|
11
|
+
export type JSXElementType = string | Component<any> ;
|
|
12
|
+
|
|
13
|
+
// JSX 属性类型
|
|
14
|
+
export type JSXProps = Record<string, any> & {
|
|
15
|
+
children?: JSXChildren;
|
|
16
|
+
};
|
|
17
|
+
export {Fragment} from './component.js'
|
|
18
|
+
// 全局 JSX 命名空间
|
|
19
|
+
declare global {
|
|
20
|
+
namespace JSX {
|
|
21
|
+
interface Element extends MessageComponent<any> {}
|
|
22
|
+
interface ElementClass {
|
|
23
|
+
render(props: any, context?: ComponentContext): MaybePromise<SendContent>;
|
|
24
|
+
}
|
|
25
|
+
interface ElementAttributesProperty {
|
|
26
|
+
data: {};
|
|
27
|
+
}
|
|
28
|
+
interface ElementChildrenAttribute {
|
|
29
|
+
children: {};
|
|
30
|
+
}
|
|
31
|
+
interface IntrinsicElements {
|
|
32
|
+
[elemName: string]: any;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// JSX 运行时函数
|
|
38
|
+
export function jsx(type: JSXElementType, data: JSXProps): MessageElement {
|
|
39
|
+
return {
|
|
40
|
+
type,
|
|
41
|
+
data,
|
|
42
|
+
} as MessageElement;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// JSX Fragment 支持
|
|
46
|
+
export function jsxs(type: JSXElementType, props: JSXProps): MessageElement {
|
|
47
|
+
return jsx(type, props);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
// JSX 渲染函数
|
|
52
|
+
export async function renderJSX(element: MessageComponent<any>, context?: ComponentContext): Promise<SendContent> {
|
|
53
|
+
if (typeof element.type === 'string') {
|
|
54
|
+
if (element.type === 'Fragment') {
|
|
55
|
+
return await renderChildren(element.data.children, context);
|
|
56
|
+
}
|
|
57
|
+
// 其他内置组件处理
|
|
58
|
+
return await renderChildren(element.data.children, context);
|
|
59
|
+
} else if (typeof element.type === 'function') {
|
|
60
|
+
// 函数组件
|
|
61
|
+
const component = element.type as Component<any>;
|
|
62
|
+
return await component(element.data, context || {} as ComponentContext);
|
|
63
|
+
} else {
|
|
64
|
+
// 类组件或其他类型
|
|
65
|
+
const component = element.type as Component<any>;
|
|
66
|
+
return await component(element.data, context || {} as ComponentContext);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// 渲染子元素
|
|
71
|
+
async function renderChildren(children: JSXChildren, context?: ComponentContext): Promise<SendContent> {
|
|
72
|
+
if (children == null) return '';
|
|
73
|
+
if (typeof children === 'string' || typeof children === 'number' || typeof children === 'boolean') {
|
|
74
|
+
return String(children);
|
|
75
|
+
}
|
|
76
|
+
if (Array.isArray(children)) {
|
|
77
|
+
const results = await Promise.all(children.map(async child => {
|
|
78
|
+
if (typeof child === 'string' || typeof child === 'number' || typeof child === 'boolean') {
|
|
79
|
+
return String(child);
|
|
80
|
+
}
|
|
81
|
+
if (child && typeof child === 'object' && 'type' in child) {
|
|
82
|
+
return await renderJSX(child as MessageComponent<any>, context);
|
|
83
|
+
}
|
|
84
|
+
return '';
|
|
85
|
+
}));
|
|
86
|
+
return results.join('');
|
|
87
|
+
}
|
|
88
|
+
if (children && typeof children === 'object' && 'type' in children) {
|
|
89
|
+
return await renderJSX(children as MessageComponent<any>, context);
|
|
90
|
+
}
|
|
91
|
+
return '';
|
|
92
|
+
}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import { LogTransport } from '@zhin.js/logger'
|
|
2
|
+
import { App } from './app.js'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* 数据库日志传输器
|
|
6
|
+
* 将日志存储到数据库,并自动清理旧日志
|
|
7
|
+
*/
|
|
8
|
+
export class DatabaseLogTransport implements LogTransport {
|
|
9
|
+
private app: App
|
|
10
|
+
private stripAnsiRegex = /\x1b\[[0-9;]*m/g
|
|
11
|
+
private cleanupTimer?: NodeJS.Timeout
|
|
12
|
+
private maxDays: number
|
|
13
|
+
private maxRecords: number
|
|
14
|
+
private cleanupInterval: number
|
|
15
|
+
|
|
16
|
+
constructor(app: App) {
|
|
17
|
+
this.app = app
|
|
18
|
+
|
|
19
|
+
// 从配置读取日志清理策略
|
|
20
|
+
const logConfig = app['config']?.log || {}
|
|
21
|
+
this.maxDays = logConfig.maxDays || 7 // 默认保留 7 天
|
|
22
|
+
this.maxRecords = logConfig.maxRecords || 10000 // 默认最多 10000 条
|
|
23
|
+
this.cleanupInterval = logConfig.cleanupInterval || 24 // 默认 24 小时清理一次
|
|
24
|
+
|
|
25
|
+
// 启动定时清理
|
|
26
|
+
this.startCleanup()
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* 启动定时清理任务
|
|
31
|
+
*/
|
|
32
|
+
private startCleanup(): void {
|
|
33
|
+
// 立即执行一次清理
|
|
34
|
+
this.cleanupOldLogs().catch(err => {
|
|
35
|
+
this.app.logger.error('[DatabaseLogTransport] Initial cleanup failed:', err.message)
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
// 设置定时任务
|
|
39
|
+
this.cleanupTimer = setInterval(() => {
|
|
40
|
+
this.cleanupOldLogs().catch(err => {
|
|
41
|
+
this.app.logger.error('[DatabaseLogTransport] Scheduled cleanup failed:', err.message)
|
|
42
|
+
})
|
|
43
|
+
}, this.cleanupInterval * 60 * 60 * 1000) // 转换为毫秒
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* 清理旧日志
|
|
48
|
+
*/
|
|
49
|
+
private async cleanupOldLogs(): Promise<void> {
|
|
50
|
+
if (!this.app.database) {
|
|
51
|
+
return
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
try {
|
|
55
|
+
const LogModel = this.app.database.model('SystemLog')
|
|
56
|
+
if (!LogModel) {
|
|
57
|
+
return
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// 1. 按时间清理:删除超过 maxDays 天的日志
|
|
61
|
+
const cutoffDate = new Date()
|
|
62
|
+
cutoffDate.setDate(cutoffDate.getDate() - this.maxDays)
|
|
63
|
+
|
|
64
|
+
const deletedByDate = await LogModel
|
|
65
|
+
.delete({ timestamp: { $lt: cutoffDate } })
|
|
66
|
+
|
|
67
|
+
// 2. 按数量清理:如果日志总数超过 maxRecords,删除最旧的
|
|
68
|
+
const total = await LogModel.select()
|
|
69
|
+
const totalCount = total.length
|
|
70
|
+
|
|
71
|
+
if (totalCount > this.maxRecords) {
|
|
72
|
+
const excessCount = totalCount - this.maxRecords
|
|
73
|
+
|
|
74
|
+
// 查找最旧的 excessCount 条日志的 ID
|
|
75
|
+
const oldestLogs = await LogModel
|
|
76
|
+
.select('id','timestamp')
|
|
77
|
+
.orderBy('timestamp', 'ASC')
|
|
78
|
+
.limit(excessCount)
|
|
79
|
+
|
|
80
|
+
const idsToDelete = oldestLogs.map((log: any) => log.id)
|
|
81
|
+
|
|
82
|
+
if (idsToDelete.length > 0) {
|
|
83
|
+
await LogModel
|
|
84
|
+
.delete({ id: { $in: idsToDelete } })
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
this.app.logger.info(
|
|
89
|
+
`[DatabaseLogTransport] Log cleanup completed. ` +
|
|
90
|
+
`Deleted ${deletedByDate || 0} logs older than ${this.maxDays} days. ` +
|
|
91
|
+
`Current total: ${Math.max(0, totalCount - (deletedByDate || 0))} logs.`
|
|
92
|
+
)
|
|
93
|
+
} catch (error) {
|
|
94
|
+
// 静默处理错误
|
|
95
|
+
this.app.logger.error('[DatabaseLogTransport] Cleanup error:', (error as Error).message)
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* 停止清理任务
|
|
101
|
+
*/
|
|
102
|
+
public stopCleanup(): void {
|
|
103
|
+
if (this.cleanupTimer) {
|
|
104
|
+
clearInterval(this.cleanupTimer)
|
|
105
|
+
this.cleanupTimer = undefined
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* 移除 ANSI 颜色代码
|
|
111
|
+
*/
|
|
112
|
+
private stripAnsi(str: string): string {
|
|
113
|
+
return str.replace(this.stripAnsiRegex, '')
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
write(message: string): void {
|
|
117
|
+
// 移除 ANSI 颜色代码
|
|
118
|
+
const cleanMessage = this.stripAnsi(message)
|
|
119
|
+
|
|
120
|
+
// 解析日志消息
|
|
121
|
+
// 格式: [09-08 04:07:55.852] [INFO] [MyApp]: message
|
|
122
|
+
const logRegex = /\[[\d-]+ [\d:.]+\] \[(\w+)\] \[([^\]]+)\]: ([\s\S]+)/
|
|
123
|
+
const match = cleanMessage.match(logRegex)
|
|
124
|
+
|
|
125
|
+
if (match) {
|
|
126
|
+
const [, level, name, msg] = match
|
|
127
|
+
const source = name.split(':')[0] // 取第一部分作为 source
|
|
128
|
+
|
|
129
|
+
// 异步存储到数据库,不阻塞日志输出
|
|
130
|
+
this.saveToDatabase(level.toLowerCase(), name, msg.trim(), source).catch(err => {
|
|
131
|
+
// 避免日志存储失败导致应用崩溃
|
|
132
|
+
console.error('[DatabaseLogTransport] Failed to save log:', err.message)
|
|
133
|
+
})
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* 保存日志到数据库
|
|
139
|
+
*/
|
|
140
|
+
private async saveToDatabase(level: string, name: string, message: string, source: string): Promise<void> {
|
|
141
|
+
if (!this.app.database) {
|
|
142
|
+
return // 没有数据库则跳过
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
try {
|
|
146
|
+
const LogModel = this.app.database.model('SystemLog')
|
|
147
|
+
if (!LogModel) {
|
|
148
|
+
return // 模型不存在则跳过
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
await LogModel.create({
|
|
152
|
+
level,
|
|
153
|
+
name,
|
|
154
|
+
message,
|
|
155
|
+
source,
|
|
156
|
+
timestamp: new Date()
|
|
157
|
+
})
|
|
158
|
+
} catch (error) {
|
|
159
|
+
// 静默处理错误,避免干扰主流程
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
package/src/message.ts
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import {MessageElement, MessageSender, SendContent} from "./types";
|
|
2
|
+
import { Component } from "./component.js";
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* 消息组件类型:用于自定义消息结构
|
|
6
6
|
*/
|
|
7
|
-
export type MessageComponent<T extends object>=
|
|
7
|
+
export type MessageComponent<T extends object>={
|
|
8
|
+
type:Component<T&{children?:SendContent}>
|
|
9
|
+
data:T
|
|
10
|
+
}
|
|
8
11
|
/**
|
|
9
12
|
* 消息频道信息
|
|
10
13
|
*/
|
|
@@ -23,9 +26,9 @@ export interface MessageBase {
|
|
|
23
26
|
$id: string;
|
|
24
27
|
$adapter:string
|
|
25
28
|
$bot:string
|
|
26
|
-
$content:
|
|
29
|
+
$content: MessageElement[];
|
|
27
30
|
$sender: MessageSender;
|
|
28
|
-
$reply(content:SendContent,quote?:boolean|string):Promise<
|
|
31
|
+
$reply(content:SendContent,quote?:boolean|string):Promise<string>
|
|
29
32
|
$channel: MessageChannel;
|
|
30
33
|
$timestamp: number;
|
|
31
34
|
$raw: string;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Schema } from '@zhin.js/database'
|
|
2
|
+
|
|
3
|
+
export interface SystemLog {
|
|
4
|
+
id?: number
|
|
5
|
+
level: string
|
|
6
|
+
name: string
|
|
7
|
+
message: string
|
|
8
|
+
source: string
|
|
9
|
+
timestamp: Date
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const SystemLogSchema:Schema<SystemLog>={
|
|
13
|
+
id: { type: 'integer', autoIncrement: true, primary: true },
|
|
14
|
+
level: { type: 'text', nullable: false },
|
|
15
|
+
name: { type: 'text', nullable: false },
|
|
16
|
+
message: { type: 'text', nullable: false },
|
|
17
|
+
source: { type: 'text', nullable: false },
|
|
18
|
+
timestamp: { type: 'date', nullable: false }
|
|
19
|
+
}
|
|
20
|
+
|
package/src/plugin.ts
CHANGED
|
@@ -9,7 +9,7 @@ import {Message} from './message.js'
|
|
|
9
9
|
import {Dependency, Logger,} from "@zhin.js/hmr";
|
|
10
10
|
import {App} from "./app";
|
|
11
11
|
import {MessageCommand} from "./command.js";
|
|
12
|
-
import {Component} from "./component.js";
|
|
12
|
+
import {Component, renderComponents} from "./component.js";
|
|
13
13
|
import { PluginError, MessageError, errorManager } from './errors.js';
|
|
14
14
|
import {remove} from "./utils.js";
|
|
15
15
|
import {Prompt} from "./prompt.js";
|
|
@@ -29,8 +29,8 @@ export type MessageMiddleware<P extends RegisteredAdapter=RegisteredAdapter> = (
|
|
|
29
29
|
* 支持命令注册、中间件、组件、定时任务、模型等。
|
|
30
30
|
*/
|
|
31
31
|
export class Plugin extends Dependency<Plugin> {
|
|
32
|
-
middlewares: MessageMiddleware<
|
|
33
|
-
components: Map<string, Component<any
|
|
32
|
+
middlewares: MessageMiddleware<RegisteredAdapter>[] = [];
|
|
33
|
+
components: Map<string, Component<any>> = new Map();
|
|
34
34
|
schemas: Map<string,Schema<any>>=new Map();
|
|
35
35
|
commands:MessageCommand[]=[];
|
|
36
36
|
crons:Cron[]=[];
|
|
@@ -54,7 +54,7 @@ export class Plugin extends Dependency<Plugin> {
|
|
|
54
54
|
return next()
|
|
55
55
|
});
|
|
56
56
|
// 发送前渲染组件
|
|
57
|
-
this.beforeSend((options)=>
|
|
57
|
+
this.beforeSend((options)=>renderComponents(this.components,options))
|
|
58
58
|
// 资源清理:卸载时清空模型、定时任务等
|
|
59
59
|
this.on('dispose',()=>{
|
|
60
60
|
for(const name of this.schemas.keys()){
|
|
@@ -140,7 +140,7 @@ export class Plugin extends Dependency<Plugin> {
|
|
|
140
140
|
return temp.getLogger(names.join('/'))
|
|
141
141
|
}
|
|
142
142
|
/** 添加组件 */
|
|
143
|
-
addComponent<T
|
|
143
|
+
addComponent<T=any>(component:Component<T>){
|
|
144
144
|
this.components.set(component.name,component);
|
|
145
145
|
}
|
|
146
146
|
/** 添加中间件 */
|
|
@@ -178,6 +178,20 @@ export class Plugin extends Dependency<Plugin> {
|
|
|
178
178
|
throw messageError
|
|
179
179
|
}
|
|
180
180
|
}
|
|
181
|
+
recallMessage(adapter:string,bot:string,id:string){
|
|
182
|
+
try{
|
|
183
|
+
this.app.recallMessage(adapter,bot,id)
|
|
184
|
+
}catch(error){
|
|
185
|
+
const messageError = new MessageError(
|
|
186
|
+
`撤回消息失败: ${(error as Error).message}`,
|
|
187
|
+
id,
|
|
188
|
+
undefined,
|
|
189
|
+
{ originalError: error }
|
|
190
|
+
)
|
|
191
|
+
errorManager.handle(messageError)
|
|
192
|
+
throw messageError
|
|
193
|
+
}
|
|
194
|
+
}
|
|
181
195
|
|
|
182
196
|
/** 销毁插件 */
|
|
183
197
|
dispose(): void {
|
package/src/prompt.ts
CHANGED
|
@@ -27,8 +27,8 @@ export class Prompt<P extends RegisteredAdapter> {
|
|
|
27
27
|
* @param config 提问配置
|
|
28
28
|
*/
|
|
29
29
|
private prompt<T = any>(config: Prompt.Config<T>) {
|
|
30
|
-
return new Promise<T>((resolve, reject) => {
|
|
31
|
-
this.event.$reply(config.tips);
|
|
30
|
+
return new Promise<T>(async (resolve, reject) => {
|
|
31
|
+
const id = await this.event.$reply(config.tips);
|
|
32
32
|
this.middleware(
|
|
33
33
|
input => {
|
|
34
34
|
if (input instanceof Error) {
|
|
@@ -37,6 +37,7 @@ export class Prompt<P extends RegisteredAdapter> {
|
|
|
37
37
|
else reject(input);
|
|
38
38
|
return;
|
|
39
39
|
}
|
|
40
|
+
this.plugin.recallMessage(this.event.$adapter,this.event.$bot,id);
|
|
40
41
|
resolve(config.format(input));
|
|
41
42
|
},
|
|
42
43
|
config.timeout,
|
package/src/types.ts
CHANGED
|
@@ -1,20 +1,10 @@
|
|
|
1
|
-
import {MaybePromise}from '@zhin.js/types'
|
|
1
|
+
import {MaybePromise,RegisteredAdapters}from '@zhin.js/types'
|
|
2
2
|
import {MessageChannel} from "./message.js";
|
|
3
3
|
import {Adapter} from "./adapter.js";
|
|
4
4
|
import {Bot,BotConfig} from "./bot.js";
|
|
5
5
|
import { Databases,Registry } from "@zhin.js/database";
|
|
6
|
+
import { MessageComponent } from "./message.js";
|
|
6
7
|
|
|
7
|
-
/**
|
|
8
|
-
* 类型定义文件:包含适配器、消息、数据库、配置等核心类型声明。
|
|
9
|
-
* 协作者可通过本文件了解各主要数据结构的用途与关系。
|
|
10
|
-
*/
|
|
11
|
-
declare module '@zhin.js/types'{
|
|
12
|
-
interface GlobalContext extends RegisteredAdapters{}
|
|
13
|
-
}
|
|
14
|
-
/**
|
|
15
|
-
* 所有已注册适配器的类型映射(key为适配器名,value为Adapter实例)
|
|
16
|
-
*/
|
|
17
|
-
export interface RegisteredAdapters extends Record<string, Adapter>{}
|
|
18
8
|
/**
|
|
19
9
|
* 数据库配置类型,支持多种数据库驱动
|
|
20
10
|
*/
|
|
@@ -52,6 +42,7 @@ export interface MessageSegment {
|
|
|
52
42
|
type: string;
|
|
53
43
|
data: Record<string, any>;
|
|
54
44
|
}
|
|
45
|
+
export type MessageElement=MessageSegment|MessageComponent<any>
|
|
55
46
|
/**
|
|
56
47
|
* 单个或数组类型
|
|
57
48
|
*/
|
|
@@ -59,7 +50,7 @@ export type MaybeArray<T>=T|T[]
|
|
|
59
50
|
/**
|
|
60
51
|
* 消息发送内容类型
|
|
61
52
|
*/
|
|
62
|
-
export type SendContent=MaybeArray<string|
|
|
53
|
+
export type SendContent=MaybeArray<string|MessageElement>
|
|
63
54
|
/**
|
|
64
55
|
* 消息发送者信息
|
|
65
56
|
*/
|
|
@@ -107,6 +98,15 @@ export interface AppConfig {
|
|
|
107
98
|
disable_dependencies?: string[];
|
|
108
99
|
/** 是否启用调试模式 */
|
|
109
100
|
debug?: boolean;
|
|
101
|
+
/** 日志配置 */
|
|
102
|
+
log?: {
|
|
103
|
+
/** 最大日志保留天数,默认 7 天 */
|
|
104
|
+
maxDays?: number;
|
|
105
|
+
/** 最大日志条数,默认 10000 条 */
|
|
106
|
+
maxRecords?: number;
|
|
107
|
+
/** 自动清理间隔(小时),默认 24 小时 */
|
|
108
|
+
cleanupInterval?: number;
|
|
109
|
+
};
|
|
110
110
|
}
|
|
111
111
|
/**
|
|
112
112
|
* defineConfig辅助类型,支持函数式/对象式配置
|
package/src/utils.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {Dict, MessageSegment, SendContent} from "./types";
|
|
1
|
+
import {Dict, MessageElement, MessageSegment, SendContent} from "./types";
|
|
2
2
|
|
|
3
3
|
export function getValueWithRuntime(template: string, ctx: Dict) {
|
|
4
4
|
const result = evaluate(template, ctx);
|
|
@@ -79,10 +79,10 @@ export namespace segment{
|
|
|
79
79
|
}
|
|
80
80
|
export function from(content: SendContent): SendContent {
|
|
81
81
|
if (!Array.isArray(content)) content=[content];
|
|
82
|
-
const toString=(template:string|
|
|
82
|
+
const toString=(template:string|MessageElement)=>{
|
|
83
83
|
if(typeof template!=='string') return [template]
|
|
84
84
|
template=unescape(template);
|
|
85
|
-
const result:
|
|
85
|
+
const result: MessageElement[] = [];
|
|
86
86
|
const closingReg = /<(\S+)(\s[^>]+)?\/>/;
|
|
87
87
|
const twinningReg = /<(\S+)(\s[^>]+)?>([\s\S]*?)<\/\1>/;
|
|
88
88
|
while (template.length) {
|
|
@@ -132,7 +132,7 @@ export namespace segment{
|
|
|
132
132
|
return content.reduce((result,item)=>{
|
|
133
133
|
result.push(...toString(item))
|
|
134
134
|
return result;
|
|
135
|
-
},[] as
|
|
135
|
+
},[] as MessageElement[])
|
|
136
136
|
}
|
|
137
137
|
export function raw(content:SendContent){
|
|
138
138
|
if(!Array.isArray(content)) content=[content]
|
|
@@ -147,7 +147,8 @@ export namespace segment{
|
|
|
147
147
|
if(!Array.isArray(content)) content=[content]
|
|
148
148
|
return content.map(item=>{
|
|
149
149
|
if(typeof item==='string') return item
|
|
150
|
-
|
|
150
|
+
let {type,data}=item
|
|
151
|
+
if(typeof type==='function') type=type.name
|
|
151
152
|
if(type==='text') return data.text
|
|
152
153
|
return `<${type} ${Object.keys(data).map(key=>`${key}='${escape(JSON.stringify(data[key]))}'`).join(' ')}/>`
|
|
153
154
|
}).join('')
|