@zhin.js/adapter-qq 1.0.84 → 1.1.2

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.
Files changed (107) hide show
  1. package/CHANGELOG.md +940 -17
  2. package/PERMITS.md +25 -0
  3. package/README.md +135 -233
  4. package/adapters/qq/index.js +50 -0
  5. package/adapters/qq/index.ts +71 -0
  6. package/agents/qq/agent.json +20 -0
  7. package/agents/qq/boundaries.md +3 -0
  8. package/agents/qq/conventions.md +3 -0
  9. package/agents/qq/skills/qq/SKILL.md +22 -0
  10. package/agents/qq/skills/qq/tools/add_role/index.js +21 -0
  11. package/agents/qq/skills/qq/tools/add_role/index.ts +21 -0
  12. package/agents/qq/skills/qq/tools/channel_info/index.js +17 -0
  13. package/agents/qq/skills/qq/tools/channel_info/index.ts +17 -0
  14. package/agents/qq/skills/qq/tools/create_role/index.js +20 -0
  15. package/agents/qq/skills/qq/tools/create_role/index.ts +20 -0
  16. package/agents/qq/skills/qq/tools/list_channels/index.js +18 -0
  17. package/agents/qq/skills/qq/tools/list_channels/index.ts +18 -0
  18. package/agents/qq/skills/qq/tools/list_guilds/index.js +14 -0
  19. package/agents/qq/skills/qq/tools/list_guilds/index.ts +14 -0
  20. package/agents/qq/skills/qq/tools/list_roles/index.js +18 -0
  21. package/agents/qq/skills/qq/tools/list_roles/index.ts +18 -0
  22. package/agents/qq/skills/qq/tools/member_detail/index.js +18 -0
  23. package/agents/qq/skills/qq/tools/member_detail/index.ts +18 -0
  24. package/agents/qq/skills/qq/tools/remove_role/index.js +21 -0
  25. package/agents/qq/skills/qq/tools/remove_role/index.ts +21 -0
  26. package/agents/qq/system.md +3 -0
  27. package/commands/qq/endpoint/add/[[id]]/index.js +3 -0
  28. package/commands/qq/endpoint/add/[[id]]/index.ts +3 -0
  29. package/commands/qq/endpoint/cancel/index.js +11 -0
  30. package/commands/qq/endpoint/cancel/index.ts +15 -0
  31. package/commands/qq/endpoint/definition.js +188 -0
  32. package/commands/qq/endpoint/definition.ts +263 -0
  33. package/commands/qq/endpoint/list/index.js +3 -0
  34. package/commands/qq/endpoint/list/index.ts +3 -0
  35. package/commands/qq/endpoint/remove/[id]/index.js +3 -0
  36. package/commands/qq/endpoint/remove/[id]/index.ts +3 -0
  37. package/lib/client.d.ts +12 -0
  38. package/lib/client.js +2 -0
  39. package/lib/endpoint.d.ts +56 -0
  40. package/lib/endpoint.js +456 -0
  41. package/lib/index.d.ts +8 -18
  42. package/lib/index.js +8 -338
  43. package/lib/outbound.d.ts +17 -0
  44. package/lib/outbound.js +234 -0
  45. package/lib/platform-permit.d.ts +15 -0
  46. package/lib/platform-permit.js +41 -0
  47. package/lib/protocol.d.ts +90 -0
  48. package/lib/protocol.js +161 -0
  49. package/lib/qq-bind-api.d.ts +36 -0
  50. package/lib/qq-bind-api.js +89 -0
  51. package/lib/qq-bind-flow.d.ts +19 -0
  52. package/lib/qq-bind-flow.js +85 -0
  53. package/lib/qq-bot-kind-prompt.d.ts +9 -0
  54. package/lib/qq-bot-kind-prompt.js +37 -0
  55. package/lib/qq-intents.d.ts +27 -0
  56. package/lib/qq-intents.js +51 -0
  57. package/lib/qq-runtime-state.d.ts +30 -0
  58. package/lib/qq-runtime-state.js +14 -0
  59. package/lib/side-event-dispatch.d.ts +10 -0
  60. package/lib/side-event-dispatch.js +114 -0
  61. package/lib/webhook.d.ts +18 -0
  62. package/lib/webhook.js +103 -0
  63. package/lib/ws.d.ts +55 -0
  64. package/lib/ws.js +234 -0
  65. package/middlewares/bot-kind-reply/index.js +47 -0
  66. package/middlewares/bot-kind-reply/index.ts +65 -0
  67. package/package.json +82 -29
  68. package/plugin.js +18 -0
  69. package/schema.json +158 -0
  70. package/src/client.ts +16 -0
  71. package/src/endpoint.ts +534 -0
  72. package/src/index.ts +66 -326
  73. package/src/outbound.ts +255 -0
  74. package/src/platform-permit.ts +56 -0
  75. package/src/protocol.ts +249 -0
  76. package/src/qq-bind-api.ts +145 -0
  77. package/src/qq-bind-flow.ts +127 -0
  78. package/src/qq-bot-kind-prompt.ts +47 -0
  79. package/src/qq-intents.ts +77 -0
  80. package/src/qq-runtime-state.ts +51 -0
  81. package/src/side-event-dispatch.ts +140 -0
  82. package/src/webhook.ts +132 -0
  83. package/src/ws.ts +331 -0
  84. package/client/Dashboard.tsx +0 -230
  85. package/client/index.tsx +0 -11
  86. package/client/tsconfig.json +0 -7
  87. package/client/utils/api.ts +0 -17
  88. package/dist/index.js +0 -30
  89. package/lib/adapter.d.ts +0 -17
  90. package/lib/adapter.d.ts.map +0 -1
  91. package/lib/adapter.js +0 -49
  92. package/lib/adapter.js.map +0 -1
  93. package/lib/bot.d.ts +0 -102
  94. package/lib/bot.d.ts.map +0 -1
  95. package/lib/bot.js +0 -337
  96. package/lib/bot.js.map +0 -1
  97. package/lib/index.d.ts.map +0 -1
  98. package/lib/index.js.map +0 -1
  99. package/lib/types.d.ts +0 -16
  100. package/lib/types.d.ts.map +0 -1
  101. package/lib/types.js +0 -2
  102. package/lib/types.js.map +0 -1
  103. package/plugin.yml +0 -3
  104. package/skills/qq/SKILL.md +0 -97
  105. package/src/adapter.ts +0 -58
  106. package/src/bot.ts +0 -347
  107. package/src/types.ts +0 -24
