@zhin.js/adapter-qq 8.0.0 → 8.0.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.
package/lib/endpoint.js CHANGED
@@ -1,29 +1,32 @@
1
+ import { Endpoint } from 'zhin.js/adapter';
1
2
  /**
2
3
  * QQ endpoints — lifecycle, outbound, admit, agent tool surface.
3
4
  */
4
5
  import { createRecallEndpointControl, } from 'zhin.js/adapter';
5
6
  import { formatCompact, getAdapterLogger, truncatePreview } from '@zhin.js/logger';
6
7
  import { formatOutbound } from './outbound.js';
7
- import { registerQqAgentEndpoint } from './qq-agent-deps.js';
8
8
  import { formatInboundContent, parseCompoundMessageId, qqInboundConversation, qqOutboundKind, resolveOutboundMessageId, senderDisplayName, } from './protocol.js';
9
9
  import { defaultCreateHttpBot, registerQqWebhookRoutes, } from './webhook.js';
10
10
  import { bindQqBotInboundEvents, defaultCreateBot, normalizeQqMessage, } from './ws.js';
11
11
  import { bindQqBotSideEvents, receiveQqSideEvent, } from './side-event-dispatch.js';
12
- export class QqWebsocketEndpoint {
12
+ export class QqWebsocketEndpoint extends Endpoint {
13
13
  #logger;
14
14
  #options;
15
15
  #createBot;
16
16
  #bot = null;
17
17
  #open = false;
18
18
  #started = false;
19
- #unregisterAgent;
20
- management = createQqEndpointManagement(this);
19
+ management = createQqEndpointManagement(() => this.#requireBot());
21
20
  control = createRecallEndpointControl((id) => this.recallMessage(id));
22
21
  constructor(options) {
22
+ super();
23
23
  this.#logger = getAdapterLogger('qq', options.config.id);
24
24
  this.#options = options;
25
25
  this.#createBot = options.createBot ?? defaultCreateBot;
26
26
  }
27
+ get client() {
28
+ return this.#requireBot();
29
+ }
27
30
  /** Live endpoint 名(Console/AdapterIndex 展示用,如 bot appid 别名)。 */
28
31
  get name() {
29
32
  return this.#options.config.id;
@@ -33,7 +36,6 @@ export class QqWebsocketEndpoint {
33
36
  return;
34
37
  this.#started = true;
35
38
  try {
36
- this.#unregisterAgent = registerQqAgentEndpoint(this.#options.config.id, this);
37
39
  this.#bot = this.#createBot(this.#options.config);
38
40
  this.#bindBot(this.#bot);
39
41
  await this.#bot.start();
@@ -54,8 +56,6 @@ export class QqWebsocketEndpoint {
54
56
  }
55
57
  async stop() {
56
58
  this.#open = false;
57
- this.#unregisterAgent?.();
58
- this.#unregisterAgent = undefined;
59
59
  if (this.#bot) {
60
60
  try {
61
61
  this.#bot.removeAllListeners();
@@ -130,7 +130,7 @@ export class QqWebsocketEndpoint {
130
130
  + (msg.authorId ? ` from ${msg.authorId}` : '')
131
131
  + (msg.mentioned ? ' (mentioned)' : '')
132
132
  + ` | ${truncatePreview(content, 80)}`);
133
- void this.#options.gateway.receive({
133
+ void this.emit('message.receive', {
134
134
  conversation,
135
135
  message: { conversation, id: msg.id },
136
136
  content,
@@ -156,38 +156,25 @@ export class QqWebsocketEndpoint {
156
156
  }));
157
157
  });
158
158
  }
159
- getGuilds() {
160
- return this.#requireBot().getGuilds();
161
- }
162
- getChannels(guildId) {
163
- return this.#requireBot().getChannels(guildId);
164
- }
165
- getChannelInfo(channelId) {
166
- return this.#requireBot().getChannelInfo(channelId);
167
- }
168
- getGuildMember(guildId, userId) {
169
- return this.#requireBot().getGuildMember(guildId, userId);
170
- }
171
- getGuildRoles(guildId) {
172
- return this.#requireBot().getGuildRoles(guildId);
173
- }
174
- createGuildRole(guildId, name, color) {
175
- return this.#requireBot().createGuildRole(guildId, name, color);
176
- }
177
- addMemberRole(guildId, channelId, userId, roleId) {
178
- return this.#requireBot().addMemberRole(guildId, channelId, userId, roleId);
179
- }
180
- removeMemberRole(guildId, channelId, userId, roleId) {
181
- return this.#requireBot().removeMemberRole(guildId, channelId, userId, roleId);
182
- }
183
159
  #bindBot(bot) {
184
160
  bindQqBotInboundEvents(bot, (raw) => {
161
+ this.#emitPlatformEvent('message', raw);
185
162
  const msg = normalizeQqMessage(raw);
186
163
  if (msg)
187
164
  this.admit(msg);
188
165
  });
189
166
  bindQqBotSideEvents(bot, (eventName, raw) => {
190
- receiveQqSideEvent(this.#options.sideEvents, this.#options.config.id, bot, eventName, raw, this.#logger);
167
+ this.#emitPlatformEvent(eventName, raw);
168
+ receiveQqSideEvent((name, payload) => this.emit(name, payload), this.#options.config.id, bot, eventName, raw, this.#logger);
169
+ });
170
+ }
171
+ #emitPlatformEvent(name, event) {
172
+ void this.emitPlatform(name, event).catch((error) => {
173
+ this.#logger.warn(formatCompact({
174
+ op: 'qq_platform_event_failed',
175
+ event: name,
176
+ error: error instanceof Error ? error.message : String(error),
177
+ }));
191
178
  });
192
179
  }
193
180
  #requireBot() {
@@ -197,7 +184,7 @@ export class QqWebsocketEndpoint {
197
184
  }
198
185
  }
199
186
  /** Webhook / middleware inbound via httpHostToken POST (qq-official-bot Middleware receiver). */
200
- export class QqHttpEndpoint {
187
+ export class QqHttpEndpoint extends Endpoint {
201
188
  #logger;
202
189
  #options;
203
190
  #createBot;
@@ -205,14 +192,17 @@ export class QqHttpEndpoint {
205
192
  #routeReleases = [];
206
193
  #open = false;
207
194
  #started = false;
208
- #unregisterAgent;
209
- management = createQqEndpointManagement(this);
195
+ management = createQqEndpointManagement(() => this.#requireBot());
210
196
  control = createRecallEndpointControl((id) => this.recallMessage(id));
211
197
  constructor(options) {
198
+ super();
212
199
  this.#logger = getAdapterLogger('qq', options.config.id);
213
200
  this.#options = options;
214
201
  this.#createBot = options.createBot ?? defaultCreateHttpBot;
215
202
  }
203
+ get client() {
204
+ return this.#requireBot();
205
+ }
216
206
  /** Live endpoint 名(Console/AdapterIndex 展示用)。 */
217
207
  get name() {
218
208
  return this.#options.config.id;
@@ -222,7 +212,6 @@ export class QqHttpEndpoint {
222
212
  return;
223
213
  this.#started = true;
224
214
  try {
225
- this.#unregisterAgent = registerQqAgentEndpoint(this.#options.config.id, this);
226
215
  this.#setupRoutes();
227
216
  this.#bot = this.#createBot(this.#options.config);
228
217
  this.#bindBot(this.#bot);
@@ -245,8 +234,6 @@ export class QqHttpEndpoint {
245
234
  this.#open = false;
246
235
  for (const release of this.#routeReleases.splice(0))
247
236
  release();
248
- this.#unregisterAgent?.();
249
- this.#unregisterAgent = undefined;
250
237
  if (this.#bot) {
251
238
  try {
252
239
  this.#bot.removeAllListeners();
@@ -320,7 +307,7 @@ export class QqHttpEndpoint {
320
307
  + (msg.authorId ? ` from ${msg.authorId}` : '')
321
308
  + (msg.mentioned ? ' (mentioned)' : '')
322
309
  + ` | ${truncatePreview(content, 80)}`);
323
- void this.#options.gateway.receive({
310
+ void this.emit('message.receive', {
324
311
  conversation,
325
312
  message: { conversation, id: msg.id },
326
313
  content,
@@ -346,30 +333,6 @@ export class QqHttpEndpoint {
346
333
  }));
347
334
  });
348
335
  }
349
- getGuilds() {
350
- return this.#requireBot().getGuilds();
351
- }
352
- getChannels(guildId) {
353
- return this.#requireBot().getChannels(guildId);
354
- }
355
- getChannelInfo(channelId) {
356
- return this.#requireBot().getChannelInfo(channelId);
357
- }
358
- getGuildMember(guildId, userId) {
359
- return this.#requireBot().getGuildMember(guildId, userId);
360
- }
361
- getGuildRoles(guildId) {
362
- return this.#requireBot().getGuildRoles(guildId);
363
- }
364
- createGuildRole(guildId, name, color) {
365
- return this.#requireBot().createGuildRole(guildId, name, color);
366
- }
367
- addMemberRole(guildId, channelId, userId, roleId) {
368
- return this.#requireBot().addMemberRole(guildId, channelId, userId, roleId);
369
- }
370
- removeMemberRole(guildId, channelId, userId, roleId) {
371
- return this.#requireBot().removeMemberRole(guildId, channelId, userId, roleId);
372
- }
373
336
  #setupRoutes() {
374
337
  this.#routeReleases.push(...registerQqWebhookRoutes(this.#options.http, {
375
338
  config: this.#options.config,
@@ -378,12 +341,23 @@ export class QqHttpEndpoint {
378
341
  }
379
342
  #bindBot(bot) {
380
343
  bindQqBotInboundEvents(bot, (raw) => {
344
+ this.#emitPlatformEvent('message', raw);
381
345
  const msg = normalizeQqMessage(raw);
382
346
  if (msg)
383
347
  this.admit(msg);
384
348
  });
385
349
  bindQqBotSideEvents(bot, (eventName, raw) => {
386
- receiveQqSideEvent(this.#options.sideEvents, this.#options.config.id, bot, eventName, raw, this.#logger);
350
+ this.#emitPlatformEvent(eventName, raw);
351
+ receiveQqSideEvent((name, payload) => this.emit(name, payload), this.#options.config.id, bot, eventName, raw, this.#logger);
352
+ });
353
+ }
354
+ #emitPlatformEvent(name, event) {
355
+ void this.emitPlatform(name, event).catch((error) => {
356
+ this.#logger.warn(formatCompact({
357
+ op: 'qq_platform_event_failed',
358
+ event: name,
359
+ error: error instanceof Error ? error.message : String(error),
360
+ }));
387
361
  });
388
362
  }
389
363
  #requireBot() {
@@ -392,18 +366,19 @@ export class QqHttpEndpoint {
392
366
  return this.#bot;
393
367
  }
394
368
  }
395
- function createQqEndpointManagement(endpoint) {
369
+ function createQqEndpointManagement(requireClient) {
396
370
  return Object.freeze({
397
371
  async listChannels() {
398
372
  const channels = [];
399
- const guilds = await endpoint.getGuilds();
373
+ const client = requireClient();
374
+ const guilds = await client.getGuilds();
400
375
  for (const guildValue of Array.isArray(guilds) ? guilds : []) {
401
376
  const guild = asRecord(guildValue);
402
377
  const guildId = String(guild.id ?? guild.guild_id ?? guildValue ?? '');
403
378
  if (!guildId)
404
379
  continue;
405
380
  const guildName = String(guild.name ?? guild.guild_name ?? guildId);
406
- const rows = await endpoint.getChannels(guildId);
381
+ const rows = await client.getChannels(guildId);
407
382
  for (const channelValue of Array.isArray(rows) ? rows : []) {
408
383
  const channel = asRecord(channelValue);
409
384
  const id = String(channel.id ?? channel.channel_id ?? channelValue ?? '');
package/lib/index.d.ts CHANGED
@@ -4,5 +4,5 @@ export { formatOutbound, resolveMediaFile, type QqOutboundElem, type QqOutboundM
4
4
  export { QqHttpEndpoint, QqWebsocketEndpoint, type CreateQqBot, type CreateQqHttpBot, type QqBotTransport, type QqEndpointOptions, type QqHttpBotTransport, type QqHttpEndpointOptions, } from './endpoint.js';
5
5
  export { registerQqWebhookRoutes, handleQqWebhookRequest, readRequestBodyText, defaultCreateHttpBot, type QqWebhookHandler, } from './webhook.js';
6
6
  export { bindQqBotInboundEvents, defaultCreateBot, normalizeQqMessage, } from './ws.js';
7
- export { getQqAgentDeps, registerQqAgentEndpoint, setQqAgentDeps, type QqAgentDeps, type QqAgentEndpoint, } from './qq-agent-deps.js';
7
+ export { qqClient, type QqClientEventMap } from './client.js';
8
8
  export { checkQqPlatformPermit, normalizeQqGuildSenderForPermit, platformPermit, qqGuildPermitResolver, } from './platform-permit.js';
package/lib/index.js CHANGED
@@ -4,5 +4,5 @@ export { formatOutbound, resolveMediaFile, } from './outbound.js';
4
4
  export { QqHttpEndpoint, QqWebsocketEndpoint, } from './endpoint.js';
5
5
  export { registerQqWebhookRoutes, handleQqWebhookRequest, readRequestBodyText, defaultCreateHttpBot, } from './webhook.js';
6
6
  export { bindQqBotInboundEvents, defaultCreateBot, normalizeQqMessage, } from './ws.js';
7
- export { getQqAgentDeps, registerQqAgentEndpoint, setQqAgentDeps, } from './qq-agent-deps.js';
7
+ export { qqClient } from './client.js';
8
8
  export { checkQqPlatformPermit, normalizeQqGuildSenderForPermit, platformPermit, qqGuildPermitResolver, } from './platform-permit.js';
@@ -42,4 +42,4 @@ export declare function runQqEndpointRemove(_state: QqRuntimeState, id: string,
42
42
  * 通用套件生成的 QQ endpoint 命令(add 经 bindFlow 钩子走扫码绑定)。
43
43
  * commands/endpoint/ 下的 list / add / remove 直接默认导出这三项;cancel 为 QQ 特化,单独定义。
44
44
  */
45
- export declare const qqEndpointCommands: import("@zhin.js/adapter").EndpointCommands<Readonly<import("@zhin.js/command").CommandDefinition<unknown, unknown, import("@zhin.js/command").CommandMessage>>>;
45
+ export declare const qqEndpointCommands: import("@zhin.js/adapter").EndpointCommands<Readonly<import("@zhin.js/command").CommandDefinition<unknown, unknown, import("@zhin.js/command").CommandMessage, string | undefined>>>;
@@ -1,4 +1,4 @@
1
- import type { SideEventGateway } from '@zhin.js/core/runtime';
1
+ import type { EndpointEventEmitter } from 'zhin.js/adapter';
2
2
  import { type getAdapterLogger } from '@zhin.js/logger';
3
3
  export interface QqSideEventCaller {
4
4
  approveGroupJoinRequest?(groupId: string, userId: string, options: {
@@ -10,4 +10,4 @@ export interface QqSideEventCaller {
10
10
  export declare function bindQqBotSideEvents(bot: {
11
11
  on(event: string, listener: (...args: unknown[]) => void): void;
12
12
  }, dispatch: (eventName: string, raw: unknown) => void): void;
13
- export declare function receiveQqSideEvent(sideEvents: SideEventGateway | undefined, endpointKey: string, caller: QqSideEventCaller, eventName: string, raw: unknown, logger: ReturnType<typeof getAdapterLogger>): void;
13
+ export declare function receiveQqSideEvent(emit: EndpointEventEmitter, endpointKey: string, caller: QqSideEventCaller, eventName: string, raw: unknown, logger: ReturnType<typeof getAdapterLogger>): void;
@@ -51,8 +51,8 @@ function toOneBotLikeRaw(eventName, raw) {
51
51
  }
52
52
  return null;
53
53
  }
54
- export function receiveQqSideEvent(sideEvents, endpointKey, caller, eventName, raw, logger) {
55
- if (!sideEvents)
54
+ export function receiveQqSideEvent(emit, endpointKey, caller, eventName, raw, logger) {
55
+ if (!emit)
56
56
  return;
57
57
  const mapped = toOneBotLikeRaw(eventName, raw);
58
58
  if (!mapped)
@@ -61,7 +61,7 @@ export function receiveQqSideEvent(sideEvents, endpointKey, caller, eventName, r
61
61
  const joinRaw = isJoinRequest && raw && typeof raw === 'object'
62
62
  ? raw
63
63
  : undefined;
64
- void receiveOneBotLikeSideEvent(sideEvents, {
64
+ void receiveOneBotLikeSideEvent(emit, {
65
65
  adapter: 'qq',
66
66
  endpointKey,
67
67
  platform: 'qq',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zhin.js/adapter-qq",
3
- "version": "8.0.0",
3
+ "version": "8.0.2",
4
4
  "description": "Zhin.js QQ Official adapter for Plugin Runtime (WebSocket gateway)",
5
5
  "type": "module",
6
6
  "main": "./lib/index.js",
@@ -35,21 +35,22 @@
35
35
  },
36
36
  "dependencies": {
37
37
  "qq-official-bot": "^1.2.3",
38
- "@zhin.js/adapter": "1.2.0",
39
- "@zhin.js/core": "1.5.13",
40
- "@zhin.js/host-http": "1.0.12",
38
+ "@zhin.js/adapter": "1.2.1",
39
+ "@zhin.js/core": "1.5.14",
40
+ "@zhin.js/feature-kit": "1.0.13",
41
+ "@zhin.js/host-http": "1.0.13",
41
42
  "@zhin.js/im-contract": "1.0.4",
42
- "@zhin.js/logger": "1.0.76",
43
- "@zhin.js/permission": "1.0.3"
43
+ "@zhin.js/logger": "1.0.77",
44
+ "@zhin.js/permission": "1.0.4"
44
45
  },
45
46
  "peerDependencies": {
46
47
  "zod": "^4.0.0",
47
- "@zhin.js/adapter": "1.2.0",
48
- "@zhin.js/agent": "1.1.15",
49
- "@zhin.js/command": "1.0.15",
50
- "@zhin.js/core": "1.5.13",
51
- "@zhin.js/middleware": "1.0.12",
52
- "zhin.js": "6.0.13"
48
+ "@zhin.js/adapter": "1.2.1",
49
+ "@zhin.js/agent": "1.1.17",
50
+ "@zhin.js/command": "1.0.16",
51
+ "@zhin.js/core": "1.5.14",
52
+ "@zhin.js/middleware": "1.0.13",
53
+ "zhin.js": "6.0.14"
53
54
  },
54
55
  "peerDependenciesMeta": {
55
56
  "@zhin.js/agent": {
@@ -73,9 +74,9 @@
73
74
  "typescript": "^6.0.3",
74
75
  "vitest": "^4.1.10",
75
76
  "zod": "^4.4.3",
76
- "@zhin.js/agent": "1.1.15",
77
- "@zhin.js/host-http": "1.0.12",
78
- "zhin.js": "6.0.13"
77
+ "@zhin.js/agent": "1.1.17",
78
+ "@zhin.js/host-http": "1.0.13",
79
+ "zhin.js": "6.0.14"
79
80
  },
80
81
  "files": [
81
82
  "adapters",
package/src/client.ts ADDED
@@ -0,0 +1,16 @@
1
+ import { defineEndpointClient } from 'zhin.js/adapter';
2
+ import type { QqInboundMessage } from './protocol.js';
3
+ import type { QqBotTransport } from './ws.js';
4
+
5
+ export type QqClientEventMap = Record<string, QqInboundMessage | unknown>;
6
+
7
+ declare module '@zhin.js/feature-kit' {
8
+ interface AdapterClientRegistry {
9
+ readonly qq: {
10
+ readonly client: QqBotTransport;
11
+ readonly events: QqClientEventMap;
12
+ };
13
+ }
14
+ }
15
+
16
+ export const qqClient = defineEndpointClient<QqBotTransport, QqClientEventMap>('qq');