@atri-bot/core 1.1.30 → 2.0.0-beta.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.
@@ -0,0 +1,204 @@
1
+ import { LogLevelType, Logger } from "@huan_kong/logger";
2
+ import { MessageHandler, NCWebsocket, NCWebsocketOptions, NodeSegment, NoticeHandler, RequestHandler, SendMessageSegment } from "node-napcat-ts";
3
+ import { Argv } from "yargs";
4
+
5
+ //#region src/utils.d.ts
6
+ type NonEmptyArray<T> = [T, ...T[]];
7
+ type MaybePromise<T> = T | Promise<T>;
8
+ /**
9
+ * 排序对象数组
10
+ * @param arr 对象数组
11
+ * @param property 属性名
12
+ * @param sortType up=>升序 down=>降序
13
+ */
14
+ declare function sortObjectArray<T extends object>(arr: T[], property: keyof T, sortType?: 'up' | 'down'): T[];
15
+ //#endregion
16
+ //#region src/bot.d.ts
17
+ type BotConfig = NCWebsocketOptions & {
18
+ logLevel?: LogLevelType;
19
+ prefix: NonEmptyArray<string>;
20
+ adminId: NonEmptyArray<number>;
21
+ yargsLocale?: string;
22
+ };
23
+ interface CommandContext<T extends keyof MessageHandler, K extends Argv> {
24
+ context: MessageHandler[T];
25
+ options: ReturnType<K['parseSync']>;
26
+ }
27
+ interface CommandEvent<T extends keyof MessageHandler = keyof MessageHandler, K extends Argv = Argv> {
28
+ type: 'command';
29
+ endPoint?: T;
30
+ trigger: string | RegExp;
31
+ priority?: number;
32
+ needReply?: boolean;
33
+ needAdmin?: boolean;
34
+ hideInHelp?: boolean;
35
+ pluginName: string;
36
+ commander?: () => K;
37
+ callback: (context: CommandContext<T, K>) => MaybePromise<void | 'quit'>;
38
+ }
39
+ interface MessageEvent<T extends keyof MessageHandler = keyof MessageHandler> {
40
+ type: 'message';
41
+ endPoint?: T;
42
+ trigger?: string | RegExp;
43
+ priority?: number;
44
+ needReply?: boolean;
45
+ needAdmin?: boolean;
46
+ pluginName: string;
47
+ callback: (context: MessageHandler[T]) => MaybePromise<void | 'quit'>;
48
+ }
49
+ interface NoticeEvent<T extends keyof NoticeHandler = keyof NoticeHandler> {
50
+ type: 'notice';
51
+ endPoint?: T;
52
+ priority?: number;
53
+ pluginName: string;
54
+ callback: (context: NoticeHandler[T]) => MaybePromise<void | 'quit'>;
55
+ }
56
+ interface RequestEvent<T extends keyof RequestHandler = keyof RequestHandler> {
57
+ type: 'request';
58
+ endPoint?: T;
59
+ priority?: number;
60
+ pluginName: string;
61
+ callback: (context: RequestHandler[T]) => MaybePromise<void | 'quit'>;
62
+ }
63
+ type RegEventOptions = CommandEvent | MessageEvent | NoticeEvent | RequestEvent;
64
+ interface BotEvents {
65
+ command: CommandEvent[];
66
+ message: MessageEvent[];
67
+ notice: NoticeEvent[];
68
+ request: RequestEvent[];
69
+ }
70
+ declare class Bot {
71
+ atri: ATRI;
72
+ config: BotConfig;
73
+ logger: Logger;
74
+ ws: NCWebsocket;
75
+ events: BotEvents;
76
+ unloaders: {
77
+ [key: string]: (() => void)[];
78
+ };
79
+ constructor(atri: ATRI, config: BotConfig);
80
+ init(): Promise<void>;
81
+ splitArgsRegex: RegExp;
82
+ splitArgs(str: string): string[];
83
+ private extractCommandBody;
84
+ regCommandEvent<T extends keyof MessageHandler, K extends Argv>(_event: Omit<CommandEvent<T, K>, 'type'>): () => void;
85
+ regMessageEvent<T extends keyof MessageHandler>(_event: Omit<MessageEvent<T>, 'type'>): () => void;
86
+ regNoticeEvent<T extends keyof NoticeHandler>(_event: Omit<NoticeEvent<T>, 'type'>): () => void;
87
+ regRequestEvent<T extends keyof RequestHandler>(_event: Omit<RequestEvent<T>, 'type'>): () => void;
88
+ /**
89
+ * 发送普通消息
90
+ */
91
+ sendMsg(context: {
92
+ message_type: 'private';
93
+ user_id: number;
94
+ message_id?: number;
95
+ } | {
96
+ message_type: 'group';
97
+ group_id: number;
98
+ user_id?: number;
99
+ message_id?: number;
100
+ }, message: SendMessageSegment[], {
101
+ reply,
102
+ at
103
+ }?: {
104
+ reply?: boolean | undefined;
105
+ at?: boolean | undefined;
106
+ }): Promise<{
107
+ message_id: number;
108
+ } | null>;
109
+ /**
110
+ * 发送合并转发
111
+ */
112
+ sendForwardMsg(context: {
113
+ message_type: 'group';
114
+ group_id: number;
115
+ } | {
116
+ message_type: 'private';
117
+ user_id: number;
118
+ }, message: NodeSegment[]): Promise<{
119
+ message_id: number;
120
+ } | null>;
121
+ /**
122
+ * 判断是否是机器人的好友
123
+ */
124
+ isFriend(context: {
125
+ user_id: number;
126
+ }): Promise<{
127
+ birthday_year: number;
128
+ birthday_month: number;
129
+ birthday_day: number;
130
+ user_id: number;
131
+ age: number;
132
+ phone_num: string;
133
+ email: string;
134
+ category_id: number;
135
+ nickname: string;
136
+ remark: string;
137
+ sex: "male" | "female" | "unknown";
138
+ level: number;
139
+ } | undefined>;
140
+ /**
141
+ * 获取用户名
142
+ */
143
+ getUsername(context: {
144
+ user_id: number;
145
+ } | {
146
+ user_id: number;
147
+ group_id: number;
148
+ }): Promise<string>;
149
+ }
150
+ //#endregion
151
+ //#region src/plugin.d.ts
152
+ interface Plugin<T extends object = object> extends PluginOptions<T> {
153
+ atri: ATRI;
154
+ bot: ATRI['bot'];
155
+ ws: ATRI['bot']['ws'];
156
+ config: T;
157
+ logger: Logger;
158
+ refreshConfig: () => Promise<void>;
159
+ saveConfig: (config?: T) => Promise<void>;
160
+ regMessageEvent: <K extends keyof MessageHandler>(this: Plugin<T>, event: Omit<MessageEvent<K>, 'type' | 'pluginName'>) => void;
161
+ regCommandEvent: <K extends keyof MessageHandler, U extends Argv>(this: Plugin<T>, event: Omit<CommandEvent<K, U>, 'type' | 'pluginName'>) => void;
162
+ regNoticeEvent: <K extends keyof NoticeHandler>(this: Plugin<T>, event: Omit<NoticeEvent<K>, 'type' | 'pluginName'>) => void;
163
+ regRequestEvent: <K extends keyof RequestHandler>(this: Plugin<T>, event: Omit<RequestEvent<K>, 'type' | 'pluginName'>) => void;
164
+ }
165
+ interface PluginOptions<T extends object = object> {
166
+ defaultConfig?: T;
167
+ pluginName: string;
168
+ install: (this: Plugin<T>) => MaybePromise<void>;
169
+ uninstall: (this: Plugin<T>) => MaybePromise<void>;
170
+ }
171
+ type definePluginReturnType<T extends object> = (atri: ATRI) => Promise<Plugin<T>>;
172
+ declare function definePlugin<T extends object>(_pluginOptions: PluginOptions<T> | (() => MaybePromise<PluginOptions<T>>)): definePluginReturnType<T>;
173
+ //#endregion
174
+ //#region src/atri.d.ts
175
+ interface ATRIConfig {
176
+ logLevel?: LogLevelType;
177
+ botConfig: BotConfig;
178
+ configDir: string;
179
+ logDir: string;
180
+ saveLogs: boolean;
181
+ maxFiles?: number;
182
+ plugins?: definePluginReturnType<any>[];
183
+ }
184
+ declare class ATRI {
185
+ config: ATRIConfig;
186
+ logger: Logger;
187
+ bot: Bot;
188
+ plugins: {
189
+ [key: string]: Plugin<any>;
190
+ };
191
+ configs: {
192
+ [key: string]: any;
193
+ };
194
+ private normalizeConfigKey;
195
+ private removeUselessLogs;
196
+ constructor(config: ATRIConfig);
197
+ init(): Promise<void>;
198
+ installPlugin<T extends object>(plugin: definePluginReturnType<T>): Promise<void>;
199
+ uninstallPlugin(pluginName: string): Promise<void>;
200
+ loadConfig<T extends object>(pluginName: string, defaultConfig?: T, refresh?: boolean): Promise<T>;
201
+ saveConfig<T extends object>(pluginName: string, config: T): Promise<void>;
202
+ }
203
+ //#endregion
204
+ export { ATRI, ATRIConfig, Bot, BotConfig, BotEvents, CommandContext, CommandEvent, MaybePromise, MessageEvent, NonEmptyArray, NoticeEvent, Plugin, PluginOptions, RegEventOptions, RequestEvent, definePlugin, definePluginReturnType, sortObjectArray };
package/dist/index.mjs ADDED
@@ -0,0 +1,7 @@
1
+ import e from"node:path";import{LogLevel as t,Logger as n,defaultTransformer as r,saveFileTransformer as i}from"@huan_kong/logger";import a from"fs-extra";import o from"node:process";import{NCWebsocket as s,Structs as c}from"node-napcat-ts";function l(e,t,n=`up`){return e.sort((e,r)=>e[t]>r[t]?n===`up`?1:-1:e[t]<r[t]?n===`up`?-1:1:0)}var u=class{atri;config;logger;ws;events={command:[],message:[],notice:[],request:[]};unloaders={};constructor(e,t){this.atri=e,this.config=t,this.logger=this.atri.logger.clone({title:`Bot`,...t.logLevel?{level:t.logLevel}:{}}),this.ws=new s(t)}async init(){this.ws.on(`socket.connecting`,e=>this.logger.INFO(`连接中 [#${e.reconnection.nowAttempts}/${e.reconnection.attempts}]`)),this.ws.on(`socket.open`,e=>this.logger.INFO(`连接成功 [#${e.reconnection.nowAttempts}/${e.reconnection.attempts}]`)),this.ws.on(`socket.error`,e=>{e.error_type===`connect_error`?(this.logger.ERROR(`连接失败 [#${e.reconnection.nowAttempts}/${e.reconnection.attempts}]`),this.logger.ERROR(`错误信息:`,e)):e.error_type===`response_error`&&(this.logger.ERROR(`NapCat 服务端返回错误 [#${e.reconnection.nowAttempts}/${e.reconnection.attempts}]`),this.logger.ERROR(`错误信息:`,e.info),o.exit(1)),e.reconnection.nowAttempts>=e.reconnection.attempts&&(this.logger.ERROR(`重试次数超过设置的${e.reconnection.attempts}次!`),o.exit(1))}),this.ws.on(`api.preSend`,e=>this.logger.DEBUG(`发送API请求`,e)),this.ws.on(`api.response.success`,e=>this.logger.DEBUG(`收到API成功响应`,e)),this.ws.on(`api.response.failure`,e=>this.logger.DEBUG(`收到API失败响应`,e)),this.ws.on(`message`,async e=>{if(e.message.length===0){this.logger.DEBUG(`收到空消息, 已跳过处理流程:`,e);return}let n=`message.${e.message_type}.${e.sub_type}`,r=this.config.adminId.includes(e.user_id),i=e.message[0].type===`reply`;if(this.logger.DEBUG(`收到消息:`,e),this.config.logLevel===t.DEBUG&&!r){this.logger.DEBUG(`当前处于调试模式, 非管理员消息, 已跳过处理流程:`,e);return}for(let t of this.events.message)if(!(!n.includes(t.endPoint??`message`)||t.needReply&&!i||t.needAdmin&&!r||t.trigger&&!(typeof t.trigger==`string`?e.raw_message.includes(t.trigger):t.trigger.test(e.raw_message))))try{if(await t.callback(e)===`quit`){this.logger.DEBUG(`插件 ${t.pluginName} 请求提前终止 ${n} 事件`);break}}catch(r){this.logger.ERROR(`插件 ${t.pluginName} ${n} 事件处理失败:`,r),await this.sendMsg(e,[c.text(`插件 ${t.pluginName} ${n} 事件处理失败, 请联系管理员处理: ${r instanceof Error?r.stack??r.message:String(r)}`)])}let a=this.config.prefix.find(t=>e.raw_message.startsWith(t));if(!a)return;let o=e.raw_message.slice(a.length).trim();for(let t of this.events.command){if(!n.includes(t.endPoint??`message`)||t.needReply&&!i||t.needAdmin&&!r)continue;let a=this.extractCommandBody(o,t.trigger);if(a!==null)try{let r=this.splitArgs(a),i=t.commander?t.commander().fail(!1).parseSync(r):{_:[],$0:``};if(await t.callback({context:e,options:i})===`quit`){this.logger.DEBUG(`插件 ${t.pluginName} 请求提前终止 ${n} 事件`);break}}catch(r){if(r instanceof Error&&r.stack?.toString().includes(`yargs`)){await this.sendMsg(e,[c.text(`命令使用错误: ${r.message}\n\n`),c.text(await t.commander?.()?.getHelp()??`无帮助信息`)]);continue}this.logger.ERROR(`插件 ${t.pluginName} ${n} 事件处理失败:`,r),await this.sendMsg(e,[c.text(`插件 ${t.pluginName} ${n} 事件处理失败, 请联系管理员处理: ${r instanceof Error?r.stack??r.message:String(r)}`)])}}}),this.ws.on(`request`,async e=>{this.logger.DEBUG(`收到请求:`,e);let t=`request.${e.request_type}.${`sub_type`in e?e.sub_type:``}`;for(let n of this.events.request)if(t.includes(n.endPoint??`request`))try{if(await n.callback(e)===`quit`){this.logger.DEBUG(`插件 ${n.pluginName} 请求提前终止 ${t} 事件`);break}}catch(e){this.logger.ERROR(`插件 ${n.pluginName} ${t} 事件处理失败:`,e),await this.sendMsg({message_type:`private`,user_id:this.config.adminId[0]},[c.text(`插件 ${n.pluginName} ${t} 事件处理失败: ${e instanceof Error?e.stack??e.message:String(e)}`)])}}),this.ws.on(`notice`,async e=>{this.logger.DEBUG(`收到通知:`,e);let t=`notice.${e.notice_type}.${`sub_type`in e?e.sub_type:``}`;e.notice_type===`notify`&&(e.sub_type===`input_status`?t+=`.${e.group_id===0?`friend`:`group`}`:e.sub_type===`poke`&&(t+=`.${`group_id`in e?`group`:`friend`}`));for(let n of this.events.notice)if(t.includes(n.endPoint??`notice`))try{if(await n.callback(e)===`quit`){this.logger.DEBUG(`插件 ${n.pluginName} 请求提前终止 ${t} 事件`);break}}catch(e){this.logger.ERROR(`插件 ${n.pluginName} ${t} 事件处理失败:`,e),await this.sendMsg({message_type:`private`,user_id:this.config.adminId[0]},[c.text(`插件 ${n.pluginName} ${t} 事件处理失败: ${e instanceof Error?e.stack??e.message:String(e)}`)])}}),await this.ws.connect(),this.logger.INFO(`Bot 初始化完成`)}splitArgsRegex=/"([^"]*)"|'([^']*)'|(\S+)/g;splitArgs(e){let t=e.matchAll(this.splitArgsRegex),n=[];for(let e of t)n.push(e[1]||e[2]||e[3]);return n}extractCommandBody(e,t){return typeof t==`string`?e.startsWith(t)?e.slice(t.length).trim():null:t.test(e)?e.replace(t,``).trim():null}regCommandEvent(e){let t={...e,type:`command`};t.commander&&=(e=>()=>e().exitProcess(!1).usage(`用法: ${t.trigger} [选项]`).locale(this.config.yargsLocale??`zh_CN`).help(!1).version(!1))(t.commander),this.events.command=l([...this.events.command,t],`priority`,`down`);let n=()=>{let e=this.events.command.indexOf(t);e!==-1&&this.events.command.splice(e,1)};return this.unloaders[t.pluginName]=this.unloaders[t.pluginName]??[],this.unloaders[t.pluginName].push(n),n}regMessageEvent(e){let t={...e,type:`message`};this.events.message=l([...this.events.message,t],`priority`,`down`);let n=()=>{let e=this.events.message.indexOf(t);e!==-1&&this.events.message.splice(e,1)};return this.unloaders[t.pluginName]=this.unloaders[t.pluginName]??[],this.unloaders[t.pluginName].push(n),n}regNoticeEvent(e){let t={...e,type:`notice`};this.events.notice=l([...this.events.notice,t],`priority`,`down`);let n=()=>{let e=this.events.notice.indexOf(t);e!==-1&&this.events.notice.splice(e,1)};return this.unloaders[t.pluginName]=this.unloaders[t.pluginName]??[],this.unloaders[t.pluginName].push(n),n}regRequestEvent(e){let t={...e,type:`request`};this.events.request=l([...this.events.request,t],`priority`,`down`);let n=()=>{let e=this.events.request.indexOf(t);e!==-1&&this.events.request.splice(e,1)};return this.unloaders[t.pluginName]=this.unloaders[t.pluginName]??[],this.unloaders[t.pluginName].push(n),n}async sendMsg(e,t,{reply:n=!0,at:r=!0}={}){try{if(e.message_type===`private`)return await this.ws.send_private_msg({user_id:e.user_id,message:t});{let i=[];return n&&e.message_id&&i.push(c.reply(e.message_id)),r&&e.user_id&&i.push(c.at(e.user_id),c.text(`
2
+ `)),t=[...i,...t],await this.ws.send_group_msg({group_id:e.group_id,message:t})}}catch{return null}}async sendForwardMsg(e,t){try{return e.message_type===`private`?await this.ws.send_private_forward_msg({user_id:e.user_id,message:t}):await this.ws.send_group_forward_msg({group_id:e.group_id,message:t})}catch{return null}}async isFriend(e){return this.ws.get_friend_list().then(t=>t.find(t=>t.user_id===e.user_id))}async getUsername(e){return`group_id`in e?this.ws.get_group_member_info({group_id:e.group_id,user_id:e.user_id}).then(e=>e.nickname):this.ws.get_stranger_info({user_id:e.user_id}).then(e=>e.nickname)}},d=class{config;logger;bot;plugins={};configs={};normalizeConfigKey(e){return e.replaceAll(`/`,`__`)}async removeUselessLogs(){let t=await Array.fromAsync(a.promises.glob(`${this.config.logDir}/[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]*.log`)),n=this.config.maxFiles??30;if(t.length<=n)return;let r=t.length-n+1;t.sort().slice(0,r).map(t=>a.promises.rm(e.join(this.config.logDir,t)).catch())}constructor(e){this.config=e,this.logger=new n({title:`ATRI`,transformers:[r,...this.config.saveLogs?[i({filename:()=>(this.removeUselessLogs(),`./logs/${new Date().toISOString().slice(0,10)}.log`)})]:[]]}),this.bot=new u(this,{logLevel:e.logLevel,...e.botConfig})}async init(){console.log(`%c __ .__
3
+ _____ _/ |_ _______ |__|
4
+ \\__ \\ \\ __\\ \\_ __ \\ | |
5
+ / __ \\_ | | | | \\/ | |
6
+ (____ / |__| |__| |__|
7
+ \\/`,`font-family: Consolas;`),this.logger.INFO(`アトリは、高性能ですから!`),await this.bot.init();for(let e of this.config.plugins??[])await this.installPlugin(e);this.logger.INFO(`ATRI 初始化完成`)}async installPlugin(e){let t=await e(this);if(t.pluginName in this.plugins){this.logger.WARN(`插件 ${t.pluginName} 已经安装,跳过本次安装`);return}await t.install(),this.plugins[t.pluginName]=t,this.logger.INFO(`插件 ${t.pluginName} 安装成功`)}async uninstallPlugin(e){let t=this.plugins[e];if(!t){this.logger.WARN(`插件 ${e} 未找到,无法卸载`);return}let n=this.bot.unloaders[e]??[];for(let e of n)e();await t.uninstall(),delete this.plugins[e],this.logger.INFO(`插件 ${e} 卸载成功`)}async loadConfig(t,n,r=!1){if(!n)return{};if(t=this.normalizeConfigKey(t),!r)return this.configs[t]??await this.loadConfig(t,n,!0);await a.ensureDir(this.config.configDir);let i=e.join(this.config.configDir,`${t}.json`);if(!await a.exists(i))return await a.writeJSON(i,n,{spaces:2}),n;try{let e=await a.readJSON(i,`utf-8`),r={...n,...e};return this.configs[t]=r,r}catch(e){return this.logger.ERROR(`插件 ${t} 配置加载失败:`,e),{}}}async saveConfig(t,n){t=this.normalizeConfigKey(t),await a.ensureDir(this.config.configDir);let r=e.join(this.config.configDir,`${t}.json`);await a.writeJSON(r,n,{spaces:2}),Object.assign(this.configs[t],n)}};function f(e){return async t=>{let n=await Promise.resolve(typeof e==`function`?e():e),r={...n,atri:t,bot:t.bot,ws:t.bot.ws,config:await t.loadConfig(n.pluginName,n.defaultConfig),logger:t.logger.clone({title:n.pluginName}),refreshConfig:async()=>{r.config=await t.loadConfig(n.pluginName,n.defaultConfig)},saveConfig:async e=>{await t.saveConfig(n.pluginName,e??r.config)},regMessageEvent:e=>t.bot.regMessageEvent({...e,pluginName:n.pluginName}),regCommandEvent:e=>t.bot.regCommandEvent({...e,pluginName:n.pluginName}),regNoticeEvent:e=>t.bot.regNoticeEvent({...e,pluginName:n.pluginName}),regRequestEvent:e=>t.bot.regRequestEvent({...e,pluginName:n.pluginName})};return r}}export{d as ATRI,u as Bot,f as definePlugin,l as sortObjectArray};
package/package.json CHANGED
@@ -1,31 +1,33 @@
1
1
  {
2
2
  "name": "@atri-bot/core",
3
- "version": "1.1.30",
3
+ "type": "module",
4
+ "version": "2.0.0-beta.0",
4
5
  "description": "QQBOT TypeScript framework",
5
6
  "author": "huankong233",
6
7
  "license": "MIT",
7
- "type": "module",
8
- "main": "./dist/index.js",
9
- "types": "./dist/index.d.ts",
10
- "files": [
11
- "./dist/**/*"
12
- ],
13
8
  "repository": {
14
9
  "type": "git",
15
10
  "url": "git+https://github.com/HkTeamX/ATRI.git"
16
11
  },
12
+ "main": "./dist/index.mjs",
13
+ "types": "./dist/index.d.ts",
14
+ "files": [
15
+ "./dist/**/*"
16
+ ],
17
17
  "scripts": {
18
- "build": "pnpm run type-check && pnpm run lint && tsup",
19
- "clean": "rimraf dist",
18
+ "dev": "tsdown --watch",
19
+ "build": "tsdown",
20
20
  "lint": "eslint",
21
- "lint:fix": "eslint --fix",
22
- "type-check": "tsc --noEmit -p tsconfig.json --composite false"
21
+ "typecheck": "tsc --noEmit -p tsconfig.json --composite false"
23
22
  },
24
23
  "dependencies": {
25
- "@huan_kong/logger": "^1.0.6",
26
- "commander": "^14.0.1",
27
- "compare-versions": "^6.1.1",
28
- "node-napcat-ts": "^0.4.20",
29
- "picocolors": "^1.1.1"
24
+ "@huan_kong/logger": "^2.0.2",
25
+ "fs-extra": "^11.3.4",
26
+ "node-napcat-ts": "^0.4.23",
27
+ "yargs": "^18.0.0"
28
+ },
29
+ "devDependencies": {
30
+ "@types/fs-extra": "^11.0.4",
31
+ "@types/yargs": "^17.0.35"
30
32
  }
31
33
  }
package/README.md DELETED
@@ -1,7 +0,0 @@
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 DELETED
@@ -1,333 +0,0 @@
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
- interface PackageJson {
17
- name: string;
18
- version: string;
19
- [key: string]: unknown;
20
- }
21
- type CallbackReturnType = void | 'quit';
22
- type CallbackReturn = Promise<CallbackReturnType> | CallbackReturnType;
23
- type OptionParams = Record<string, any>;
24
- type OptionArgs = any[];
25
- interface CommandContext {
26
- params?: OptionParams;
27
- args?: OptionArgs;
28
- }
29
- interface CommandCallback<Opts extends CommandContext = CommandContext, T extends keyof MessageHandler = 'message'> {
30
- context: MessageHandler[T];
31
- prefix: string;
32
- commandName: string;
33
- params: Opts['params'];
34
- args: Opts['args'];
35
- }
36
- interface CommandEvent<Opts extends CommandContext = CommandContext, T extends keyof MessageHandler = 'message'> {
37
- type: 'command';
38
- endPoint?: T;
39
- callback: (context: CommandCallback<Opts, T>) => CallbackReturn;
40
- packageName: string;
41
- commandName: string | RegExp;
42
- commander?: Command;
43
- priority?: number;
44
- needHide?: boolean;
45
- needReply?: boolean;
46
- needAdmin?: boolean;
47
- }
48
- interface MessageCallback<T extends keyof MessageHandler = 'message'> {
49
- context: MessageHandler[T];
50
- }
51
- interface MessageEvent<T extends keyof MessageHandler = 'message'> {
52
- type: 'message';
53
- endPoint?: T;
54
- regexp?: RegExp;
55
- callback: (context: MessageCallback<T>) => CallbackReturn;
56
- packageName: string;
57
- priority?: number;
58
- needReply?: boolean;
59
- needAdmin?: boolean;
60
- }
61
- interface NoticeCallback<T extends keyof NoticeHandler = 'notice'> {
62
- context: NoticeHandler[T];
63
- }
64
- interface NoticeEvent<T extends keyof NoticeHandler = 'notice'> {
65
- type: 'notice';
66
- endPoint?: T;
67
- callback: (context: NoticeCallback<T>) => CallbackReturn;
68
- packageName: string;
69
- priority?: number;
70
- }
71
- interface RequestCallback<T extends keyof RequestHandler = 'request'> {
72
- context: RequestHandler[T];
73
- }
74
- interface RequestEvent<T extends keyof RequestHandler = 'request'> {
75
- type: 'request';
76
- endPoint?: T;
77
- callback: (context: RequestCallback<T>) => CallbackReturn;
78
- packageName: string;
79
- priority?: number;
80
- }
81
- type RegEventOptions = CommandEvent | MessageEvent | NoticeEvent | RequestEvent;
82
- type AutoInferCommandEndPoint<Opts extends CommandContext = CommandContext> = {
83
- [T in keyof MessageHandler]: RemoveField<CommandEvent<Opts, T>, 'packageName' | 'type'> & {
84
- endPoint: T;
85
- };
86
- }[keyof MessageHandler];
87
- type AutoInferMessageEndPoint = {
88
- [T in keyof MessageHandler]: RemoveField<MessageEvent<T>, 'packageName' | 'type'> & {
89
- endPoint: T;
90
- };
91
- }[keyof MessageHandler];
92
- type AutoInferRequestEndPoint = {
93
- [T in keyof RequestHandler]: RemoveField<RequestEvent<T>, 'packageName' | 'type'> & {
94
- endPoint: T;
95
- };
96
- }[keyof RequestHandler];
97
- type AutoInferNoticeEndPoint = {
98
- [T in keyof NoticeHandler]: RemoveField<NoticeEvent<T>, 'packageName' | 'type'> & {
99
- endPoint: T;
100
- };
101
- }[keyof NoticeHandler];
102
- declare abstract class BasePlugin<TConfig extends object = object> {
103
- packageJson: PackageJson;
104
- disableAutoLoadConfig?: boolean;
105
- configName?: string;
106
- defaultConfig?: TConfig;
107
- config: TConfig;
108
- atri: ATRI;
109
- bot: Bot;
110
- ws: NCWebsocket;
111
- unregHandlers: UnRegHandler[];
112
- logger: Logger;
113
- constructor(atri: ATRI, packageJson: PackageJson);
114
- abstract load(): void | Promise<void>;
115
- abstract unload(): void | Promise<void>;
116
- saveConfig(config?: TConfig): void;
117
- regCommandEvent<Opts extends CommandContext = CommandContext>(options: AutoInferCommandEndPoint<Opts>): () => void;
118
- regCommandEvent<Opts extends CommandContext = CommandContext>(options: RemoveField<CommandEvent<Opts, 'message'>, 'packageName' | 'type'>): () => void;
119
- regMessageEvent(options: AutoInferMessageEndPoint): () => void;
120
- regMessageEvent(options: RemoveField<MessageEvent<'message'>, 'packageName' | 'type'>): () => void;
121
- regRequestEvent(options: AutoInferRequestEndPoint): () => void;
122
- regRequestEvent(options: RemoveField<RequestEvent<'request'>, 'packageName' | 'type'>): () => void;
123
- regNoticeEvent(options: AutoInferNoticeEndPoint): () => void;
124
- regNoticeEvent(options: RemoveField<NoticeEvent<'notice'>, 'packageName' | 'type'>): () => void;
125
- }
126
-
127
- type BotConfig = {
128
- debug?: boolean;
129
- logLevel?: LogLevel;
130
- prefix: NonEmptyArray<string>;
131
- adminId: NonEmptyArray<number>;
132
- connection: RemoveField<NCWebsocketOptions, 'reconnection'>;
133
- reconnection: NCWebsocketOptions['reconnection'];
134
- };
135
- type UnRegHandler = () => void;
136
- interface BotEvents {
137
- command: CommandEvent[];
138
- message: MessageEvent[];
139
- notice: NoticeEvent[];
140
- request: RequestEvent[];
141
- }
142
- interface CommandData {
143
- prefix: string;
144
- commandName: string;
145
- params: OptionParams;
146
- args: OptionArgs;
147
- }
148
-
149
- declare class Bot extends InjectLogger {
150
- ws: NCWebsocket;
151
- config: BotConfig;
152
- events: BotEvents;
153
- private constructor();
154
- static init(config: BotConfig): Promise<Bot>;
155
- /**
156
- * 注册事件
157
- */
158
- regEvent(_options: RegEventOptions): () => void;
159
- /**
160
- * 解析命令
161
- * @param rawMessage 原始消息
162
- * @param commandName 命令名称
163
- * @param command 命令对象
164
- * @returns 解析结果
165
- */
166
- parseCommand(rawMessage: string, commandName: CommandEvent['commandName'], command?: Command): [0, CommandData] | [1, string] | [2, string];
167
- /**
168
- * 获取命令信息
169
- * @param command 命令对象
170
- * @param fallback 后备值
171
- * @param field 字段名
172
- * @returns 命令信息
173
- */
174
- getCommandInfo(command: Command, fallback: string, field?: 'name' | 'description'): string;
175
- /**
176
- * 获取命令帮助信息
177
- * @param commandName 命令名称
178
- */
179
- getCommandHelpInformation(commandName: string): string | undefined;
180
- /**
181
- * 发送普通消息
182
- */
183
- sendMsg(context: {
184
- message_type: 'private';
185
- user_id: number;
186
- message_id?: number;
187
- } | {
188
- message_type: 'group';
189
- group_id: number;
190
- user_id?: number;
191
- message_id?: number;
192
- }, message: SendMessageSegment[], { reply, at }?: {
193
- reply?: boolean | undefined;
194
- at?: boolean | undefined;
195
- }): Promise<{
196
- message_id: number;
197
- } | null>;
198
- /**
199
- * 发送合并转发
200
- */
201
- sendForwardMsg(context: {
202
- message_type: 'group';
203
- group_id: number;
204
- } | {
205
- message_type: 'private';
206
- user_id: number;
207
- }, message: NodeSegment[]): Promise<{
208
- message_id: number;
209
- } | null>;
210
- /**
211
- * 判断是否是机器人的好友
212
- */
213
- isFriend(context: {
214
- user_id: number;
215
- }): Promise<{
216
- birthday_year: number;
217
- birthday_month: number;
218
- birthday_day: number;
219
- user_id: number;
220
- age: number;
221
- phone_num: string;
222
- email: string;
223
- category_id: number;
224
- nickname: string;
225
- remark: string;
226
- sex: "male" | "female" | "unknown";
227
- level: number;
228
- } | undefined>;
229
- /**
230
- * 获取用户名
231
- */
232
- getUsername(context: {
233
- user_id: number;
234
- } | {
235
- user_id: number;
236
- group_id: number;
237
- }): Promise<string>;
238
- }
239
-
240
- type LogRecorderConfig = {
241
- enable?: boolean;
242
- maxFiles?: number;
243
- logLevel?: LogLevel;
244
- logDir?: string;
245
- };
246
-
247
- type ATRIConfig = {
248
- bot: BotConfig;
249
- logRecorder?: LogRecorderConfig;
250
- debug?: boolean;
251
- baseDir: string;
252
- configDir?: string;
253
- logLevel?: LogLevel;
254
- plugins?: string[];
255
- timezone?: string;
256
- disableClearTerminal?: boolean;
257
- disableStartupMessage?: boolean;
258
- };
259
- interface PluginModule {
260
- Plugin?: new (...args: ConstructorParameters<typeof BasePlugin>) => BasePlugin;
261
- }
262
- interface LoadPluginHookContext {
263
- plugin: BasePlugin;
264
- packageName: string;
265
- }
266
- type LoadPluginHook = (context: LoadPluginHookContext) => Promise<boolean> | boolean;
267
- interface LoadPluginOptions {
268
- initPlugin?: boolean;
269
- quiet?: boolean;
270
- import?: NodeJS.Require;
271
- baseDir?: string;
272
- }
273
-
274
- declare class LogRecorder extends InjectLogger {
275
- config: LogRecorderConfig;
276
- atriConfig: ATRIConfig;
277
- originConsoleLog: (message?: any, ...optionalParams: any[]) => void;
278
- constructor(atriConfig: ATRIConfig, config: LogRecorderConfig);
279
- rewriteConsole(): void;
280
- handleException(): void;
281
- stripAnsi(str: string): string;
282
- saveLog(args: string[]): void;
283
- removeUselessLogs(): void;
284
- }
285
-
286
- declare class ATRI extends InjectLogger {
287
- config: ATRIConfig;
288
- configDir: string;
289
- bot: Bot;
290
- logRecorder: LogRecorder;
291
- import: NodeJS.Require;
292
- loadedPlugins: Record<string, BasePlugin>;
293
- loadPluginHooks: Record<string, LoadPluginHook>;
294
- private constructor();
295
- static init(config: ATRIConfig): Promise<ATRI>;
296
- /**
297
- * 0 - 成功 (返回 插件实例化后的对象)
298
- * 1 - 失败 (返回 错误信息)
299
- * 2 - 加载钩子返回 false (返回 钩子名)
300
- */
301
- loadPlugin<T extends BasePlugin = BasePlugin>(packageName: string, options?: LoadPluginOptions): Promise<[0, T] | [1 | 2, string]>;
302
- unloadPlugin(packageName: string): Promise<[0] | [1, string]>;
303
- loadConfig<TConfig extends object>(packageName: string, defaultConfig: TConfig): Promise<{}>;
304
- saveConfig<TConfig extends object>(packageName: string, config: TConfig): Promise<void>;
305
- addPluginLoadHook(hookName: string, hook: LoadPluginHook): void;
306
- removePluginLoadHook(hookName: string): void;
307
- }
308
-
309
- interface CommanderTransformOptions {
310
- max?: number;
311
- min?: number;
312
- }
313
-
314
- declare class CommanderUtils {
315
- static enum(options: string[]): (value: string) => string;
316
- static int(options?: CommanderTransformOptions): (value: string) => number;
317
- static float(options?: CommanderTransformOptions): (value: string) => number;
318
- }
319
-
320
- /**
321
- * 性能计时器
322
- * 返回一个获取当前时间耗时的函数
323
- */
324
- declare function performanceCounter(): () => string;
325
- /**
326
- * 排序对象数组
327
- * @param arr 对象数组
328
- * @param property 属性名
329
- * @param sortType up=>升序 down=>降序
330
- */
331
- declare function sortObjectArray<T extends object>(arr: T[], property: keyof T, sortType?: 'up' | 'down'): T[];
332
-
333
- 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, CommanderUtils, type LoadPluginHook, type LoadPluginHookContext, type LoadPluginOptions, type LogRecorderConfig, type MessageCallback, type MessageEvent, type NonEmptyArray, type NoticeCallback, type NoticeEvent, type OptionArgs, type OptionParams, type PackageJson, type PluginModule, type RegEventOptions, type RemoveField, type RequestCallback, type RequestEvent, type UnRegHandler, performanceCounter, sortObjectArray };
package/dist/index.js DELETED
@@ -1,13 +0,0 @@
1
- var I=Object.defineProperty;var g=(d,e)=>I(d,"name",{value:e,configurable:!0});import{InjectLogger as L,Logger as M,LogLevel as w}from"@huan_kong/logger";import{createRequire as O}from"module";import l from"fs";import h from"path";import B from"process";import{InjectLogger as A,Logger as q,LogLevel as P}from"@huan_kong/logger";import{CommanderError as S}from"commander";import{NCWebsocket as D,Structs as c}from"node-napcat-ts";function b(){let d=performance.now();return()=>(performance.now()-d).toFixed(2)}g(b,"performanceCounter");function f(d,e,t="up"){return d.sort((n,s)=>n[e]>s[e]?t==="up"?1:-1:n[e]<s[e]?t==="up"?-1:1:0)}g(f,"sortObjectArray");var v=class d extends A{static{g(this,"Bot")}ws;config;events={command:[],message:[],notice:[],request:[]};constructor(e,t){super({level:e.logLevel??(e.debug?P.DEBUG:void 0)}),this.ws=t,this.config=e,t.on("api.preSend",n=>this.logger.DEBUG("\u53D1\u9001API\u8BF7\u6C42",n)),t.on("api.response.success",n=>this.logger.DEBUG("\u6536\u5230API\u6210\u529F\u54CD\u5E94",n)),t.on("api.response.failure",n=>this.logger.DEBUG("\u6536\u5230API\u5931\u8D25\u54CD\u5E94",n)),t.on("message",async n=>{if(n.message.length===0){this.logger.DEBUG("\u6536\u5230\u7A7A\u6D88\u606F, \u5DF2\u8DF3\u8FC7\u5904\u7406\u6D41\u7A0B:",n);return}if(this.config.debug&&!this.config.adminId.includes(n.user_id)){this.logger.DEBUG("\u5F53\u524D\u5904\u4E8E\u8C03\u8BD5\u6A21\u5F0F, \u975E\u7BA1\u7406\u5458\u6D88\u606F, \u5DF2\u8DF3\u8FC7\u5904\u7406\u6D41\u7A0B:",n);return}else this.logger.DEBUG("\u6536\u5230\u6D88\u606F:",n);let s=`message.${n.message_type}.${n.sub_type}`,i=this.config.adminId.includes(n.user_id),o=n.message[0].type==="reply";for(let r of this.events.message)if(s.includes(r.endPoint??"message")&&(!r.needReply||o)&&(!r.needAdmin||i)&&(!r.regexp||r.regexp.test(n.raw_message)))try{if(await r.callback({context:n})==="quit"){this.logger.DEBUG(`\u63D2\u4EF6 ${r.packageName} \u8BF7\u6C42\u63D0\u524D\u7EC8\u6B62`);return}}catch(m){this.logger.ERROR(`\u63D2\u4EF6 ${r.packageName} message \u4E8B\u4EF6\u5904\u7406\u5931\u8D25:`,m),await this.sendMsg(n,[c.text(`\u63D2\u4EF6 ${r.packageName} message \u4E8B\u4EF6\u5904\u7406\u5931\u8D25, \u8BF7\u8054\u7CFB\u7BA1\u7406\u5458\u5904\u7406: ${m instanceof Error?m.stack??m.message:String(m)}`)])}for(let r of this.events.command)if(s.includes(r.endPoint??"message")&&(!r.needAdmin||i)&&(!r.needReply||o)){let[m,a]=this.parseCommand(n.raw_message,r.commandName,r.commander);if(m===1)continue;if(m===2){await this.sendMsg(n,[c.text(a)]);continue}let{prefix:C,commandName:_,params:y,args:x}=a;try{if(await r.callback({context:n,prefix:C,commandName:_,params:y,args:x})==="quit"){this.logger.DEBUG(`\u63D2\u4EF6 ${r.packageName} \u8BF7\u6C42\u63D0\u524D\u7EC8\u6B62`);return}}catch(p){this.logger.ERROR(`\u63D2\u4EF6 ${r.packageName} command \u4E8B\u4EF6\u5904\u7406\u5931\u8D25:`,p),await this.sendMsg(n,[c.text(`\u63D2\u4EF6 ${r.packageName} command \u4E8B\u4EF6\u5904\u7406\u5931\u8D25, \u8BF7\u8054\u7CFB\u7BA1\u7406\u5458\u5904\u7406: ${p instanceof Error?p.stack??p.message:String(p)}`)])}}}),t.on("request",async n=>{this.logger.DEBUG("\u6536\u5230\u8BF7\u6C42:",n);let s=`request.${n.request_type}.${"sub_type"in n?n.sub_type:""}`;for(let i of this.events.request)if(s.includes(i.endPoint??"request"))try{if(await i.callback({context:n})==="quit"){this.logger.DEBUG(`\u63D2\u4EF6 ${i.packageName} \u8BF7\u6C42\u63D0\u524D\u7EC8\u6B62`);return}}catch(o){this.logger.ERROR(`\u63D2\u4EF6 ${i.packageName} \u4E8B\u4EF6\u5904\u7406\u5931\u8D25:`,o),await this.sendMsg({message_type:"private",user_id:this.config.adminId[0]},[c.text(`\u63D2\u4EF6 ${i.packageName} request \u4E8B\u4EF6\u5904\u7406\u5931\u8D25: ${o instanceof Error?o.stack??o.message:String(o)}`)])}}),t.on("notice",async n=>{this.logger.DEBUG("\u6536\u5230\u901A\u77E5:",n);let s=`notice.${n.notice_type}.${"sub_type"in n?n.sub_type:""}`;n.notice_type==="notify"&&(n.sub_type==="input_status"?s+=`.${n.group_id!==0?"group":"friend"}`:n.sub_type==="poke"&&(s+=`.${"group_id"in n?"group":"friend"}`));for(let i of this.events.notice)if(s.includes(i.endPoint??"notice"))try{if(await i.callback({context:n})==="quit"){this.logger.DEBUG(`\u63D2\u4EF6 ${i.packageName} \u8BF7\u6C42\u63D0\u524D\u7EC8\u6B62`);return}}catch(o){this.logger.ERROR(`\u63D2\u4EF6 ${i.packageName} notice \u4E8B\u4EF6\u5904\u7406\u5931\u8D25:`,o),await this.sendMsg({message_type:"private",user_id:this.config.adminId[0]},[c.text(`\u63D2\u4EF6 ${i.packageName} notice \u4E8B\u4EF6\u5904\u7406\u5931\u8D25: ${o instanceof Error?o.stack??o.message:String(o)}`)])}}),process.on("uncaughtException",n=>{this.sendMsg({message_type:"private",user_id:this.config.adminId[0]},[c.text(`\u6355\u83B7\u5230\u672A\u5904\u7406\u7684\u5F02\u5E38, \u673A\u5668\u4EBA\u5C06\u9000\u51FA, \u9519\u8BEF\u4FE1\u606F:
2
- ${n instanceof Error?n.stack??n.message:String(n)}, \u8BF7\u524D\u5F80\u540E\u53F0\u68C0\u67E5`)])}),this.logger.INFO("Bot \u521D\u59CB\u5316\u5B8C\u6210")}static async init(e){return new Promise((t,n)=>{let s=new q({title:"Bot",level:e.logLevel??(e.debug?P.DEBUG:void 0)}),i=new D({...e.connection,reconnection:e.reconnection}),o=b();i.on("socket.connecting",r=>{o=b(),s.INFO(`\u8FDE\u63A5\u4E2D [#${r.reconnection.nowAttempts}/${r.reconnection.attempts}]`)}),i.on("socket.error",r=>{if(s.ERROR(`\u8FDE\u63A5\u5931\u8D25 [#${r.reconnection.nowAttempts}/${r.reconnection.attempts}]`),s.ERROR("\u9519\u8BEF\u4FE1\u606F:",r),r.error_type==="response_error"&&(s.ERROR("NapCat \u670D\u52A1\u7AEF\u8FD4\u56DE\u9519\u8BEF, \u53EF\u80FD\u662F AccessToken \u9519\u8BEF"),process.exit(1)),r.reconnection.nowAttempts>=r.reconnection.attempts)throw n(`\u91CD\u8BD5\u6B21\u6570\u8D85\u8FC7\u8BBE\u7F6E\u7684${r.reconnection.attempts}\u6B21!`),new Error(`\u91CD\u8BD5\u6B21\u6570\u8D85\u8FC7\u8BBE\u7F6E\u7684${r.reconnection.attempts}\u6B21!`)}),i.on("socket.open",async r=>{s.INFO(`\u8FDE\u63A5\u6210\u529F [#${r.reconnection.nowAttempts}/${r.reconnection.attempts}]`),s.INFO(`\u8FDE\u63A5 NapCat \u8017\u65F6: ${o()}ms`),t(new d(e,i))}),i.connect()})}regEvent(e){let t={...e,priority:e.priority??1};switch(t.type){case"command":return this.events.command=f([...this.events.command,t],"priority","down"),()=>{let n=this.events.command.indexOf(t);n!==-1&&this.events.command.splice(n,1)};case"message":return this.events.message=f([...this.events.message,t],"priority","down"),()=>{let n=this.events.message.indexOf(t);n!==-1&&this.events.message.splice(n,1)};case"notice":return this.events.notice=f([...this.events.notice,t],"priority","down"),()=>{let n=this.events.notice.indexOf(t);n!==-1&&this.events.notice.splice(n,1)};case"request":return this.events.request=f([...this.events.request,t],"priority","down"),()=>{let n=this.events.request.indexOf(t);n!==-1&&this.events.request.splice(n,1)}}}parseCommand(e,t,n){let s=e.charAt(0),i=this.config.prefix.find(a=>a===s);if(!i)return[1,"\u672A\u5339\u914D\u5230\u524D\u7F00"];let o=e.split(" ");if(o.length===0)return[1,"\u547D\u4EE4\u4FE1\u606F\u672A\u7A7A"];let r=o[0].slice(i.length),m=o.slice(1).filter(a=>a!=="");if(t!=="*"&&(typeof t=="string"&&t!==r||t instanceof RegExp&&r.match(t)===null))return[1,"\u547D\u4EE4\u540D\u4E0D\u5339\u914D"];if(n)try{let a=n.configureOutput({writeErr:g(()=>{},"writeErr"),writeOut:g(()=>{},"writeOut")}).exitOverride().parse(m,{from:"user"});return[0,{prefix:i,commandName:r,params:a.opts(),args:a.processedArgs}]}catch(a){if(a instanceof S||"code"in a&&"message"in a){let{code:C,message:_}=a;if(C==="commander.helpDisplayed")return[2,this.getCommandHelpInformation(t.toString())??""];let y=_.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").replace(/Expected (\d+) arguments? but got (\d+)\./,"\u671F\u671B $1 \u4E2A\u53C2\u6570\uFF0C\u4F46\u5F97\u5230\u4E86 $2 \u4E2A\u53C2\u6570\u3002");return[2,y+(y.includes("\u4F60\u662F\u60F3\u8981")?"":`
3
- (\u4F7F\u7528 -h \u83B7\u53D6\u5E2E\u52A9\u4FE1\u606F)`)]}else return this.logger.ERROR("\u547D\u4EE4\u5904\u7406\u51FA\u9519:",a),[2,a instanceof Error?a.message:"\u672A\u77E5\u9519\u8BEF"]}return[0,{prefix:i,commandName:r,params:{},args:[]}]}getCommandInfo(e,t,n="name"){let s=e[n]().replace("/","");return s===""||s==="program"?t:s}getCommandHelpInformation(e){let t=this.events.command.find(o=>o.commandName==="*"?!1:typeof o.commandName=="string"?o.commandName===e:o.commandName instanceof RegExp?o.commandName.test(e):!1);if(!t||!t.commander)return;let n=this.getCommandInfo(t.commander,t.commandName.toString()),s=this.config.prefix[0];return t.commander.name(n.includes(s)?n:`${s}${n}`).helpOption("-h, --help","\u5C55\u793A\u5E2E\u52A9\u4FE1\u606F").helpInformation().replaceAll("default:","\u9ED8\u8BA4\u503C:").replace("Arguments:","\u53C2\u6570:").replace("Options:","\u9009\u9879:").replace("Usage:","\u7528\u6CD5:")}async sendMsg(e,t,{reply:n=!0,at:s=!0}={}){try{if(e.message_type==="private")return await this.ws.send_private_msg({user_id:e.user_id,message:t});{let i=[];return n&&e.message_id&&i.push(c.reply(e.message_id)),s&&e.user_id&&i.push(c.at(e.user_id),c.text(`
4
- `)),t=[...i,...t],await this.ws.send_group_msg({group_id:e.group_id,message:t})}}catch{return null}}async sendForwardMsg(e,t){try{return e.message_type==="private"?await this.ws.send_private_forward_msg({user_id:e.user_id,message:t}):await this.ws.send_group_forward_msg({group_id:e.group_id,message:t})}catch{return null}}async isFriend(e){return this.ws.get_friend_list().then(t=>t.find(n=>n.user_id===e.user_id))}async getUsername(e){return"group_id"in e?this.ws.get_group_member_info({group_id:e.group_id,user_id:e.user_id}).then(t=>t.nickname):this.ws.get_stranger_info({user_id:e.user_id}).then(t=>t.nickname)}};import{InjectLogger as H,LogLevel as k}from"@huan_kong/logger";import u from"fs";import R from"path";var E=class extends H{static{g(this,"LogRecorder")}config;atriConfig;originConsoleLog=console.log;constructor(e,t){if(super({level:e.logLevel??(e.debug?k.DEBUG:void 0)}),this.atriConfig=e,this.config=t,e.debug&&!t.enable){this.logger.WARN("\u5F53\u524D\u5904\u4E8E\u8C03\u8BD5\u6A21\u5F0F, \u5982\u9700\u8BB0\u5F55\u65E5\u5FD7, \u8BF7\u5C06 logRecorder.enable \u8BBE\u4E3A true");return}this.config={maxFiles:31,maxSize:100*1024*1024,logLevel:e.debug?k.DEBUG:k.INFO,logDir:R.join(e.baseDir,"logs"),...this.config},this.rewriteConsole(),this.handleException(),this.logger.INFO("\u65E5\u5FD7\u8BB0\u5F55\u5668\u5DF2\u542F\u7528")}rewriteConsole(){console.log=(e=>(...t)=>{this.saveLog(t),e(...t)})(console.log)}handleException(){process.on("uncaughtException",e=>{this.logger.ERROR(`\u6355\u83B7\u5230\u672A\u5904\u7406\u7684\u5F02\u5E38, \u9519\u8BEF\u4FE1\u606F:
5
- `,e)})}stripAnsi(e){return e.replace(/\u001B\[[0-9;]*m/g,"")}saveLog(e){let t=e.map(s=>this.stripAnsi(s)).join(" ");u.existsSync(this.config.logDir)||u.mkdirSync(this.config.logDir,{recursive:!0});let n=R.join(this.config.logDir,`${new Date().toISOString().split("T")[0]}.log`);u.existsSync(n)||this.removeUselessLogs(),u.appendFileSync(n,t+`
6
- `,{encoding:"utf-8"})}removeUselessLogs(){let e=u.readdirSync(this.config.logDir).filter(n=>/^\d{4}-\d{2}-\d{2}/.test(n)&&u.statSync(R.join(this.config.logDir,n)).isFile());if(e.length<=this.config.maxFiles)return;let t=e.length-this.config.maxFiles+1;e.sort().slice(0,t).map(n=>u.rmSync(R.join(this.config.logDir,n)))}};var T=class d extends L{static{g(this,"ATRI")}config;configDir;bot;logRecorder;import;loadedPlugins={};loadPluginHooks={};constructor(e,t,n){super({level:e.logLevel??(e.debug?w.DEBUG:void 0)}),this.config=e,this.bot=t,this.logRecorder=n,this.configDir=e.configDir??h.join(e.baseDir,"config"),this.import=O(e.baseDir)}static async init(e){let t=new M({title:"ATRI",level:e.logLevel??(e.debug?w.DEBUG:void 0)});e.disableClearTerminal||console.log("\x1Bc"),e.disableStartupMessage||console.log(`%c __ .__
7
- _____ _/ |_ _______ |__|
8
- \\__ \\ \\ __\\ \\_ __ \\ | |
9
- / __ \\_ | | | | \\/ | |
10
- (____ / |__| |__| |__|
11
- \\/`,"font-family: Consolas;");let n=new E(e,e.logRecorder??{});e.disableStartupMessage||t.INFO("\u30A2\u30C8\u30EA\u306F\u3001\u9AD8\u6027\u80FD\u3067\u3059\u304B\u3089\uFF01"),"debug"in e.bot||(e.bot.debug=e.debug),"logLevel"in e.bot||(e.bot.logLevel=e.logLevel),"timezone"in e||(e.timezone="Asia/Shanghai");let s=await v.init(e.bot),i=new d(e,s,n);for(let o of e.plugins??[]){let[r]=await i.loadPlugin(o);r!==0&&(t.ERROR("\u521D\u59CB\u63D2\u4EF6\u52A0\u8F7D\u5931\u8D25\uFF0C\u7A0B\u5E8F\u7EC8\u6B62"),B.exit(1))}return t.INFO("ATRI \u521D\u59CB\u5316\u5B8C\u6210"),i}async loadPlugin(e,t){if(t={initPlugin:!0,quiet:!1,import:this.import,...t},t.baseDir&&(t.import=O(t.baseDir)),t.quiet||this.logger.INFO(`\u52A0\u8F7D\u63D2\u4EF6: ${e}`),this.loadedPlugins[e])return t.quiet||this.logger.WARN(`\u63D2\u4EF6 ${e} \u5DF2\u52A0\u8F7D\uFF0C\u8DF3\u8FC7\u52A0\u8F7D`),[0,this.loadedPlugins[e]];let n=[e,h.join(e,"src/index.ts")];this.config.debug&&(n=n.reverse());let s;try{s=await t.import(n[0])}catch{try{s=await t.import(n[1])}catch(r){return t.quiet||this.logger.ERROR(`\u63D2\u4EF6 ${e} \u5BFC\u5165\u5931\u8D25:`,r),[1,r instanceof Error?r.message:String(r)]}}if(!s.Plugin)return t.quiet||this.logger.ERROR(`\u63D2\u4EF6 ${e} \u52A0\u8F7D\u5931\u8D25: \u672A\u627E\u5230 Plugin \u7C7B`),[1,"\u672A\u627E\u5230 Plugin \u7C7B"];let i;try{let r=t.import.resolve(h.join(e,"package.json"));i=JSON.parse(l.readFileSync(r,"utf-8"))}catch(r){t.quiet||(this.logger.WARN(`\u63D2\u4EF6 ${e} \u672A\u627E\u5230 package.json, \u5C06\u4F7F\u7528\u672A\u77E5\u4EE3\u66FF`),this.logger.DEBUG(r)),i={name:"\u672A\u77E5",version:"\u672A\u77E5"}}let o;try{o=new s.Plugin(this,i)}catch(r){return t.quiet||this.logger.ERROR(`\u63D2\u4EF6 ${e} \u5B9E\u4F8B\u5316\u5931\u8D25:`,r),[1,r instanceof Error?r.message:String(r)]}if(!t.initPlugin)return[0,o];try{for(let r in this.loadPluginHooks){let m=this.loadPluginHooks[r];if(!await m({plugin:o,packageName:e}))return t.quiet||this.logger.ERROR(`\u63D2\u4EF6 ${e} \u52A0\u8F7D\u5931\u8D25: \u52A0\u8F7D\u94A9\u5B50 ${r} \u8FD4\u56DE false`),[2,r]}return o.disableAutoLoadConfig||(o.config=await this.loadConfig(o.configName??e,o.defaultConfig??{})),await o.load(),this.loadedPlugins[e]=o,t.quiet||this.logger.INFO(`\u63D2\u4EF6 ${e} \u52A0\u8F7D\u6210\u529F`),[0,o]}catch(r){return t.quiet||this.logger.ERROR(`\u63D2\u4EF6 ${e} \u52A0\u8F7D\u5931\u8D25:`,r),[1,r instanceof Error?r.message:String(r)]}}async unloadPlugin(e){let t=this.loadedPlugins[e];if(!t)return this.logger.WARN(`\u63D2\u4EF6 ${e} \u672A\u52A0\u8F7D`),[1,"\u63D2\u4EF6\u672A\u52A0\u8F7D"];try{return t.unregHandlers.forEach(n=>n()),await t.unload(),delete this.loadedPlugins[e],this.logger.INFO(`\u63D2\u4EF6 ${e} \u5378\u8F7D\u6210\u529F`),[0]}catch(n){return this.logger.ERROR(`\u63D2\u4EF6 ${e} \u5378\u8F7D\u5931\u8D25:`,n),[1,n instanceof Error?n.message:String(n)]}}async loadConfig(e,t){e=e.replaceAll("/","__"),l.existsSync(this.configDir)||l.mkdirSync(this.configDir,{recursive:!0});let n=h.join(this.configDir,`${e}.json`);if(!l.existsSync(n))return l.writeFileSync(n,JSON.stringify(t,null,2)),t;try{let s=JSON.parse(l.readFileSync(n,"utf-8"));return{...t,...s}}catch(s){return this.logger.ERROR(`\u63D2\u4EF6 ${e} \u914D\u7F6E\u52A0\u8F7D\u5931\u8D25:`,s),{}}}async saveConfig(e,t){e=e.replaceAll("/","__"),l.existsSync(this.configDir)||l.mkdirSync(this.configDir,{recursive:!0});let n=h.join(this.configDir,`${e}.json`);l.writeFileSync(n,JSON.stringify(t,null,2))}addPluginLoadHook(e,t){this.loadPluginHooks[e]=t}removePluginLoadHook(e){delete this.loadPluginHooks[e]}};var N=class{static{g(this,"CommanderUtils")}static enum(e){return function(t){if(!e.includes(t))throw new Error(`\u53C2\u6570 "${t}" \u4E0D\u662F\u6709\u6548\u53C2\u6570, \u6709\u6548\u53C2\u6570:
12
- ${e.map(n=>` - ${n}`).join(`
13
- `)}`);return t}}static int(e={}){return function(t){let n=parseInt(t);if(isNaN(n))throw new Error(`\u53C2\u6570 "${t}" \u4E0D\u662F\u6709\u6548\u7684\u6574\u6570`);if(e.min!==void 0&&n<e.min)throw new Error(`\u53C2\u6570 "${t}" \u4E0D\u80FD\u5C0F\u4E8E ${e.min}`);if(e.max!==void 0&&n>e.max)throw new Error(`\u53C2\u6570 "${t}" \u4E0D\u80FD\u5927\u4E8E ${e.max}`);return n}}static float(e={}){return function(t){let n=parseFloat(t);if(isNaN(n))throw new Error(`\u53C2\u6570 "${t}" \u4E0D\u662F\u6709\u6548\u7684\u6D6E\u70B9\u6570`);if(e.min!==void 0&&n<e.min)throw new Error(`\u53C2\u6570 "${t}" \u4E0D\u80FD\u5C0F\u4E8E ${e.min}`);if(e.max!==void 0&&n>e.max)throw new Error(`\u53C2\u6570 "${t}" \u4E0D\u80FD\u5927\u4E8E ${e.max}`);return n}}};import{Logger as F,LogLevel as j}from"@huan_kong/logger";var $=class{static{g(this,"BasePlugin")}packageJson;disableAutoLoadConfig;configName;defaultConfig;config;atri;bot;ws;unregHandlers=[];logger;constructor(e,t){this.atri=e,this.bot=e.bot,this.ws=e.bot.ws,this.config={},this.packageJson=t,this.logger=new F({title:this.packageJson.name,level:e.config.logLevel??(e.config.debug?j.DEBUG:void 0)})}saveConfig(e){this.atri.saveConfig(this.configName??this.packageJson.name,e??this.config)}regCommandEvent(e){let t=this.bot.regEvent({...e,type:"command",packageName:this.packageJson.name});return this.unregHandlers.push(t),t}regMessageEvent(e){let t=this.bot.regEvent({...e,type:"message",packageName:this.packageJson.name});return this.unregHandlers.push(t),t}regRequestEvent(e){let t=this.bot.regEvent({...e,type:"request",packageName:this.packageJson.name});return this.unregHandlers.push(t),t}regNoticeEvent(e){let t=this.bot.regEvent({...e,type:"notice",packageName:this.packageJson.name});return this.unregHandlers.push(t),t}};export{T as ATRI,$ as BasePlugin,v as Bot,N as CommanderUtils,b as performanceCounter,f as sortObjectArray};