@alemonjs/qq-bot 0.0.18 → 0.0.20
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 +6 -10
- package/lib/hook.d.ts +10 -0
- package/lib/hook.js +35 -0
- package/lib/index.d.ts +4 -2
- package/lib/index.group.js +7 -204
- package/lib/index.guild.js +23 -298
- package/lib/index.js +41 -403
- package/lib/index.webhook.js +26 -0
- package/lib/register.d.ts +3 -0
- package/lib/register.js +405 -0
- package/lib/sdk/api.d.ts +5 -10
- package/lib/sdk/api.js +5 -10
- package/lib/sdk/{websoket.group.js → client.websoket.group.js} +1 -1
- package/lib/sdk/{websoket.guild.js → client.websoket.guild.js} +11 -9
- package/lib/sdk/client.websoket.js +221 -0
- package/lib/sdk/intents.js +12 -23
- package/lib/send/index.js +18 -18
- package/package.json +1 -1
- package/lib/api.d.ts +0 -975
- package/lib/api.js +0 -1188
- package/lib/client.d.ts +0 -26
- package/lib/client.js +0 -212
- package/lib/config.js +0 -3
- package/lib/from.js +0 -37
- package/lib/message/AT_MESSAGE_CREATE.d.ts +0 -37
- package/lib/message/C2C_MESSAGE_CREATE.d.ts +0 -11
- package/lib/message/CHANNEL_CREATE.d.ts +0 -17
- package/lib/message/CHANNEL_DELETE.d.ts +0 -22
- package/lib/message/CHANNEL_UPDATE.d.ts +0 -22
- package/lib/message/DIRECT_MESSAGE_CREATE.d.ts +0 -36
- package/lib/message/DIRECT_MESSAGE_DELETE.d.ts +0 -24
- package/lib/message/ERROR.d.ts +0 -3
- package/lib/message/GROUP_AT_MESSAGE_CREATE.d.ts +0 -16
- package/lib/message/GUILD_CREATE.d.ts +0 -22
- package/lib/message/GUILD_DELETE.d.ts +0 -22
- package/lib/message/GUILD_MEMBER_ADD.d.ts +0 -21
- package/lib/message/GUILD_MEMBER_REMOVE.d.ts +0 -21
- package/lib/message/GUILD_MEMBER_UPDATE.d.ts +0 -21
- package/lib/message/GUILD_UPDATE.d.ts +0 -22
- package/lib/message/INTERACTION_CREATE.d.ts +0 -8
- package/lib/message/MESSAGE_CREATE.d.ts +0 -11
- package/lib/message/MESSAGE_DELETE.d.ts +0 -11
- package/lib/message/MESSAGE_REACTION_ADD.d.ts +0 -15
- package/lib/message/MESSAGE_REACTION_REMOVE.d.ts +0 -15
- package/lib/message/PUBLIC_MESSAGE_DELETE.d.ts +0 -21
- package/lib/message/READY.d.ts +0 -11
- package/lib/message.d.ts +0 -49
- package/lib/typing.d.ts +0 -73
- package/lib/webhook.js +0 -51
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import WebSocket from 'ws';
|
|
2
|
+
import { QQBotAPI } from './api.js';
|
|
3
|
+
import { config } from './config.js';
|
|
4
|
+
import { getIntentsMask } from './intents.js';
|
|
5
|
+
import { Counter } from './counter.js';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* 连接
|
|
9
|
+
*/
|
|
10
|
+
class QQBotClients extends QQBotAPI {
|
|
11
|
+
//
|
|
12
|
+
#counter = new Counter(1); // 初始值为1
|
|
13
|
+
// 标记是否已连接
|
|
14
|
+
#isConnected = false;
|
|
15
|
+
// 存储最新的消息序号
|
|
16
|
+
#heartbeat_interval = 30000;
|
|
17
|
+
// 鉴权
|
|
18
|
+
#IntervalId = null;
|
|
19
|
+
// url
|
|
20
|
+
#gatewayUrl = null;
|
|
21
|
+
/**
|
|
22
|
+
* 设置配置
|
|
23
|
+
* @param opstion
|
|
24
|
+
*/
|
|
25
|
+
constructor(opstion) {
|
|
26
|
+
super();
|
|
27
|
+
for (const key in opstion) {
|
|
28
|
+
config.set(key, opstion[key]);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* 定时鉴权
|
|
33
|
+
* @param cfg
|
|
34
|
+
* @returns
|
|
35
|
+
*/
|
|
36
|
+
async #setTimeoutBotConfig() {
|
|
37
|
+
const accessToken = async () => {
|
|
38
|
+
const app_id = config.get('app_id');
|
|
39
|
+
const secret = config.get('secret');
|
|
40
|
+
if (!app_id || !secret)
|
|
41
|
+
return;
|
|
42
|
+
// 发送请求
|
|
43
|
+
const data = await this.getAuthentication(app_id, secret).then(res => res.data);
|
|
44
|
+
config.set('access_token', data.access_token);
|
|
45
|
+
console.info('refresh', data.expires_in, 's');
|
|
46
|
+
setTimeout(accessToken, data.expires_in * 1000);
|
|
47
|
+
};
|
|
48
|
+
await accessToken();
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* 鉴权数据
|
|
53
|
+
* @returns
|
|
54
|
+
*/
|
|
55
|
+
#aut() {
|
|
56
|
+
const token = config.get('access_token');
|
|
57
|
+
const intents = config.get('intents');
|
|
58
|
+
const shard = config.get('shard');
|
|
59
|
+
return {
|
|
60
|
+
op: 2, // op = 2
|
|
61
|
+
d: {
|
|
62
|
+
token: `QQBot ${token}`,
|
|
63
|
+
intents: getIntentsMask(intents),
|
|
64
|
+
shard: shard,
|
|
65
|
+
properties: {
|
|
66
|
+
$os: process.platform,
|
|
67
|
+
$browser: 'alemonjs',
|
|
68
|
+
$device: 'alemonjs'
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
#ws = null;
|
|
74
|
+
#events = {};
|
|
75
|
+
/**
|
|
76
|
+
* 注册事件处理程序
|
|
77
|
+
* @param key 事件名称
|
|
78
|
+
* @param val 事件处理函数
|
|
79
|
+
*/
|
|
80
|
+
on(key, val) {
|
|
81
|
+
if (!this.#events[key])
|
|
82
|
+
this.#events[key] = [];
|
|
83
|
+
this.#events[key].push(val);
|
|
84
|
+
return this;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
*
|
|
88
|
+
* @param cfg
|
|
89
|
+
* @param conversation
|
|
90
|
+
*/
|
|
91
|
+
async connect(gatewayURL) {
|
|
92
|
+
// 定时模式
|
|
93
|
+
await this.#setTimeoutBotConfig();
|
|
94
|
+
// 请求url
|
|
95
|
+
if (!this.#gatewayUrl) {
|
|
96
|
+
this.#gatewayUrl = gatewayURL ?? (await this.gateway().then(res => res?.url));
|
|
97
|
+
}
|
|
98
|
+
if (!this.#gatewayUrl)
|
|
99
|
+
return;
|
|
100
|
+
// 重新连接的逻辑
|
|
101
|
+
const reconnect = async () => {
|
|
102
|
+
if (this.#counter.get() >= 5) {
|
|
103
|
+
console.info('The maximum number of reconnections has been reached, cancel reconnection');
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
setTimeout(() => {
|
|
107
|
+
console.info('[ws] reconnecting...');
|
|
108
|
+
// 重新starrt
|
|
109
|
+
start();
|
|
110
|
+
// 记录
|
|
111
|
+
this.#counter.getNextId();
|
|
112
|
+
}, 5000);
|
|
113
|
+
};
|
|
114
|
+
const start = () => {
|
|
115
|
+
if (this.#gatewayUrl) {
|
|
116
|
+
const map = {
|
|
117
|
+
0: async ({ t, d }) => {
|
|
118
|
+
if (this.#events[t]) {
|
|
119
|
+
try {
|
|
120
|
+
for (const event of this.#events[t]) {
|
|
121
|
+
// 是否是函数
|
|
122
|
+
if (typeof event != 'function')
|
|
123
|
+
continue;
|
|
124
|
+
event(d);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
catch (err) {
|
|
128
|
+
if (this.#events['ERROR']) {
|
|
129
|
+
for (const event of this.#events['ERROR']) {
|
|
130
|
+
// 是否是函数
|
|
131
|
+
if (typeof event != 'function')
|
|
132
|
+
continue;
|
|
133
|
+
event(err);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
// Ready Event,鉴权成功
|
|
139
|
+
if (t === 'READY') {
|
|
140
|
+
this.#IntervalId = setInterval(() => {
|
|
141
|
+
if (this.#isConnected) {
|
|
142
|
+
this.#ws &&
|
|
143
|
+
this.#ws.send(JSON.stringify({
|
|
144
|
+
op: 1, // op = 1
|
|
145
|
+
d: null // 如果是第一次连接,传null
|
|
146
|
+
}));
|
|
147
|
+
}
|
|
148
|
+
}, this.#heartbeat_interval);
|
|
149
|
+
}
|
|
150
|
+
// Resumed Event,恢复连接成功
|
|
151
|
+
if (t === 'RESUMED') {
|
|
152
|
+
console.info('[ws] restore connection');
|
|
153
|
+
// 重制次数
|
|
154
|
+
this.#counter.reStart();
|
|
155
|
+
}
|
|
156
|
+
return;
|
|
157
|
+
},
|
|
158
|
+
6: ({ d }) => {
|
|
159
|
+
console.info('[ws] connection attempt', d);
|
|
160
|
+
return;
|
|
161
|
+
},
|
|
162
|
+
7: async ({ d }) => {
|
|
163
|
+
// 执行重新连接
|
|
164
|
+
console.info('[ws] reconnect', d);
|
|
165
|
+
// 取消鉴权发送
|
|
166
|
+
if (this.#IntervalId)
|
|
167
|
+
clearInterval(this.#IntervalId);
|
|
168
|
+
return;
|
|
169
|
+
},
|
|
170
|
+
9: ({ d }) => {
|
|
171
|
+
console.info('[ws] parameter error', d);
|
|
172
|
+
return;
|
|
173
|
+
},
|
|
174
|
+
10: ({ d }) => {
|
|
175
|
+
// 重制次数
|
|
176
|
+
this.#isConnected = true;
|
|
177
|
+
// 记录新循环
|
|
178
|
+
this.#heartbeat_interval = d.heartbeat_interval;
|
|
179
|
+
// 发送鉴权
|
|
180
|
+
this.#ws && this.#ws.send(JSON.stringify(this.#aut()));
|
|
181
|
+
return;
|
|
182
|
+
},
|
|
183
|
+
11: () => {
|
|
184
|
+
// OpCode 11 Heartbeat ACK 消息,心跳发送成功
|
|
185
|
+
console.info('[ws] heartbeat transmission');
|
|
186
|
+
// 重制次数
|
|
187
|
+
this.#counter.reStart();
|
|
188
|
+
return;
|
|
189
|
+
},
|
|
190
|
+
12: ({ d }) => {
|
|
191
|
+
console.info('[ws] platform data', d);
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
};
|
|
195
|
+
// 连接
|
|
196
|
+
this.#ws = new WebSocket(this.#gatewayUrl);
|
|
197
|
+
this.#ws.on('open', () => {
|
|
198
|
+
console.info('[ws] open');
|
|
199
|
+
});
|
|
200
|
+
// 监听消息
|
|
201
|
+
this.#ws.on('message', async (msg) => {
|
|
202
|
+
const message = JSON.parse(msg.toString('utf8'));
|
|
203
|
+
if (process.env.NTQQ_WS == 'dev')
|
|
204
|
+
console.info('message', message);
|
|
205
|
+
// 根据 opcode 进行处理
|
|
206
|
+
if (map[message.op]) {
|
|
207
|
+
map[message.op](message);
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
// 关闭
|
|
211
|
+
this.#ws.on('close', async (err) => {
|
|
212
|
+
await reconnect();
|
|
213
|
+
console.info('[ws] close', err);
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
};
|
|
217
|
+
start();
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
export { QQBotClients };
|
package/lib/sdk/intents.js
CHANGED
|
@@ -71,29 +71,18 @@ PUBLIC_GUILD_MESSAGES (1 << 30) // 消息事件,此为公域的消息事件
|
|
|
71
71
|
* 订阅事件集合
|
|
72
72
|
*/
|
|
73
73
|
const intentsMap = {
|
|
74
|
-
GUILDS: 1 << 0,
|
|
75
|
-
GUILD_MEMBERS: 1 << 1,
|
|
76
|
-
GUILD_MESSAGES: 1 << 9,
|
|
77
|
-
GUILD_MESSAGE_REACTIONS: 1 << 10,
|
|
78
|
-
DIRECT_MESSAGE: 1 << 12,
|
|
79
|
-
INTERACTION: 1 << 26,
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
// group
|
|
86
|
-
GROUP_AND_C2C_EVENT: 1 << 25,
|
|
87
|
-
C2C_MESSAGE_CREATE: 1 << 25,
|
|
88
|
-
FRIEND_ADD: 1 << 25,
|
|
89
|
-
FRIEND_DEL: 1 << 25,
|
|
90
|
-
C2C_MSG_REJECT: 1 << 25,
|
|
91
|
-
C2C_MSG_RECEIVE: 1 << 25,
|
|
92
|
-
GROUP_AT_MESSAGE_CREATE: 1 << 25,
|
|
93
|
-
GROUP_ADD_ROBOT: 1 << 25,
|
|
94
|
-
GROUP_DEL_ROBOT: 1 << 25,
|
|
95
|
-
GROUP_MSG_REJECT: 1 << 25,
|
|
96
|
-
GROUP_MSG_RECEIVE: 1 << 25
|
|
74
|
+
GUILDS: 1 << 0, // 频道事件
|
|
75
|
+
GUILD_MEMBERS: 1 << 1, // 成员
|
|
76
|
+
GUILD_MESSAGES: 1 << 9, // 消息事件,仅 *私域*
|
|
77
|
+
GUILD_MESSAGE_REACTIONS: 1 << 10, // 消息表情表态
|
|
78
|
+
DIRECT_MESSAGE: 1 << 12, // 私信消息
|
|
79
|
+
INTERACTION: 1 << 26, // 互动事件
|
|
80
|
+
// INTERACTION_CREATE: 1 << 26,
|
|
81
|
+
MESSAGE_AUDIT: 1 << 27, // 消息审核
|
|
82
|
+
FORUMS_EVENT: 1 << 28, // 论坛事件,仅 *私域*
|
|
83
|
+
AUDIO_ACTION: 1 << 29, // 音频
|
|
84
|
+
PUBLIC_GUILD_MESSAGES: 1 << 30, // 消息事件,此为公域的消息事件
|
|
85
|
+
GROUP_AND_C2C_EVENT: 1 << 25, // group all
|
|
97
86
|
};
|
|
98
87
|
/**
|
|
99
88
|
*
|
package/lib/send/index.js
CHANGED
|
@@ -12,27 +12,27 @@ const createButtonsData = (rows) => {
|
|
|
12
12
|
const options = button.options;
|
|
13
13
|
id++;
|
|
14
14
|
return {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
id: String(id),
|
|
16
|
+
render_data: {
|
|
17
|
+
label: typeof value == 'object' ? value.title : value,
|
|
18
|
+
visited_label: typeof value == 'object' ? value.label : value,
|
|
19
19
|
// tudo
|
|
20
|
-
|
|
20
|
+
style: 0
|
|
21
21
|
},
|
|
22
|
-
|
|
23
|
-
// 0 link 1 callback , 2 command
|
|
24
|
-
|
|
25
|
-
|
|
22
|
+
action: {
|
|
23
|
+
// 0 link 1 callback , 2 command
|
|
24
|
+
type: typeof options.data === 'object' ? 1 : options?.isLink ? 0 : 2,
|
|
25
|
+
permission: {
|
|
26
26
|
// 所有人
|
|
27
|
-
|
|
27
|
+
type: 2
|
|
28
28
|
// "specify_role_ids": ["1", "2", "3"]
|
|
29
29
|
},
|
|
30
30
|
// "click_limit": 10,
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
unsupport_tips: options?.toolTip ?? '',
|
|
32
|
+
data: options?.data ?? '',
|
|
33
33
|
// reply: true,
|
|
34
|
-
|
|
35
|
-
|
|
34
|
+
at_bot_show_channel_list: options.showList ?? false,
|
|
35
|
+
enter: options?.autoEnter ?? false
|
|
36
36
|
}
|
|
37
37
|
};
|
|
38
38
|
})
|
|
@@ -47,7 +47,7 @@ const GROUP_AT_MESSAGE_CREATE = (client, event, val) => {
|
|
|
47
47
|
.map(item => {
|
|
48
48
|
// if (item.type == 'Link') {
|
|
49
49
|
// return `[${item.options?.title ?? item.value}](${item.value})`
|
|
50
|
-
// } else
|
|
50
|
+
// } else
|
|
51
51
|
if (item.type == 'Mention') {
|
|
52
52
|
if (item.value == 'everyone' ||
|
|
53
53
|
item.value == 'all' ||
|
|
@@ -126,7 +126,7 @@ const GROUP_AT_MESSAGE_CREATE = (client, event, val) => {
|
|
|
126
126
|
});
|
|
127
127
|
}
|
|
128
128
|
const rows = item.value;
|
|
129
|
-
// 构造成按钮
|
|
129
|
+
// 构造成按钮
|
|
130
130
|
const data = createButtonsData(rows);
|
|
131
131
|
return client.groupOpenMessages(event.GuildId, {
|
|
132
132
|
content: '',
|
|
@@ -216,7 +216,7 @@ const C2C_MESSAGE_CREATE = (client, event, val) => {
|
|
|
216
216
|
rows.map(row => {
|
|
217
217
|
return row;
|
|
218
218
|
});
|
|
219
|
-
// 构造成按钮
|
|
219
|
+
// 构造成按钮
|
|
220
220
|
const data = createButtonsData(rows);
|
|
221
221
|
return client.groupOpenMessages(event.GuildId, {
|
|
222
222
|
content: '',
|
|
@@ -284,7 +284,7 @@ const AT_MESSAGE_CREATE = (client, event, val) => {
|
|
|
284
284
|
.map(item => {
|
|
285
285
|
// if (item.type == 'Link') {
|
|
286
286
|
// return `[${item.options?.title ?? item.value}](${item.value})`
|
|
287
|
-
// } else
|
|
287
|
+
// } else
|
|
288
288
|
if (item.type == 'Mention') {
|
|
289
289
|
if (item.value == 'everyone' ||
|
|
290
290
|
item.value == 'all' ||
|