@atri-bot/core 1.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/README.md +7 -0
- package/dist/index.d.ts +287 -0
- package/dist/index.js +578 -0
- package/package.json +31 -0
package/README.md
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
<img src="https://github.com/HkTeamX/ATRI/blob/main/ATRI.png?raw=true" align="right" style="height:530px;width:450px;" />
|
|
2
|
+
|
|
3
|
+
# 🤖 ATRI
|
|
4
|
+
|
|
5
|
+
基于 [NapCat](https://github.com/NapNeko/NapCatQQ) 设计的机器人框架
|
|
6
|
+
|
|
7
|
+
取名来自 [亚托莉(ATRI)](https://mzh.moegirl.org.cn/%E4%BA%9A%E6%89%98%E8%8E%89)
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
import { Logger, LogLevel, InjectLogger } from '@huan_kong/logger';
|
|
2
|
+
import { Command } from 'commander';
|
|
3
|
+
import { MessageHandler, NoticeHandler, RequestHandler, NCWebsocket, NCWebsocketOptions, SendMessageSegment, NodeSegment } from 'node-napcat-ts';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* 非空数组
|
|
7
|
+
*/
|
|
8
|
+
type NonEmptyArray<T> = [T, ...T[]];
|
|
9
|
+
/**
|
|
10
|
+
* 移除对象中的某个字段
|
|
11
|
+
*/
|
|
12
|
+
type RemoveField<T, KToRemove extends keyof T> = {
|
|
13
|
+
[K in keyof T as K extends KToRemove ? never : K]: T[K];
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
type CallbackReturnType = void | 'quit';
|
|
17
|
+
type CallbackReturn = Promise<CallbackReturnType> | CallbackReturnType;
|
|
18
|
+
type OptionParams = Record<string, any>;
|
|
19
|
+
type OptionArgs = any[];
|
|
20
|
+
interface CommandContext {
|
|
21
|
+
params?: OptionParams;
|
|
22
|
+
args?: OptionArgs;
|
|
23
|
+
}
|
|
24
|
+
interface CommandCallback<Opts extends CommandContext = CommandContext, T extends keyof MessageHandler = 'message'> {
|
|
25
|
+
context: MessageHandler[T];
|
|
26
|
+
prefix: string;
|
|
27
|
+
commandName: string;
|
|
28
|
+
params: Opts['params'];
|
|
29
|
+
args: Opts['args'];
|
|
30
|
+
}
|
|
31
|
+
interface CommandEvent<Opts extends CommandContext = CommandContext, T extends keyof MessageHandler = 'message'> {
|
|
32
|
+
type: 'command';
|
|
33
|
+
endPoint?: T;
|
|
34
|
+
callback: (context: CommandCallback<Opts, T>) => CallbackReturn;
|
|
35
|
+
pluginName: string;
|
|
36
|
+
commandName: string | RegExp;
|
|
37
|
+
commander?: Command;
|
|
38
|
+
priority?: number;
|
|
39
|
+
needHide?: boolean;
|
|
40
|
+
needReply?: boolean;
|
|
41
|
+
needAdmin?: boolean;
|
|
42
|
+
}
|
|
43
|
+
interface MessageCallback<T extends keyof MessageHandler = 'message'> {
|
|
44
|
+
context: MessageHandler[T];
|
|
45
|
+
}
|
|
46
|
+
interface MessageEvent<T extends keyof MessageHandler = 'message'> {
|
|
47
|
+
type: 'message';
|
|
48
|
+
endPoint?: T;
|
|
49
|
+
regexp?: RegExp;
|
|
50
|
+
callback: (context: MessageCallback<T>) => CallbackReturn;
|
|
51
|
+
pluginName: string;
|
|
52
|
+
priority?: number;
|
|
53
|
+
needReply?: boolean;
|
|
54
|
+
needAdmin?: boolean;
|
|
55
|
+
}
|
|
56
|
+
interface NoticeCallback<T extends keyof NoticeHandler = 'notice'> {
|
|
57
|
+
context: NoticeHandler[T];
|
|
58
|
+
}
|
|
59
|
+
interface NoticeEvent<T extends keyof NoticeHandler = 'notice'> {
|
|
60
|
+
type: 'notice';
|
|
61
|
+
endPoint?: T;
|
|
62
|
+
callback: (context: NoticeCallback<T>) => CallbackReturn;
|
|
63
|
+
pluginName: string;
|
|
64
|
+
priority?: number;
|
|
65
|
+
}
|
|
66
|
+
interface RequestCallback<T extends keyof RequestHandler = 'request'> {
|
|
67
|
+
context: RequestHandler[T];
|
|
68
|
+
}
|
|
69
|
+
interface RequestEvent<T extends keyof RequestHandler = 'request'> {
|
|
70
|
+
type: 'request';
|
|
71
|
+
endPoint?: T;
|
|
72
|
+
callback: (context: RequestCallback<T>) => CallbackReturn;
|
|
73
|
+
pluginName: string;
|
|
74
|
+
priority?: number;
|
|
75
|
+
}
|
|
76
|
+
type RegEventOptions = CommandEvent | MessageEvent | NoticeEvent | RequestEvent;
|
|
77
|
+
type AutoInferCommandEndPoint<Opts extends CommandContext = CommandContext> = {
|
|
78
|
+
[T in keyof MessageHandler]: RemoveField<CommandEvent<Opts, T>, 'pluginName' | 'type'> & {
|
|
79
|
+
endPoint: T;
|
|
80
|
+
};
|
|
81
|
+
}[keyof MessageHandler];
|
|
82
|
+
type AutoInferMessageEndPoint = {
|
|
83
|
+
[T in keyof MessageHandler]: RemoveField<MessageEvent<T>, 'pluginName' | 'type'> & {
|
|
84
|
+
endPoint: T;
|
|
85
|
+
};
|
|
86
|
+
}[keyof MessageHandler];
|
|
87
|
+
type AutoInferRequestEndPoint = {
|
|
88
|
+
[T in keyof RequestHandler]: RemoveField<RequestEvent<T>, 'pluginName' | 'type'> & {
|
|
89
|
+
endPoint: T;
|
|
90
|
+
};
|
|
91
|
+
}[keyof RequestHandler];
|
|
92
|
+
type AutoInferNoticeEndPoint = {
|
|
93
|
+
[T in keyof NoticeHandler]: RemoveField<NoticeEvent<T>, 'pluginName' | 'type'> & {
|
|
94
|
+
endPoint: T;
|
|
95
|
+
};
|
|
96
|
+
}[keyof NoticeHandler];
|
|
97
|
+
declare abstract class BasePlugin<TConfig extends object = object> {
|
|
98
|
+
disableAutoLoadConfig?: boolean;
|
|
99
|
+
configName?: string;
|
|
100
|
+
defaultConfig?: TConfig;
|
|
101
|
+
config: TConfig;
|
|
102
|
+
atri: ATRI;
|
|
103
|
+
bot: Bot;
|
|
104
|
+
ws: NCWebsocket;
|
|
105
|
+
private unregHandlers;
|
|
106
|
+
logger: Logger;
|
|
107
|
+
abstract pluginName: string;
|
|
108
|
+
constructor(atri: ATRI);
|
|
109
|
+
initLogger(): void;
|
|
110
|
+
abstract load(): void | Promise<void>;
|
|
111
|
+
abstract unload(): void | Promise<void>;
|
|
112
|
+
setConfig(config: TConfig): void;
|
|
113
|
+
saveConfig(config?: TConfig): void;
|
|
114
|
+
getDisableAutoLoadConfig(): boolean | undefined;
|
|
115
|
+
getConfigName(): string;
|
|
116
|
+
getDefaultConfig(): TConfig;
|
|
117
|
+
getUnregHandlers(): UnRegHandler[];
|
|
118
|
+
getPluginName(): string;
|
|
119
|
+
reg_command_event<Opts extends CommandContext = CommandContext>(options: AutoInferCommandEndPoint<Opts>): () => void;
|
|
120
|
+
reg_command_event<Opts extends CommandContext = CommandContext>(options: RemoveField<CommandEvent<Opts, 'message'>, 'pluginName' | 'type'>): () => void;
|
|
121
|
+
reg_message_event(options: AutoInferMessageEndPoint): () => void;
|
|
122
|
+
reg_message_event(options: RemoveField<MessageEvent<'message'>, 'pluginName' | 'type'>): () => void;
|
|
123
|
+
reg_request_event(options: AutoInferRequestEndPoint): () => void;
|
|
124
|
+
reg_request_event(options: RemoveField<RequestEvent<'request'>, 'pluginName' | 'type'>): () => void;
|
|
125
|
+
reg_notice_event(options: AutoInferNoticeEndPoint): () => void;
|
|
126
|
+
reg_notice_event(options: RemoveField<NoticeEvent<'notice'>, 'pluginName' | 'type'>): () => void;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
type BotConfig = {
|
|
130
|
+
debug?: boolean;
|
|
131
|
+
logLevel?: LogLevel;
|
|
132
|
+
prefix: NonEmptyArray<string>;
|
|
133
|
+
adminId: NonEmptyArray<number>;
|
|
134
|
+
connection: RemoveField<NCWebsocketOptions, 'reconnection'>;
|
|
135
|
+
reconnection: NCWebsocketOptions['reconnection'];
|
|
136
|
+
};
|
|
137
|
+
type UnRegHandler = () => void;
|
|
138
|
+
interface BotEvents {
|
|
139
|
+
command: CommandEvent[];
|
|
140
|
+
message: MessageEvent[];
|
|
141
|
+
notice: NoticeEvent[];
|
|
142
|
+
request: RequestEvent[];
|
|
143
|
+
}
|
|
144
|
+
interface CommandData {
|
|
145
|
+
prefix: string;
|
|
146
|
+
commandName: string;
|
|
147
|
+
params: OptionParams;
|
|
148
|
+
args: OptionArgs;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
declare class Bot extends InjectLogger {
|
|
152
|
+
ws: NCWebsocket;
|
|
153
|
+
config: BotConfig;
|
|
154
|
+
events: BotEvents;
|
|
155
|
+
private constructor();
|
|
156
|
+
static init(config: BotConfig): Promise<Bot>;
|
|
157
|
+
/**
|
|
158
|
+
* 注册事件
|
|
159
|
+
*/
|
|
160
|
+
regEvent(_options: RegEventOptions): () => void;
|
|
161
|
+
/**
|
|
162
|
+
* 解析命令
|
|
163
|
+
* @param rawMessage 原始消息
|
|
164
|
+
* @param commandName 命令名称
|
|
165
|
+
* @param command 命令对象
|
|
166
|
+
* @returns 解析结果
|
|
167
|
+
*/
|
|
168
|
+
parseCommand(rawMessage: string, commandName: CommandEvent['commandName'], command?: Command): [0, CommandData] | [1, string] | [2, string];
|
|
169
|
+
/**
|
|
170
|
+
* 获取命令信息
|
|
171
|
+
* @param command 命令对象
|
|
172
|
+
* @param fallback 后备值
|
|
173
|
+
* @param field 字段名
|
|
174
|
+
* @returns 命令信息
|
|
175
|
+
*/
|
|
176
|
+
getCommandInfo(command: Command, fallback: string, field?: 'name' | 'description'): string;
|
|
177
|
+
/**
|
|
178
|
+
* 获取命令帮助信息
|
|
179
|
+
* @param commandName 命令名称
|
|
180
|
+
*/
|
|
181
|
+
getCommandHelpInformation(commandName: string): string | undefined;
|
|
182
|
+
/**
|
|
183
|
+
* 发送普通消息
|
|
184
|
+
*/
|
|
185
|
+
sendMsg(context: {
|
|
186
|
+
message_type: 'private';
|
|
187
|
+
user_id: number;
|
|
188
|
+
message_id?: number;
|
|
189
|
+
} | {
|
|
190
|
+
message_type: 'group';
|
|
191
|
+
group_id: number;
|
|
192
|
+
user_id?: number;
|
|
193
|
+
message_id?: number;
|
|
194
|
+
}, message: SendMessageSegment[], { reply, at }?: {
|
|
195
|
+
reply?: boolean | undefined;
|
|
196
|
+
at?: boolean | undefined;
|
|
197
|
+
}): Promise<{
|
|
198
|
+
message_id: number;
|
|
199
|
+
} | null>;
|
|
200
|
+
/**
|
|
201
|
+
* 发送合并转发
|
|
202
|
+
*/
|
|
203
|
+
sendForwardMsg(context: {
|
|
204
|
+
message_type: 'group';
|
|
205
|
+
group_id: number;
|
|
206
|
+
} | {
|
|
207
|
+
message_type: 'private';
|
|
208
|
+
user_id: number;
|
|
209
|
+
}, message: NodeSegment[]): Promise<{
|
|
210
|
+
message_id: number;
|
|
211
|
+
} | null>;
|
|
212
|
+
/**
|
|
213
|
+
* 判断是否是机器人的好友
|
|
214
|
+
*/
|
|
215
|
+
isFriend(context: {
|
|
216
|
+
user_id: number;
|
|
217
|
+
}): Promise<{
|
|
218
|
+
birthday_year: number;
|
|
219
|
+
birthday_month: number;
|
|
220
|
+
birthday_day: number;
|
|
221
|
+
user_id: number;
|
|
222
|
+
age: number;
|
|
223
|
+
phone_num: string;
|
|
224
|
+
email: string;
|
|
225
|
+
category_id: number;
|
|
226
|
+
nickname: string;
|
|
227
|
+
remark: string;
|
|
228
|
+
sex: "male" | "female" | "unknown";
|
|
229
|
+
level: number;
|
|
230
|
+
} | undefined>;
|
|
231
|
+
/**
|
|
232
|
+
* 获取用户名
|
|
233
|
+
*/
|
|
234
|
+
getUsername(context: {
|
|
235
|
+
user_id: number;
|
|
236
|
+
} | {
|
|
237
|
+
user_id: number;
|
|
238
|
+
group_id: number;
|
|
239
|
+
}): Promise<string>;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
type ATRIConfig = {
|
|
243
|
+
bot: BotConfig;
|
|
244
|
+
debug?: boolean;
|
|
245
|
+
baseDir: string;
|
|
246
|
+
configDir?: string;
|
|
247
|
+
logLevel?: LogLevel;
|
|
248
|
+
disableClearTerminal?: boolean;
|
|
249
|
+
disableStartupMessage?: boolean;
|
|
250
|
+
disableAutoLoadPlugins?: boolean;
|
|
251
|
+
};
|
|
252
|
+
interface PluginModule {
|
|
253
|
+
Plugin?: new (...args: ConstructorParameters<typeof BasePlugin>) => BasePlugin;
|
|
254
|
+
}
|
|
255
|
+
type LoadPluginHook = (plugin: BasePlugin) => Promise<boolean> | boolean;
|
|
256
|
+
|
|
257
|
+
declare class ATRI extends InjectLogger {
|
|
258
|
+
config: ATRIConfig;
|
|
259
|
+
configDir: string;
|
|
260
|
+
bot: Bot;
|
|
261
|
+
loadedPlugins: Record<string, BasePlugin>;
|
|
262
|
+
loadPluginHooks: Record<string, LoadPluginHook>;
|
|
263
|
+
private constructor();
|
|
264
|
+
static init(config: ATRIConfig): Promise<ATRI>;
|
|
265
|
+
loadPlugin(importFunction: () => Promise<PluginModule>): Promise<boolean>;
|
|
266
|
+
unloadPlugin(pluginName: string): Promise<boolean>;
|
|
267
|
+
loadConfig<TConfig extends object>(pluginName: string, defaultConfig: TConfig): Promise<{}>;
|
|
268
|
+
saveConfig<TConfig extends object>(pluginName: string, config: TConfig): Promise<void>;
|
|
269
|
+
addPluginLoadHook(hookName: string, hook: LoadPluginHook): void;
|
|
270
|
+
removePluginLoadHook(hookName: string): void;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* 性能计时器
|
|
275
|
+
* 返回一个获取当前时间耗时的函数
|
|
276
|
+
*/
|
|
277
|
+
declare function performanceCounter(): () => string;
|
|
278
|
+
/**
|
|
279
|
+
* 排序对象数组
|
|
280
|
+
* @param arr 对象数组
|
|
281
|
+
* @param property 属性名
|
|
282
|
+
* @param sortType up=>升序 down=>降序
|
|
283
|
+
*/
|
|
284
|
+
declare function sortObjectArray<T extends object>(arr: T[], property: keyof T, sortType?: 'up' | 'down'): T[];
|
|
285
|
+
declare function getImportItemName(importFunction: () => Promise<any>): string;
|
|
286
|
+
|
|
287
|
+
export { ATRI, type ATRIConfig, type AutoInferCommandEndPoint, type AutoInferMessageEndPoint, type AutoInferNoticeEndPoint, type AutoInferRequestEndPoint, BasePlugin, Bot, type BotConfig, type BotEvents, type CallbackReturn, type CallbackReturnType, type CommandCallback, type CommandContext, type CommandData, type CommandEvent, type LoadPluginHook, type MessageCallback, type MessageEvent, type NonEmptyArray, type NoticeCallback, type NoticeEvent, type OptionArgs, type OptionParams, type PluginModule, type RegEventOptions, type RemoveField, type RequestCallback, type RequestEvent, type UnRegHandler, getImportItemName, performanceCounter, sortObjectArray };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,578 @@
|
|
|
1
|
+
// src/atri.ts
|
|
2
|
+
import { InjectLogger as InjectLogger2, Logger as Logger2, LogLevel as LogLevel2 } from "@huan_kong/logger";
|
|
3
|
+
import fs from "fs";
|
|
4
|
+
import path from "path";
|
|
5
|
+
|
|
6
|
+
// src/bot.ts
|
|
7
|
+
import { InjectLogger, Logger, LogLevel } from "@huan_kong/logger";
|
|
8
|
+
import { CommanderError } from "commander";
|
|
9
|
+
import { NCWebsocket, Structs } from "node-napcat-ts";
|
|
10
|
+
|
|
11
|
+
// src/utils.ts
|
|
12
|
+
function performanceCounter() {
|
|
13
|
+
const startTime = performance.now();
|
|
14
|
+
return () => {
|
|
15
|
+
const endTime = performance.now();
|
|
16
|
+
return (endTime - startTime).toFixed(2);
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
function sortObjectArray(arr, property, sortType = "up") {
|
|
20
|
+
return arr.sort((a, b) => {
|
|
21
|
+
if (a[property] > b[property]) return sortType === "up" ? 1 : -1;
|
|
22
|
+
if (a[property] < b[property]) return sortType === "up" ? -1 : 1;
|
|
23
|
+
return 0;
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
function getImportItemName(importFunction) {
|
|
27
|
+
const match = importFunction.toString().match(/import\(([^)]+)\)/);
|
|
28
|
+
return match ? match[1].replace(/['"]/g, "") : "\u83B7\u53D6\u5931\u8D25";
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// src/bot.ts
|
|
32
|
+
var Bot = class _Bot extends InjectLogger {
|
|
33
|
+
ws;
|
|
34
|
+
config;
|
|
35
|
+
events = {
|
|
36
|
+
command: [],
|
|
37
|
+
message: [],
|
|
38
|
+
notice: [],
|
|
39
|
+
request: []
|
|
40
|
+
};
|
|
41
|
+
constructor(config, ws) {
|
|
42
|
+
super({ level: config.debug ? LogLevel.DEBUG : config.logLevel });
|
|
43
|
+
this.ws = ws;
|
|
44
|
+
this.config = config;
|
|
45
|
+
if (config.debug) {
|
|
46
|
+
ws.on("api.preSend", (context) => this.logger.DEBUG("\u53D1\u9001API\u8BF7\u6C42", context));
|
|
47
|
+
ws.on("api.response.success", (context) => this.logger.DEBUG("\u6536\u5230API\u6210\u529F\u54CD\u5E94", context));
|
|
48
|
+
ws.on("api.response.failure", (context) => this.logger.DEBUG("\u6536\u5230API\u5931\u8D25\u54CD\u5E94", context));
|
|
49
|
+
ws.on("message", (context) => this.logger.DEBUG("\u6536\u5230\u6D88\u606F:", context));
|
|
50
|
+
ws.on("request", (context) => this.logger.DEBUG("\u6536\u5230\u8BF7\u6C42:", context));
|
|
51
|
+
ws.on("notice", (context) => this.logger.DEBUG("\u6536\u5230\u901A\u77E5:", context));
|
|
52
|
+
}
|
|
53
|
+
ws.on("message", async (context) => {
|
|
54
|
+
const endpoint = `message.${context.message_type}.${context.sub_type}`;
|
|
55
|
+
const isAdmin = this.config.adminId.includes(context.user_id);
|
|
56
|
+
const isReply = context.message[0].type === "reply";
|
|
57
|
+
for (const event of this.events.message) {
|
|
58
|
+
if (endpoint.includes(event.endPoint ?? "message") && (event.needReply ? isReply : true) && (event.needAdmin ? isAdmin : true) && (event.regexp ? event.regexp.test(context.raw_message) : true)) {
|
|
59
|
+
try {
|
|
60
|
+
const result = await event.callback({ context });
|
|
61
|
+
if (result === "quit") {
|
|
62
|
+
this.logger.DEBUG(`\u63D2\u4EF6 ${event.pluginName} \u8BF7\u6C42\u63D0\u524D\u7EC8\u6B62`);
|
|
63
|
+
break;
|
|
64
|
+
}
|
|
65
|
+
} catch (error) {
|
|
66
|
+
this.logger.ERROR(`\u63D2\u4EF6 ${event.pluginName} \u4E8B\u4EF6\u5904\u7406\u5931\u8D25:`, error);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
for (const event of this.events.command) {
|
|
71
|
+
if (endpoint.includes(event.endPoint ?? "message") && (event.needAdmin ? isAdmin : true) && (event.needReply ? isReply : true)) {
|
|
72
|
+
const [retCode, dataOrMessage] = this.parseCommand(
|
|
73
|
+
context.raw_message,
|
|
74
|
+
event.commandName,
|
|
75
|
+
event.commander
|
|
76
|
+
);
|
|
77
|
+
if (retCode === 1) continue;
|
|
78
|
+
if (retCode === 2) {
|
|
79
|
+
await this.sendMsg(context, [Structs.text(dataOrMessage)]);
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
const { prefix, commandName, params, args } = dataOrMessage;
|
|
83
|
+
try {
|
|
84
|
+
const result = await event.callback({
|
|
85
|
+
context,
|
|
86
|
+
prefix,
|
|
87
|
+
commandName,
|
|
88
|
+
params,
|
|
89
|
+
args
|
|
90
|
+
});
|
|
91
|
+
if (result === "quit") {
|
|
92
|
+
this.logger.DEBUG(`\u63D2\u4EF6 ${event.pluginName} \u8BF7\u6C42\u63D0\u524D\u7EC8\u6B62`);
|
|
93
|
+
break;
|
|
94
|
+
}
|
|
95
|
+
} catch (error) {
|
|
96
|
+
this.logger.ERROR(`\u63D2\u4EF6 ${event.pluginName} \u4E8B\u4EF6\u5904\u7406\u5931\u8D25:`, error);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
ws.on("request", async (context) => {
|
|
102
|
+
const endpoint = `request.${context.request_type}.${"sub_type" in context ? context.sub_type : ""}`;
|
|
103
|
+
for (const event of this.events.request) {
|
|
104
|
+
if (endpoint.includes(event.endPoint ?? "request")) {
|
|
105
|
+
try {
|
|
106
|
+
const result = await event.callback({ context });
|
|
107
|
+
if (result === "quit") {
|
|
108
|
+
this.logger.DEBUG(`\u63D2\u4EF6 ${event.pluginName} \u8BF7\u6C42\u63D0\u524D\u7EC8\u6B62`);
|
|
109
|
+
break;
|
|
110
|
+
}
|
|
111
|
+
} catch (error) {
|
|
112
|
+
this.logger.ERROR(`\u63D2\u4EF6 ${event.pluginName} \u4E8B\u4EF6\u5904\u7406\u5931\u8D25:`, error);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
ws.on("notice", async (context) => {
|
|
118
|
+
let endpoint = `notice.${context.notice_type}.${"sub_type" in context ? context.sub_type : ""}`;
|
|
119
|
+
if (context.notice_type === "notify") {
|
|
120
|
+
if (context.sub_type === "input_status") {
|
|
121
|
+
endpoint += `.${context.group_id !== 0 ? "group" : "friend"}`;
|
|
122
|
+
} else if (context.sub_type === "poke") {
|
|
123
|
+
endpoint += `.${"group_id" in context ? "group" : "friend"}`;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
for (const event of this.events.notice) {
|
|
127
|
+
if (endpoint.includes(event.endPoint ?? "notice")) {
|
|
128
|
+
try {
|
|
129
|
+
const result = await event.callback({ context });
|
|
130
|
+
if (result === "quit") {
|
|
131
|
+
this.logger.DEBUG(`\u63D2\u4EF6 ${event.pluginName} \u8BF7\u6C42\u63D0\u524D\u7EC8\u6B62`);
|
|
132
|
+
break;
|
|
133
|
+
}
|
|
134
|
+
} catch (error) {
|
|
135
|
+
this.logger.ERROR(`\u63D2\u4EF6 ${event.pluginName} \u4E8B\u4EF6\u5904\u7406\u5931\u8D25:`, error);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
this.logger.INFO(`Bot \u521D\u59CB\u5316\u5B8C\u6210`);
|
|
141
|
+
}
|
|
142
|
+
static async init(config) {
|
|
143
|
+
return new Promise((resolve, reject) => {
|
|
144
|
+
const logger = new Logger({
|
|
145
|
+
title: "Bot",
|
|
146
|
+
level: config.debug ? LogLevel.DEBUG : config.logLevel
|
|
147
|
+
});
|
|
148
|
+
const ws = new NCWebsocket({
|
|
149
|
+
...config.connection,
|
|
150
|
+
reconnection: config.reconnection
|
|
151
|
+
});
|
|
152
|
+
let getElapsedTimeMs = performanceCounter();
|
|
153
|
+
ws.on("socket.connecting", (context) => {
|
|
154
|
+
getElapsedTimeMs = performanceCounter();
|
|
155
|
+
logger.INFO(
|
|
156
|
+
`\u8FDE\u63A5\u4E2D [#${context.reconnection.nowAttempts}/${context.reconnection.attempts}]`
|
|
157
|
+
);
|
|
158
|
+
});
|
|
159
|
+
ws.on("socket.error", (context) => {
|
|
160
|
+
logger.ERROR(
|
|
161
|
+
`\u8FDE\u63A5\u5931\u8D25 [#${context.reconnection.nowAttempts}/${context.reconnection.attempts}]`
|
|
162
|
+
);
|
|
163
|
+
logger.ERROR(`\u9519\u8BEF\u4FE1\u606F:`, context);
|
|
164
|
+
if (context.error_type === "response_error") {
|
|
165
|
+
logger.ERROR(`NapCat \u670D\u52A1\u7AEF\u8FD4\u56DE\u9519\u8BEF, \u53EF\u80FD\u662F AccessToken \u9519\u8BEF`);
|
|
166
|
+
process.exit(1);
|
|
167
|
+
}
|
|
168
|
+
if (context.reconnection.nowAttempts >= context.reconnection.attempts) {
|
|
169
|
+
reject(`\u91CD\u8BD5\u6B21\u6570\u8D85\u8FC7\u8BBE\u7F6E\u7684${context.reconnection.attempts}\u6B21!`);
|
|
170
|
+
throw new Error(`\u91CD\u8BD5\u6B21\u6570\u8D85\u8FC7\u8BBE\u7F6E\u7684${context.reconnection.attempts}\u6B21!`);
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
ws.on("socket.open", async (context) => {
|
|
174
|
+
logger.INFO(
|
|
175
|
+
`\u8FDE\u63A5\u6210\u529F [#${context.reconnection.nowAttempts}/${context.reconnection.attempts}]`
|
|
176
|
+
);
|
|
177
|
+
logger.INFO(`\u8FDE\u63A5 NapCat \u8017\u65F6: ${getElapsedTimeMs()}ms`);
|
|
178
|
+
resolve(new _Bot(config, ws));
|
|
179
|
+
});
|
|
180
|
+
ws.connect();
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* 注册事件
|
|
185
|
+
*/
|
|
186
|
+
regEvent(_options) {
|
|
187
|
+
const options = { ..._options, priority: _options.priority ?? 1 };
|
|
188
|
+
switch (options.type) {
|
|
189
|
+
case "command":
|
|
190
|
+
this.events.command = sortObjectArray([...this.events.command, options], "priority", "down");
|
|
191
|
+
return () => {
|
|
192
|
+
const index = this.events.command.indexOf(options);
|
|
193
|
+
if (index !== -1) this.events.command.splice(index, 1);
|
|
194
|
+
};
|
|
195
|
+
case "message":
|
|
196
|
+
this.events.message = sortObjectArray([...this.events.message, options], "priority", "down");
|
|
197
|
+
return () => {
|
|
198
|
+
const index = this.events.message.indexOf(options);
|
|
199
|
+
if (index !== -1) this.events.message.splice(index, 1);
|
|
200
|
+
};
|
|
201
|
+
case "notice":
|
|
202
|
+
this.events.notice = sortObjectArray([...this.events.notice, options], "priority", "down");
|
|
203
|
+
return () => {
|
|
204
|
+
const index = this.events.notice.indexOf(options);
|
|
205
|
+
if (index !== -1) this.events.notice.splice(index, 1);
|
|
206
|
+
};
|
|
207
|
+
case "request":
|
|
208
|
+
this.events.request = sortObjectArray([...this.events.request, options], "priority", "down");
|
|
209
|
+
return () => {
|
|
210
|
+
const index = this.events.request.indexOf(options);
|
|
211
|
+
if (index !== -1) this.events.request.splice(index, 1);
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* 解析命令
|
|
217
|
+
* @param rawMessage 原始消息
|
|
218
|
+
* @param commandName 命令名称
|
|
219
|
+
* @param command 命令对象
|
|
220
|
+
* @returns 解析结果
|
|
221
|
+
*/
|
|
222
|
+
parseCommand(rawMessage, commandName, command) {
|
|
223
|
+
const firstChar = rawMessage.charAt(0);
|
|
224
|
+
const prefix = this.config.prefix.find((p) => p === firstChar);
|
|
225
|
+
if (!prefix) return [1, "\u672A\u5339\u914D\u5230\u524D\u7F00"];
|
|
226
|
+
const parts = rawMessage.split(" ");
|
|
227
|
+
if (parts.length === 0) return [1, "\u547D\u4EE4\u4FE1\u606F\u672A\u7A7A"];
|
|
228
|
+
const cmdName = parts[0].slice(prefix.length);
|
|
229
|
+
const args = parts.slice(1).filter((arg) => arg !== "");
|
|
230
|
+
if (commandName !== "*" && (typeof commandName === "string" && commandName !== cmdName || commandName instanceof RegExp && cmdName.match(commandName) === null)) {
|
|
231
|
+
return [1, "\u547D\u4EE4\u540D\u4E0D\u5339\u914D"];
|
|
232
|
+
}
|
|
233
|
+
if (command) {
|
|
234
|
+
try {
|
|
235
|
+
const parsedCommand = command.configureOutput({ writeErr: () => {
|
|
236
|
+
}, writeOut: () => {
|
|
237
|
+
} }).exitOverride().parse(args, { from: "user" });
|
|
238
|
+
return [
|
|
239
|
+
0,
|
|
240
|
+
{
|
|
241
|
+
prefix,
|
|
242
|
+
commandName: cmdName,
|
|
243
|
+
params: parsedCommand.opts(),
|
|
244
|
+
args: parsedCommand.processedArgs
|
|
245
|
+
}
|
|
246
|
+
];
|
|
247
|
+
} catch (error) {
|
|
248
|
+
if (error instanceof CommanderError) {
|
|
249
|
+
if (error.code === "commander.helpDisplayed") {
|
|
250
|
+
const helpInformation = this.getCommandHelpInformation(commandName.toString());
|
|
251
|
+
return [2, helpInformation ?? ""];
|
|
252
|
+
}
|
|
253
|
+
error.message = error.message.replace("error:", "\u9519\u8BEF:").replace("unknown option", "\u672A\u77E5\u9009\u9879").replace("missing required argument", "\u7F3A\u5C11\u5FC5\u8981\u53C2\u6570").replace("too many arguments", "\u53C2\u6570\u8FC7\u591A").replace("invalid argument", "\u65E0\u6548\u53C2\u6570").replace("option '", "\u9009\u9879 '").replace("argument missing", "\u7F3A\u5C11\u53C2\u6570").replace("Did you mean", "\u4F60\u662F\u60F3\u8981");
|
|
254
|
+
return [
|
|
255
|
+
2,
|
|
256
|
+
error.message + (error.message.includes("\u4F60\u662F\u60F3\u8981") ? "" : "\n(\u4F7F\u7528 -h \u83B7\u53D6\u5E2E\u52A9\u4FE1\u606F)")
|
|
257
|
+
];
|
|
258
|
+
} else {
|
|
259
|
+
this.logger.ERROR(error);
|
|
260
|
+
return [2, error instanceof Error ? error.message : "\u672A\u77E5\u9519\u8BEF"];
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
return [
|
|
265
|
+
0,
|
|
266
|
+
{
|
|
267
|
+
prefix,
|
|
268
|
+
commandName: cmdName,
|
|
269
|
+
params: {},
|
|
270
|
+
args: []
|
|
271
|
+
}
|
|
272
|
+
];
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* 获取命令信息
|
|
276
|
+
* @param command 命令对象
|
|
277
|
+
* @param fallback 后备值
|
|
278
|
+
* @param field 字段名
|
|
279
|
+
* @returns 命令信息
|
|
280
|
+
*/
|
|
281
|
+
getCommandInfo(command, fallback, field = "name") {
|
|
282
|
+
const commandInfo = command[field]().replace("/", "");
|
|
283
|
+
return commandInfo === "" || commandInfo === "program" ? fallback : commandInfo;
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* 获取命令帮助信息
|
|
287
|
+
* @param commandName 命令名称
|
|
288
|
+
*/
|
|
289
|
+
getCommandHelpInformation(commandName) {
|
|
290
|
+
const foundEvent = this.events.command.find((cmd) => cmd.commandName.toString() === commandName);
|
|
291
|
+
if (!foundEvent || !foundEvent.commander) return void 0;
|
|
292
|
+
const resolvedCommandName = this.getCommandInfo(
|
|
293
|
+
foundEvent.commander,
|
|
294
|
+
foundEvent.commandName.toString()
|
|
295
|
+
);
|
|
296
|
+
const defaultPrefix = this.config.prefix[0];
|
|
297
|
+
const helpInformation = foundEvent.commander.name(
|
|
298
|
+
resolvedCommandName.includes(defaultPrefix) ? resolvedCommandName : `${defaultPrefix}${resolvedCommandName}`
|
|
299
|
+
).helpOption("-h, --help", "\u5C55\u793A\u5E2E\u52A9\u4FE1\u606F").helpInformation().replace("default:", "\u9ED8\u8BA4\u503C:").replace("Arguments:", "\u53C2\u6570:").replace("Options:", "\u9009\u9879:").replace("Usage:", "\u7528\u6CD5:");
|
|
300
|
+
return helpInformation;
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* 发送普通消息
|
|
304
|
+
*/
|
|
305
|
+
async sendMsg(context, message, { reply = true, at = true } = {}) {
|
|
306
|
+
try {
|
|
307
|
+
if (context.message_type === "private") {
|
|
308
|
+
return await this.ws.send_private_msg({ user_id: context.user_id, message });
|
|
309
|
+
} else {
|
|
310
|
+
const prefix = [];
|
|
311
|
+
if (reply && context.message_id) prefix.push(Structs.reply(context.message_id));
|
|
312
|
+
if (at && context.user_id) prefix.push(Structs.at(context.user_id), Structs.text("\n"));
|
|
313
|
+
message = [...prefix, ...message];
|
|
314
|
+
return await this.ws.send_group_msg({ group_id: context.group_id, message });
|
|
315
|
+
}
|
|
316
|
+
} catch {
|
|
317
|
+
return null;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
321
|
+
* 发送合并转发
|
|
322
|
+
*/
|
|
323
|
+
async sendForwardMsg(context, message) {
|
|
324
|
+
try {
|
|
325
|
+
if (context.message_type === "private") {
|
|
326
|
+
return await this.ws.send_private_forward_msg({
|
|
327
|
+
user_id: context.user_id,
|
|
328
|
+
message
|
|
329
|
+
});
|
|
330
|
+
} else {
|
|
331
|
+
return await this.ws.send_group_forward_msg({
|
|
332
|
+
group_id: context.group_id,
|
|
333
|
+
message
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
} catch {
|
|
337
|
+
return null;
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* 判断是否是机器人的好友
|
|
342
|
+
*/
|
|
343
|
+
async isFriend(context) {
|
|
344
|
+
return this.ws.get_friend_list().then((res) => res.find((value) => value.user_id === context.user_id));
|
|
345
|
+
}
|
|
346
|
+
/**
|
|
347
|
+
* 获取用户名
|
|
348
|
+
*/
|
|
349
|
+
async getUsername(context) {
|
|
350
|
+
if ("group_id" in context) {
|
|
351
|
+
return this.ws.get_group_member_info({ group_id: context.group_id, user_id: context.user_id }).then((res) => res.nickname);
|
|
352
|
+
} else {
|
|
353
|
+
return this.ws.get_stranger_info({ user_id: context.user_id }).then((res) => res.nickname);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
};
|
|
357
|
+
|
|
358
|
+
// src/atri.ts
|
|
359
|
+
var ATRI = class _ATRI extends InjectLogger2 {
|
|
360
|
+
config;
|
|
361
|
+
configDir;
|
|
362
|
+
bot;
|
|
363
|
+
loadedPlugins = {};
|
|
364
|
+
loadPluginHooks = {};
|
|
365
|
+
constructor(config, bot) {
|
|
366
|
+
super({ level: config.debug ? LogLevel2.DEBUG : config.logLevel });
|
|
367
|
+
this.config = config;
|
|
368
|
+
this.bot = bot;
|
|
369
|
+
this.configDir = config.configDir ?? path.join(config.baseDir, "config");
|
|
370
|
+
this.logger.INFO(`ATRI \u521D\u59CB\u5316\u5B8C\u6210`);
|
|
371
|
+
}
|
|
372
|
+
static async init(config) {
|
|
373
|
+
if (config.debug) config.logLevel = LogLevel2.DEBUG;
|
|
374
|
+
const logger = new Logger2({
|
|
375
|
+
title: "ATRI",
|
|
376
|
+
level: config.debug ? LogLevel2.DEBUG : config.logLevel
|
|
377
|
+
});
|
|
378
|
+
if (!config.disableClearTerminal) console.log("\x1Bc");
|
|
379
|
+
if (!config.disableStartupMessage) {
|
|
380
|
+
console.log(
|
|
381
|
+
`%c __ .__
|
|
382
|
+
_____ _/ |_ _______ |__|
|
|
383
|
+
\\__ \\ \\ __\\ \\_ __ \\ | |
|
|
384
|
+
/ __ \\_ | | | | \\/ | |
|
|
385
|
+
(____ / |__| |__| |__|
|
|
386
|
+
\\/`,
|
|
387
|
+
`font-family: Consolas;`
|
|
388
|
+
);
|
|
389
|
+
logger.INFO(`\u30A2\u30C8\u30EA\u306F\u3001\u9AD8\u6027\u80FD\u3067\u3059\u304B\u3089\uFF01`);
|
|
390
|
+
}
|
|
391
|
+
if (!("debug" in config.bot)) config.bot.debug = config.debug;
|
|
392
|
+
if (!("logLevel" in config.bot)) config.bot.logLevel = config.logLevel;
|
|
393
|
+
const bot = await Bot.init(config.bot);
|
|
394
|
+
const atri = new _ATRI(config, bot);
|
|
395
|
+
return atri;
|
|
396
|
+
}
|
|
397
|
+
async loadPlugin(importFunction) {
|
|
398
|
+
const pluginName = getImportItemName(importFunction);
|
|
399
|
+
if (pluginName === "\u83B7\u53D6\u5931\u8D25") {
|
|
400
|
+
this.logger.ERROR(`\u65E0\u6CD5\u4ECE import \u51FD\u6570\u4E2D\u83B7\u53D6\u63D2\u4EF6\u540D\u79F0\u3002\u8BF7\u786E\u4FDD\u4F20\u5165\u7684\u51FD\u6570\u662F\u4E00\u4E2A import \u8BED\u53E5\u3002`);
|
|
401
|
+
return false;
|
|
402
|
+
}
|
|
403
|
+
this.logger.INFO(`\u52A0\u8F7D\u63D2\u4EF6: ${pluginName}`);
|
|
404
|
+
let module;
|
|
405
|
+
try {
|
|
406
|
+
module = await importFunction();
|
|
407
|
+
} catch (error) {
|
|
408
|
+
this.logger.ERROR(`\u63D2\u4EF6 ${pluginName} \u52A0\u8F7D\u5931\u8D25:`, error);
|
|
409
|
+
return false;
|
|
410
|
+
}
|
|
411
|
+
if (!module.Plugin) {
|
|
412
|
+
this.logger.ERROR(`\u63D2\u4EF6 ${pluginName} \u52A0\u8F7D\u5931\u8D25: \u672A\u627E\u5230 Plugin \u7C7B`);
|
|
413
|
+
return false;
|
|
414
|
+
}
|
|
415
|
+
try {
|
|
416
|
+
const plugin = new module.Plugin(this);
|
|
417
|
+
if (!plugin.pluginName) {
|
|
418
|
+
this.logger.ERROR(`\u63D2\u4EF6 ${pluginName} \u52A0\u8F7D\u5931\u8D25: \u7F3A\u5C11\u5FC5\u8981\u53C2\u6570: pluginName`);
|
|
419
|
+
return false;
|
|
420
|
+
}
|
|
421
|
+
for (const hookName in this.loadPluginHooks) {
|
|
422
|
+
const hook = this.loadPluginHooks[hookName];
|
|
423
|
+
const result = await hook(plugin);
|
|
424
|
+
if (!result) {
|
|
425
|
+
this.logger.ERROR(`\u63D2\u4EF6 ${plugin.pluginName} \u52A0\u8F7D\u5931\u8D25: \u52A0\u8F7D\u94A9\u5B50 ${hookName} \u8FD4\u56DE false`);
|
|
426
|
+
return false;
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
if (!plugin.getDisableAutoLoadConfig()) {
|
|
430
|
+
const config = await this.loadConfig(plugin.getConfigName(), plugin.getDefaultConfig());
|
|
431
|
+
plugin.setConfig(config);
|
|
432
|
+
}
|
|
433
|
+
await plugin.load();
|
|
434
|
+
this.loadedPlugins[plugin.pluginName] = plugin;
|
|
435
|
+
this.logger.INFO(`\u63D2\u4EF6 ${plugin.pluginName} \u52A0\u8F7D\u6210\u529F`);
|
|
436
|
+
} catch (error) {
|
|
437
|
+
this.logger.ERROR(`\u63D2\u4EF6 ${pluginName} \u52A0\u8F7D\u5931\u8D25:`, error);
|
|
438
|
+
return false;
|
|
439
|
+
}
|
|
440
|
+
return true;
|
|
441
|
+
}
|
|
442
|
+
async unloadPlugin(pluginName) {
|
|
443
|
+
if (!this.loadedPlugins[pluginName]) {
|
|
444
|
+
this.logger.WARN(`\u63D2\u4EF6 ${pluginName} \u672A\u52A0\u8F7D`);
|
|
445
|
+
return true;
|
|
446
|
+
}
|
|
447
|
+
const plugin = this.loadedPlugins[pluginName];
|
|
448
|
+
try {
|
|
449
|
+
plugin.getUnregHandlers().forEach((unreg) => unreg());
|
|
450
|
+
await plugin.unload();
|
|
451
|
+
delete this.loadedPlugins[pluginName];
|
|
452
|
+
this.logger.INFO(`\u63D2\u4EF6 ${pluginName} \u5378\u8F7D\u6210\u529F`);
|
|
453
|
+
} catch (error) {
|
|
454
|
+
this.logger.ERROR(`\u63D2\u4EF6 ${pluginName} \u5378\u8F7D\u5931\u8D25:`, error);
|
|
455
|
+
return false;
|
|
456
|
+
}
|
|
457
|
+
return true;
|
|
458
|
+
}
|
|
459
|
+
async loadConfig(pluginName, defaultConfig) {
|
|
460
|
+
if (!fs.existsSync(this.configDir)) fs.mkdirSync(this.configDir, { recursive: true });
|
|
461
|
+
const configPath = path.join(this.configDir, `${pluginName}.json`);
|
|
462
|
+
if (!fs.existsSync(configPath)) {
|
|
463
|
+
fs.writeFileSync(configPath, JSON.stringify(defaultConfig, null, 2));
|
|
464
|
+
return defaultConfig;
|
|
465
|
+
}
|
|
466
|
+
try {
|
|
467
|
+
const currentJson = JSON.parse(fs.readFileSync(configPath, "utf-8"));
|
|
468
|
+
return { ...defaultConfig, ...currentJson };
|
|
469
|
+
} catch (error) {
|
|
470
|
+
this.logger.ERROR(`\u63D2\u4EF6 ${pluginName} \u914D\u7F6E\u52A0\u8F7D\u5931\u8D25:`, error);
|
|
471
|
+
return {};
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
async saveConfig(pluginName, config) {
|
|
475
|
+
if (!fs.existsSync(this.configDir)) fs.mkdirSync(this.configDir, { recursive: true });
|
|
476
|
+
const configPath = path.join(this.configDir, `${pluginName}.json`);
|
|
477
|
+
fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
|
|
478
|
+
}
|
|
479
|
+
addPluginLoadHook(hookName, hook) {
|
|
480
|
+
this.loadPluginHooks[hookName] = hook;
|
|
481
|
+
}
|
|
482
|
+
removePluginLoadHook(hookName) {
|
|
483
|
+
delete this.loadPluginHooks[hookName];
|
|
484
|
+
}
|
|
485
|
+
};
|
|
486
|
+
|
|
487
|
+
// src/types/plugin.ts
|
|
488
|
+
import { Logger as Logger3, LogLevel as LogLevel3 } from "@huan_kong/logger";
|
|
489
|
+
var BasePlugin = class {
|
|
490
|
+
disableAutoLoadConfig;
|
|
491
|
+
configName;
|
|
492
|
+
defaultConfig;
|
|
493
|
+
config;
|
|
494
|
+
atri;
|
|
495
|
+
bot;
|
|
496
|
+
ws;
|
|
497
|
+
unregHandlers = [];
|
|
498
|
+
// 构造完成后通过 initLogger 初始化
|
|
499
|
+
logger;
|
|
500
|
+
constructor(atri) {
|
|
501
|
+
this.atri = atri;
|
|
502
|
+
this.bot = atri.bot;
|
|
503
|
+
this.ws = atri.bot.ws;
|
|
504
|
+
this.config = {};
|
|
505
|
+
}
|
|
506
|
+
initLogger() {
|
|
507
|
+
const config = this.atri.config;
|
|
508
|
+
this.logger = new Logger3({
|
|
509
|
+
title: this.pluginName,
|
|
510
|
+
level: config.debug ? LogLevel3.DEBUG : config.logLevel
|
|
511
|
+
});
|
|
512
|
+
}
|
|
513
|
+
setConfig(config) {
|
|
514
|
+
this.config = config;
|
|
515
|
+
}
|
|
516
|
+
saveConfig(config) {
|
|
517
|
+
this.atri.saveConfig(this.configName ?? this.pluginName, config ?? this.config);
|
|
518
|
+
}
|
|
519
|
+
getDisableAutoLoadConfig() {
|
|
520
|
+
return this.disableAutoLoadConfig;
|
|
521
|
+
}
|
|
522
|
+
getConfigName() {
|
|
523
|
+
return this.configName ?? this.pluginName;
|
|
524
|
+
}
|
|
525
|
+
getDefaultConfig() {
|
|
526
|
+
return this.defaultConfig ?? {};
|
|
527
|
+
}
|
|
528
|
+
getUnregHandlers() {
|
|
529
|
+
return this.unregHandlers;
|
|
530
|
+
}
|
|
531
|
+
getPluginName() {
|
|
532
|
+
return this.pluginName;
|
|
533
|
+
}
|
|
534
|
+
reg_command_event(options) {
|
|
535
|
+
const unreg = this.bot.regEvent({
|
|
536
|
+
...options,
|
|
537
|
+
type: "command",
|
|
538
|
+
pluginName: this.pluginName
|
|
539
|
+
});
|
|
540
|
+
this.unregHandlers.push(unreg);
|
|
541
|
+
return unreg;
|
|
542
|
+
}
|
|
543
|
+
reg_message_event(options) {
|
|
544
|
+
const unreg = this.bot.regEvent({
|
|
545
|
+
...options,
|
|
546
|
+
type: "message",
|
|
547
|
+
pluginName: this.pluginName
|
|
548
|
+
});
|
|
549
|
+
this.unregHandlers.push(unreg);
|
|
550
|
+
return unreg;
|
|
551
|
+
}
|
|
552
|
+
reg_request_event(options) {
|
|
553
|
+
const unreg = this.bot.regEvent({
|
|
554
|
+
...options,
|
|
555
|
+
type: "request",
|
|
556
|
+
pluginName: this.pluginName
|
|
557
|
+
});
|
|
558
|
+
this.unregHandlers.push(unreg);
|
|
559
|
+
return unreg;
|
|
560
|
+
}
|
|
561
|
+
reg_notice_event(options) {
|
|
562
|
+
const unreg = this.bot.regEvent({
|
|
563
|
+
...options,
|
|
564
|
+
type: "notice",
|
|
565
|
+
pluginName: this.pluginName
|
|
566
|
+
});
|
|
567
|
+
this.unregHandlers.push(unreg);
|
|
568
|
+
return unreg;
|
|
569
|
+
}
|
|
570
|
+
};
|
|
571
|
+
export {
|
|
572
|
+
ATRI,
|
|
573
|
+
BasePlugin,
|
|
574
|
+
Bot,
|
|
575
|
+
getImportItemName,
|
|
576
|
+
performanceCounter,
|
|
577
|
+
sortObjectArray
|
|
578
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@atri-bot/core",
|
|
3
|
+
"version": "1.1.0",
|
|
4
|
+
"description": "QQBOT TypeScript framework",
|
|
5
|
+
"author": "huankong233",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"main": "./dist/index.js",
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"files": [
|
|
11
|
+
"./dist/**/*"
|
|
12
|
+
],
|
|
13
|
+
"repository": {
|
|
14
|
+
"type": "git",
|
|
15
|
+
"url": "git+https://github.com/HkTeamX/ATRI.git"
|
|
16
|
+
},
|
|
17
|
+
"scripts": {
|
|
18
|
+
"build": "tsup",
|
|
19
|
+
"clean": "rimraf dist",
|
|
20
|
+
"lint": "eslint",
|
|
21
|
+
"lint:fix": "eslint --fix",
|
|
22
|
+
"type-check": "tsc --noEmit -p tsconfig.json --composite false"
|
|
23
|
+
},
|
|
24
|
+
"dependencies": {
|
|
25
|
+
"@huan_kong/logger": "^1.0.6",
|
|
26
|
+
"commander": "^14.0.0",
|
|
27
|
+
"compare-versions": "^6.1.1",
|
|
28
|
+
"node-napcat-ts": "^0.4.19",
|
|
29
|
+
"picocolors": "^1.1.1"
|
|
30
|
+
}
|
|
31
|
+
}
|