package/src/bot.ts DELETED
@@ -1,347 +0,0 @@
1
- /**
2
- * QQ 官方 Bot 实现
3
- */
4
- import {
5
- Bot,
6
- PrivateMessageEvent,
7
- GroupMessageEvent,
8
- } from "qq-official-bot";
9
- import path from "path";
10
- import {
11
- Bot as ZhinBot,
12
- Message,
13
- SendOptions,
14
- SendContent,
15
- segment,
16
- } from "zhin.js";
17
- import type { QQBotConfig, ReceiverMode, ApplicationPlatform } from "./types.js";
18
- import type { QQAdapter } from "./adapter.js";
19
-
20
-
21
- export class QQBot<T extends ReceiverMode, M extends ApplicationPlatform = ApplicationPlatform>
22
- extends Bot
23
- implements ZhinBot<QQBotConfig<T, M>, PrivateMessageEvent | GroupMessageEvent>
24
- {
25
- $connected: boolean = false;
26
- declare $config: QQBotConfig<T, M>;
27
-
28
- get pluginLogger() {
29
- return this.adapter.plugin.logger;
30
- }
31
-
32
- get $id() {
33
- return this.$config.name;
34
- }
35
-
36
- constructor(public adapter: QQAdapter, config: QQBotConfig<T, M>) {
37
- if (!config.data_dir) config.data_dir = path.join(process.cwd(), "data");
38
- super(config);
39
- this.$config = config;
40
- }
41
-
42
- private handleQQMessage(msg: PrivateMessageEvent | GroupMessageEvent): void {
43
- const message = this.$formatMessage(msg);
44
- this.adapter.emit("message.receive", message);
45
- this.pluginLogger.debug(`${this.$config.name} recv ${message.$channel.type}(${message.$channel.id}):${segment.raw(message.$content)}`);
46
- }
47
-
48
- async $connect(): Promise<void> {
49
- this.on("message.group", this.handleQQMessage.bind(this));
50
- this.on("message.guild", this.handleQQMessage.bind(this));
51
- this.on("message.private", this.handleQQMessage.bind(this));
52
- await this.start();
53
- this.$connected = true;
54
- }
55
-
56
- async $disconnect(): Promise<void> {
57
- // Bot 继承自 EventEmitter,清除 $connect() 注册的所有监听器
58
- (this as unknown as import('node:events').EventEmitter).removeAllListeners();
59
- await this.stop();
60
- this.$connected = false;
61
- }
62
-
63
- $formatMessage(msg: PrivateMessageEvent | GroupMessageEvent) {
64
- let target_id = msg.user_id;
65
- if (msg.message_type === "guild") target_id = msg.channel_id!;
66
- if (msg.message_type === "group") target_id = msg.group_id!;
67
- if (msg.sub_type === "direct") target_id = `direct:${msg.guild_id}`;
68
- const result = Message.from(msg, {
69
- $id: msg.message_id?.toString(),
70
- $adapter: "qq" as const,
71
- $bot: this.$config.name,
72
- $sender: {
73
- id: msg.sender.user_id?.toString(),
74
- name: msg.sender.user_name?.toString(),
75
- },
76
- $channel: {
77
- id: target_id,
78
- type: msg.message_type === "guild" ? "channel" : msg.message_type,
79
- },
80
- $content: msg.message,
81
- $raw: msg.raw_message,
82
- $timestamp: Date.now(),
83
- $recall: async () => {
84
- await this.$recallMessage(result.$id);
85
- },
86
- $reply: async (content: SendContent, quote: boolean | string = true): Promise<string> => {
87
- if (!Array.isArray(content)) content = [content];
88
- if (quote) content.unshift({ type: "reply", data: { id: typeof quote === "boolean" ? result.$id : quote } });
89
- return await this.adapter.sendMessage({
90
- ...result.$channel,
91
- context: "qq",
92
- bot: this.$config.name,
93
- content,
94
- });
95
- },
96
- });
97
- return result;
98
- }
99
-
100
- async $sendMessage(options: SendOptions): Promise<string> {
101
- switch (options.type) {
102
- case "private": {
103
- if (options.id.startsWith("direct:")) {
104
- const id = options.id.replace("direct:", "");
105
- const result = await this.sendDirectMessage(id, options.content);
106
- this.pluginLogger.debug(`${this.$config.name} send ${options.type}(${options.id}):${segment.raw(options.content)}`);
107
- return `direct-${options.id}:${result.id.toString()}`;
108
- } else {
109
- const result = await this.sendPrivateMessage(options.id, options.content);
110
- this.pluginLogger.debug(`${this.$config.name} send ${options.type}(${options.id}):${segment.raw(options.content)}`);
111
- return `private-${options.id}:${result.id.toString()}`;
112
- }
113
- }
114
- case "group": {
115
- const result = await this.sendGroupMessage(options.id, options.content);
116
- this.pluginLogger.debug(`${this.$config.name} send ${options.type}(${options.id}):${segment.raw(options.content)}`);
117
- return `group-${options.id}:${result.id.toString()}`;
118
- }
119
- case "channel": {
120
- const result = await this.sendGuildMessage(options.id, options.content);
121
- this.pluginLogger.debug(`${this.$config.name} send ${options.type}(${options.id}):${segment.raw(options.content)}`);
122
- return `channel-${options.id}:${result.id.toString()}`;
123
- }
124
- default:
125
- throw new Error(`unsupported channel type ${options.type}`);
126
- }
127
- }
128
-
129
- async $recallMessage(id: string): Promise<void> {
130
- if (!/^(private|group|channel|direct)-([^\:]+):(.+)$/.test(id)) throw new Error(`invalid message id ${id}`);
131
- const match = id.match(/^(private|group|channel|direct)-([^\:]+):(.+)$/);
132
- if (!match) return;
133
- const [, target_type, target_id, message_id] = match;
134
- if (target_type === "private") await this.recallPrivateMessage(target_id, message_id);
135
- if (target_type === "group") await this.recallGroupMessage(target_id, message_id);
136
- if (target_type === "channel") await this.recallGuildMessage(target_id, message_id);
137
- if (target_type === "direct") await this.recallDirectMessage(target_id, message_id);
138
- }
139
-
140
- // ==================== 频道管理 API ====================
141
-
142
- /**
143
- * 获取频道列表
144
- */
145
- async getGuilds(): Promise<any[]> {
146
- try {
147
- return await this.guildService.getList();
148
- } catch (error) {
149
- this.pluginLogger.error(`QQ Bot ${this.$id} 获取频道列表失败:`, error);
150
- throw error;
151
- }
152
- }
153
-
154
- /**
155
- * 获取频道详情
156
- * @param guildId 频道 ID
157
- */
158
- async getGuildInfo(guildId: string): Promise<any> {
159
- try {
160
- return await this.guildService.getInfo(guildId);
161
- } catch (error) {
162
- this.pluginLogger.error(`QQ Bot ${this.$id} 获取频道详情失败:`, error);
163
- throw error;
164
- }
165
- }
166
-
167
- /**
168
- * 获取子频道列表
169
- * @param guildId 频道 ID
170
- */
171
- async getChannels(guildId: string): Promise<any[]> {
172
- try {
173
- return await this.channelService.getList(guildId);
174
- } catch (error) {
175
- this.pluginLogger.error(`QQ Bot ${this.$id} 获取子频道列表失败:`, error);
176
- throw error;
177
- }
178
- }
179
-
180
- /**
181
- * 获取子频道详情
182
- * @param channelId 子频道 ID
183
- */
184
- async getChannelInfo(channelId: string): Promise<any> {
185
- try {
186
- return await this.channelService.getInfo(channelId);
187
- } catch (error) {
188
- this.pluginLogger.error(`QQ Bot ${this.$id} 获取子频道详情失败:`, error);
189
- throw error;
190
- }
191
- }
192
-
193
- /**
194
- * 获取频道成员列表
195
- * @param guildId 频道 ID
196
- */
197
- async getGuildMembers(guildId: string): Promise<any[]> {
198
- try {
199
- return await this.memberService.getGuildMemberList(guildId);
200
- } catch (error) {
201
- this.pluginLogger.error(`QQ Bot ${this.$id} 获取频道成员列表失败:`, error);
202
- throw error;
203
- }
204
- }
205
-
206
- /**
207
- * 获取频道成员详情
208
- * @param guildId 频道 ID
209
- * @param userId 用户 ID
210
- */
211
- async getGuildMember(guildId: string, userId: string): Promise<any> {
212
- try {
213
- return await this.memberService.getGuildMemberInfo(guildId, userId);
214
- } catch (error) {
215
- this.pluginLogger.error(`QQ Bot ${this.$id} 获取成员详情失败:`, error);
216
- throw error;
217
- }
218
- }
219
-
220
- /**
221
- * 删除频道成员(踢出)
222
- * @param guildId 频道 ID
223
- * @param userId 用户 ID
224
- * @param addBlacklist 是否加入黑名单
225
- * @param deleteHistoryMsg 删除历史消息天数 (-1不删除,0全部删除,3/7/15/30)
226
- */
227
- async removeGuildMember(guildId: string, userId: string, addBlacklist?: boolean, deleteHistoryMsg?: -1 | 0 | 3 | 7 | 15 | 30): Promise<boolean> {
228
- try {
229
- await this.memberService.kickMember(guildId, userId, deleteHistoryMsg, addBlacklist);
230
- this.pluginLogger.info(`QQ Bot ${this.$id} 踢出成员 ${userId}(频道 ${guildId})`);
231
- return true;
232
- } catch (error) {
233
- this.pluginLogger.error(`QQ Bot ${this.$id} 踢出成员失败:`, error);
234
- throw error;
235
- }
236
- }
237
-
238
- /**
239
- * 获取频道角色列表
240
- * @param guildId 频道 ID
241
- */
242
- async getGuildRoles(guildId: string): Promise<any[]> {
243
- try {
244
- return await this.guildService.getRoles(guildId);
245
- } catch (error) {
246
- this.pluginLogger.error(`QQ Bot ${this.$id} 获取角色列表失败:`, error);
247
- throw error;
248
- }
249
- }
250
-
251
- /**
252
- * 创建频道角色
253
- * @param guildId 频道 ID
254
- * @param name 角色名
255
- * @param color 颜色
256
- * @param hoist 是否在成员列表中单独展示 (0 或 1)
257
- */
258
- async createGuildRole(guildId: string, name: string, color?: number, hoist?: 0 | 1): Promise<any> {
259
- try {
260
- const result = await this.guildService.createRole(guildId, { name, color: color || 0, hoist: hoist ?? 0 });
261
- this.pluginLogger.info(`QQ Bot ${this.$id} 创建角色 "${name}"(频道 ${guildId})`);
262
- return result;
263
- } catch (error) {
264
- this.pluginLogger.error(`QQ Bot ${this.$id} 创建角色失败:`, error);
265
- throw error;
266
- }
267
- }
268
-
269
- /**
270
- * 给成员添加角色
271
- * @param guildId 频道 ID
272
- * @param channelId 子频道 ID
273
- * @param userId 用户 ID
274
- * @param roleId 角色 ID
275
- */
276
- async addMemberRole(guildId: string, channelId: string, userId: string, roleId: string): Promise<boolean> {
277
- try {
278
- await this.memberService.addMemberRole(guildId, channelId, userId, roleId);
279
- this.pluginLogger.info(`QQ Bot ${this.$id} 给成员 ${userId} 添加角色 ${roleId}(频道 ${guildId})`);
280
- return true;
281
- } catch (error) {
282
- this.pluginLogger.error(`QQ Bot ${this.$id} 添加角色失败:`, error);
283
- throw error;
284
- }
285
- }
286
-
287
- /**
288
- * 移除成员角色
289
- * @param guildId 频道 ID
290
- * @param channelId 子频道 ID
291
- * @param userId 用户 ID
292
- * @param roleId 角色 ID
293
- */
294
- async removeMemberRole(guildId: string, channelId: string, userId: string, roleId: string): Promise<boolean> {
295
- try {
296
- await this.memberService.removeMemberRole(guildId, channelId, userId, roleId);
297
- this.pluginLogger.info(`QQ Bot ${this.$id} 移除成员 ${userId} 的角色 ${roleId}(频道 ${guildId})`);
298
- return true;
299
- } catch (error) {
300
- this.pluginLogger.error(`QQ Bot ${this.$id} 移除角色失败:`, error);
301
- throw error;
302
- }
303
- }
304
-
305
- /**
306
- * 禁言成员(批量)
307
- * @param guildId 频道 ID
308
- * @param userIds 用户 ID 列表
309
- * @param muteSeconds 禁言时长(秒),0 表示解除禁言
310
- */
311
- async muteMembers(guildId: string, userIds: string[], muteSeconds: number): Promise<boolean> {
312
- try {
313
- if (muteSeconds > 0) {
314
- await this.memberService.muteMembers(guildId, userIds, muteSeconds);
315
- this.pluginLogger.info(`QQ Bot ${this.$id} 禁言成员 ${userIds.join(',')} ${muteSeconds}秒(频道 ${guildId})`);
316
- } else {
317
- await this.memberService.unmuteMembers(guildId, userIds);
318
- this.pluginLogger.info(`QQ Bot ${this.$id} 解除成员 ${userIds.join(',')} 禁言(频道 ${guildId})`);
319
- }
320
- return true;
321
- } catch (error) {
322
- this.pluginLogger.error(`QQ Bot ${this.$id} 禁言操作失败:`, error);
323
- throw error;
324
- }
325
- }
326
-
327
- /**
328
- * 全员禁言
329
- * @param guildId 频道 ID
330
- * @param muteSeconds 禁言时长(秒),0 表示解除禁言
331
- */
332
- async muteAll(guildId: string, muteSeconds: number): Promise<boolean> {
333
- try {
334
- if (muteSeconds > 0) {
335
- await this.guildService.mute(guildId, muteSeconds);
336
- this.pluginLogger.info(`QQ Bot ${this.$id} 开启全员禁言(频道 ${guildId})`);
337
- } else {
338
- await this.guildService.unmute(guildId);
339
- this.pluginLogger.info(`QQ Bot ${this.$id} 关闭全员禁言(频道 ${guildId})`);
340
- }
341
- return true;
342
- } catch (error) {
343
- this.pluginLogger.error(`QQ Bot ${this.$id} 全员禁言操作失败:`, error);
344
- throw error;
345
- }
346
- }
347
- }
package/src/types.ts DELETED
@@ -1,24 +0,0 @@
1
- /**
2
- * QQ 官方机器人适配器类型定义
3
- */
4
- import type { Bot } from "qq-official-bot";
5
- import type { ReceiverMode, ApplicationPlatform } from "qq-official-bot";
6
-
7
- export { ReceiverMode } from "qq-official-bot";
8
- export type { ApplicationPlatform, Intent } from "qq-official-bot";
9
-
10
- export type QQBotConfig<
11
- T extends ReceiverMode,
12
- M extends ApplicationPlatform = ApplicationPlatform,
13
- > = Bot.Config<T, M> & {
14
- context: "qq";
15
- name: string;
16
- data_dir?: string;
17
- };
18
-
19
- export interface QQBot<
20
- T extends ReceiverMode,
21
- M extends ApplicationPlatform = ApplicationPlatform,
22
- > {
23
- $config: QQBotConfig<T, M>;
24
- }