@karinjs/adapter-qqbot 1.2.1 → 1.2.4
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/lib/core/api.d.ts +5 -8
- package/lib/core/api.js +6 -5
- package/lib/core/index.js +13 -12
- package/lib/core/markdown.js +17 -3
- package/lib/index.js +1 -1
- package/lib/utils/common.d.ts +7 -0
- package/lib/utils/common.js +12 -0
- package/lib/utils/config.d.ts +1 -1
- package/lib/utils/config.js +14 -14
- package/package.json +1 -1
package/lib/core/api.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import WebSocket from 'ws';
|
|
2
|
-
import
|
|
2
|
+
import EventEmitter from 'events';
|
|
3
3
|
import { AccountCfgType } from '../utils/index.js';
|
|
4
|
+
import { LoggerLevel } from 'node-karin';
|
|
4
5
|
import { IdType, FileType, PathType, V2ApiType, UploadMediaOptions, SendMessageOptions, UploadMediaResponse, SubEvent } from '../types/index.js';
|
|
5
6
|
export interface SendMessageResponse {
|
|
6
7
|
/** 消息唯一ID */
|
|
@@ -15,7 +16,7 @@ export type Params = Array<{
|
|
|
15
16
|
key: string;
|
|
16
17
|
values: string[];
|
|
17
18
|
}>;
|
|
18
|
-
export declare class QQBotApi {
|
|
19
|
+
export declare class QQBotApi extends EventEmitter {
|
|
19
20
|
#private;
|
|
20
21
|
/** 开发者的appId */
|
|
21
22
|
appId: string;
|
|
@@ -57,13 +58,9 @@ export declare class QQBotApi {
|
|
|
57
58
|
* @param isRefresh 是否是刷新凭证
|
|
58
59
|
*/
|
|
59
60
|
getAccessToken(isRefresh?: boolean): Promise<{
|
|
60
|
-
/**
|
|
61
|
-
* 凭证有效时间,单位:秒 需要在倒计时50秒内刷新凭证
|
|
62
|
-
*/
|
|
61
|
+
/** 凭证有效时间,单位:秒 需要在倒计时50秒内刷新凭证 */
|
|
63
62
|
expires_in: string;
|
|
64
|
-
/**
|
|
65
|
-
* 调用凭证
|
|
66
|
-
*/
|
|
63
|
+
/** 调用凭证 */
|
|
67
64
|
access_token: string;
|
|
68
65
|
}>;
|
|
69
66
|
/**
|
package/lib/core/api.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import got from 'got';
|
|
2
2
|
import WebSocket from 'ws';
|
|
3
|
+
import EventEmitter from 'events';
|
|
3
4
|
import { Intents } from './intents.js';
|
|
4
5
|
import { common, logger } from 'node-karin';
|
|
5
|
-
export class QQBotApi {
|
|
6
|
+
export class QQBotApi extends EventEmitter {
|
|
6
7
|
/** 开发者的appId */
|
|
7
8
|
appId;
|
|
8
9
|
/** Bot头像 */
|
|
@@ -29,6 +30,7 @@ export class QQBotApi {
|
|
|
29
30
|
host;
|
|
30
31
|
#config;
|
|
31
32
|
constructor(config) {
|
|
33
|
+
super();
|
|
32
34
|
this.#config = config;
|
|
33
35
|
this.appId = String(this.#config.appId);
|
|
34
36
|
this.avatar = '';
|
|
@@ -78,7 +80,6 @@ export class QQBotApi {
|
|
|
78
80
|
const time = Number(expires_in) * 1000 - 50000;
|
|
79
81
|
setTimeout(async () => {
|
|
80
82
|
this.getAccessToken(true);
|
|
81
|
-
/** 重新鉴权 */
|
|
82
83
|
}, time);
|
|
83
84
|
return data;
|
|
84
85
|
}
|
|
@@ -210,17 +211,17 @@ export class QQBotApi {
|
|
|
210
211
|
const info = await this.getBotInfo();
|
|
211
212
|
this.avatar = info.avatar;
|
|
212
213
|
this.nick = data.d.user.username;
|
|
213
|
-
this.
|
|
214
|
+
this.emit('start');
|
|
214
215
|
break;
|
|
215
216
|
}
|
|
216
217
|
case "GROUP_AT_MESSAGE_CREATE" /* EventType.GROUP_AT_MESSAGE_CREATE */: {
|
|
217
218
|
this.heartbeat.d = data.s;
|
|
218
|
-
this.
|
|
219
|
+
this.emit("GROUP_AT_MESSAGE_CREATE" /* EventType.GROUP_AT_MESSAGE_CREATE */, data);
|
|
219
220
|
break;
|
|
220
221
|
}
|
|
221
222
|
case "C2C_MESSAGE_CREATE" /* EventType.C2C_MESSAGE_CREATE */: {
|
|
222
223
|
this.heartbeat.d = data.s;
|
|
223
|
-
this.
|
|
224
|
+
this.emit("C2C_MESSAGE_CREATE" /* EventType.C2C_MESSAGE_CREATE */, data);
|
|
224
225
|
break;
|
|
225
226
|
}
|
|
226
227
|
// case 'GUILD_CREATE':
|
package/lib/core/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { QQBotApi } from './api.js';
|
|
2
2
|
import { markdownTemplate, markdownRaw } from './markdown.js';
|
|
3
3
|
import { common, common as Common, config as Config, } from '../utils/index.js';
|
|
4
|
-
import { logger,
|
|
4
|
+
import { logger, karin, segment, KarinMessage, } from 'node-karin';
|
|
5
5
|
/**
|
|
6
6
|
* - QQBot适配器
|
|
7
7
|
*/
|
|
@@ -47,7 +47,7 @@ export class AdapterQQBot {
|
|
|
47
47
|
await this.super.getAccessToken();
|
|
48
48
|
await this.super.getWssUrl();
|
|
49
49
|
this.super.createWss();
|
|
50
|
-
this.super.
|
|
50
|
+
this.super.on("GROUP_AT_MESSAGE_CREATE" /* QQBotEventType.GROUP_AT_MESSAGE_CREATE */, (data) => {
|
|
51
51
|
const user_id = data.d.author.id;
|
|
52
52
|
const group_id = data.d.group_id;
|
|
53
53
|
const time = new Date(data.d.timestamp).getTime();
|
|
@@ -79,9 +79,9 @@ export class AdapterQQBot {
|
|
|
79
79
|
const e = new KarinMessage(message);
|
|
80
80
|
e.bot = this;
|
|
81
81
|
e.replyCallback = async (elements) => await this._sendNsg(elements, "groups" /* PathType.Groups */, e.contact.peer, e.message_id);
|
|
82
|
-
|
|
82
|
+
karin.emit('adapter.message', e);
|
|
83
83
|
});
|
|
84
|
-
this.super.
|
|
84
|
+
this.super.on("C2C_MESSAGE_CREATE" /* QQBotEventType.C2C_MESSAGE_CREATE */, (data) => {
|
|
85
85
|
const user_id = data.d.author.user_openid;
|
|
86
86
|
const time = new Date(data.d.timestamp).getTime();
|
|
87
87
|
const message = {
|
|
@@ -112,14 +112,14 @@ export class AdapterQQBot {
|
|
|
112
112
|
const e = new KarinMessage(message);
|
|
113
113
|
e.bot = this;
|
|
114
114
|
e.replyCallback = async (elements) => await this._sendNsg(elements, "users" /* PathType.Friends */, e.contact.peer, e.message_id);
|
|
115
|
-
|
|
115
|
+
karin.emit('adapter.message', e);
|
|
116
116
|
});
|
|
117
117
|
/** 等待建立连接 注册Bot */
|
|
118
|
-
this.super.
|
|
118
|
+
this.super.on('start', () => {
|
|
119
119
|
this.account.name = this.super.nick;
|
|
120
120
|
this.logger('info', `建立连接成功: ${this.account.name}`);
|
|
121
121
|
/** 注册bot */
|
|
122
|
-
const index =
|
|
122
|
+
const index = karin.addBot({ type: this.adapter.type, bot: this });
|
|
123
123
|
if (index)
|
|
124
124
|
this.adapter.index = index;
|
|
125
125
|
});
|
|
@@ -163,11 +163,12 @@ export class AdapterQQBot {
|
|
|
163
163
|
elements.push(segment.face(Number(Match[1])));
|
|
164
164
|
}
|
|
165
165
|
else {
|
|
166
|
-
const
|
|
167
|
-
for (const
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
166
|
+
const { regex } = Config.getBotConfig(this.account.uid) || { regex: [] };
|
|
167
|
+
for (const r of regex) {
|
|
168
|
+
const reg = r.reg;
|
|
169
|
+
if (typeof reg !== 'string')
|
|
170
|
+
continue;
|
|
171
|
+
v = v.replace(reg, r.rep);
|
|
171
172
|
}
|
|
172
173
|
elements.push(segment.text(v));
|
|
173
174
|
}
|
package/lib/core/markdown.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import path from 'path';
|
|
2
2
|
import { common, common as Common } from '../utils/common.js';
|
|
3
|
-
import { handler, common as karinCommon, } from 'node-karin';
|
|
3
|
+
import { handler, common as karinCommon, segment, } from 'node-karin';
|
|
4
4
|
/**
|
|
5
5
|
* 图文模板
|
|
6
6
|
*/
|
|
@@ -26,8 +26,9 @@ export async function markdownTemplate(Opt) {
|
|
|
26
26
|
const textFn = async () => {
|
|
27
27
|
text.sort((a, b) => a.index - b.index);
|
|
28
28
|
const data = Common.getQQBotButton(text.map(v => v.data.text).join(''));
|
|
29
|
+
const val = type === "users" /* PathType.Friends */ ? Common.formatText(data.text, true) : Common.formatText(data.text);
|
|
29
30
|
/** 去除at全体 */
|
|
30
|
-
params.push({ key: bot.markdown.oldTemplate.textStartKey, values: [
|
|
31
|
+
params.push({ key: bot.markdown.oldTemplate.textStartKey, values: [val] });
|
|
31
32
|
/** 按钮 */
|
|
32
33
|
buttons.push(...data.data);
|
|
33
34
|
};
|
|
@@ -50,6 +51,12 @@ export async function markdownTemplate(Opt) {
|
|
|
50
51
|
case 'image':
|
|
51
52
|
image.push({ index, data });
|
|
52
53
|
break;
|
|
54
|
+
case 'at': {
|
|
55
|
+
if (type === "users" /* PathType.Friends */)
|
|
56
|
+
break;
|
|
57
|
+
text.push({ index, data: segment.text(`<qqbot-at-user id="${data.uid || data.uin}" />`) });
|
|
58
|
+
break;
|
|
59
|
+
}
|
|
53
60
|
case 'record': {
|
|
54
61
|
const file = await common.voiceToSilk(data.file);
|
|
55
62
|
list.push(mediaFn(file, type, '0.silk', 3 /* FileType.Record */));
|
|
@@ -176,12 +183,19 @@ export async function markdownRaw(Opt) {
|
|
|
176
183
|
/** 先提取掉url 随后放出按钮中 */
|
|
177
184
|
const res = Common.getQQBotButton(data.text);
|
|
178
185
|
buttons.push(...res.data);
|
|
179
|
-
|
|
186
|
+
const text = type === "users" /* PathType.Friends */ ? Common.formatText(res.text, true) : Common.formatText(res.text);
|
|
187
|
+
message.push({ index, data: text });
|
|
180
188
|
break;
|
|
181
189
|
}
|
|
182
190
|
case 'image':
|
|
183
191
|
imageFn(index, data);
|
|
184
192
|
break;
|
|
193
|
+
case 'at': {
|
|
194
|
+
if (type === "users" /* PathType.Friends */)
|
|
195
|
+
break;
|
|
196
|
+
message.push({ index, data: `<qqbot-at-user id="${data.uid || data.uin}" />` });
|
|
197
|
+
break;
|
|
198
|
+
}
|
|
185
199
|
case 'record': {
|
|
186
200
|
const file = await common.voiceToSilk(data.file);
|
|
187
201
|
list.push(mediaFn(file, type, '0.silk', 3 /* FileType.Record */));
|
package/lib/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import './core/index.js';
|
|
2
|
+
import Jimp from 'jimp';
|
|
2
3
|
import { logger, common } from 'node-karin';
|
|
3
4
|
import { basename, dirPath } from './utils/dir.js';
|
|
4
|
-
import Jimp from 'jimp';
|
|
5
5
|
const pkg = common.readJson(dirPath + '/package.json');
|
|
6
6
|
logger.info(`${logger.violet(`[插件:${pkg.version}]`)} ${logger.green(basename)} 初始化完成~`);
|
|
7
7
|
export default Jimp;
|
package/lib/utils/common.d.ts
CHANGED
|
@@ -54,6 +54,13 @@ declare class Common {
|
|
|
54
54
|
text: string;
|
|
55
55
|
data: ButtonElement[];
|
|
56
56
|
};
|
|
57
|
+
/**
|
|
58
|
+
* 传入文本 将文本一些特殊字符转义去除 用于处理markdown
|
|
59
|
+
* @param text - 文本
|
|
60
|
+
* @param isC2C - 是否是C2C
|
|
61
|
+
* @returns 处理后的文本
|
|
62
|
+
*/
|
|
63
|
+
formatText(text: string, isC2C?: boolean): string;
|
|
57
64
|
}
|
|
58
65
|
export declare const common: Common;
|
|
59
66
|
export {};
|
package/lib/utils/common.js
CHANGED
|
@@ -194,5 +194,17 @@ class Common {
|
|
|
194
194
|
data,
|
|
195
195
|
};
|
|
196
196
|
}
|
|
197
|
+
/**
|
|
198
|
+
* 传入文本 将文本一些特殊字符转义去除 用于处理markdown
|
|
199
|
+
* @param text - 文本
|
|
200
|
+
* @param isC2C - 是否是C2C
|
|
201
|
+
* @returns 处理后的文本
|
|
202
|
+
*/
|
|
203
|
+
formatText(text, isC2C = false) {
|
|
204
|
+
text = text.replace(/everyone/g, '').replace(/\n/g, '\r');
|
|
205
|
+
if (isC2C)
|
|
206
|
+
text = text.replace(/<qqbot-at-user id=".+" \/>/gm, '').replace(/<@.+>/gm, '');
|
|
207
|
+
return text;
|
|
208
|
+
}
|
|
197
209
|
}
|
|
198
210
|
export const common = new Common();
|
package/lib/utils/config.d.ts
CHANGED
package/lib/utils/config.js
CHANGED
|
@@ -107,12 +107,24 @@ class Cfg {
|
|
|
107
107
|
const botCfg = allCfg.accounts[appID];
|
|
108
108
|
/** 全局默认配置 */
|
|
109
109
|
const defCfg = allCfg.default;
|
|
110
|
-
|
|
110
|
+
/** 对regex进行处理 */
|
|
111
|
+
const regex = Array.isArray(botCfg.regex) ? botCfg.regex : defCfg.regex;
|
|
112
|
+
/** 对表达式进行new RegExp处理 */
|
|
113
|
+
const regexData = regex.map(({ reg, rep }) => {
|
|
114
|
+
return {
|
|
115
|
+
reg: reg instanceof RegExp ? reg : new RegExp(reg),
|
|
116
|
+
rep,
|
|
117
|
+
};
|
|
118
|
+
});
|
|
119
|
+
const data = {
|
|
111
120
|
...defCfg,
|
|
112
121
|
...botCfg,
|
|
113
122
|
sendMode: Number(botCfg.sendMode) || defCfg.sendMode,
|
|
114
|
-
regex:
|
|
123
|
+
regex: regexData,
|
|
115
124
|
};
|
|
125
|
+
/** 缓存 */
|
|
126
|
+
this.change.set(key, data);
|
|
127
|
+
return data;
|
|
116
128
|
}
|
|
117
129
|
/**
|
|
118
130
|
* package
|
|
@@ -153,18 +165,6 @@ class Cfg {
|
|
|
153
165
|
watcher.on('change', () => {
|
|
154
166
|
this.change.delete(key);
|
|
155
167
|
logger.mark(`[修改配置文件][${type}][${name}]`);
|
|
156
|
-
/** 文件修改后调用对应的方法 请自行使用 */
|
|
157
|
-
// switch (`change_${name}`) {
|
|
158
|
-
// case 'change_App':
|
|
159
|
-
// this.change_App()
|
|
160
|
-
// break
|
|
161
|
-
// case 'change_config':
|
|
162
|
-
// this.change_config()
|
|
163
|
-
// break
|
|
164
|
-
// case 'change_group':
|
|
165
|
-
// this.change_group()
|
|
166
|
-
// break
|
|
167
|
-
// }
|
|
168
168
|
});
|
|
169
169
|
/** 缓存 防止重复监听 */
|
|
170
170
|
this.watcher.set(key, watcher);
|