@zhin.js/adapter-qq 1.1.4 → 1.1.6
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/CHANGELOG.md +50 -0
- package/README.md +27 -0
- package/lib/delivery-error.d.ts +13 -0
- package/lib/delivery-error.js +19 -0
- package/lib/endpoint.d.ts +7 -1
- package/lib/endpoint.js +163 -71
- package/lib/interaction.d.ts +7 -0
- package/lib/interaction.js +16 -0
- package/lib/outbound.js +8 -5
- package/lib/protocol.d.ts +3 -1
- package/lib/protocol.js +15 -8
- package/lib/qq-intents.js +1 -0
- package/lib/start-deadline.d.ts +2 -0
- package/lib/start-deadline.js +21 -0
- package/lib/stream-proxy.d.ts +7 -0
- package/lib/stream-proxy.js +17 -0
- package/lib/upload-diagnostics.d.ts +6 -0
- package/lib/upload-diagnostics.js +106 -0
- package/lib/ws.d.ts +2 -0
- package/lib/ws.js +37 -2
- package/package.json +18 -18
- package/schema.json +40 -0
- package/src/delivery-error.ts +20 -0
- package/src/endpoint.ts +141 -71
- package/src/interaction.ts +15 -0
- package/src/outbound.ts +9 -5
- package/src/protocol.ts +17 -8
- package/src/qq-intents.ts +1 -0
- package/src/start-deadline.ts +18 -0
- package/src/stream-proxy.ts +20 -0
- package/src/upload-diagnostics.ts +70 -0
- package/src/ws.ts +27 -2
package/src/ws.ts
CHANGED
|
@@ -2,12 +2,14 @@
|
|
|
2
2
|
* QQ WebSocket transport: bot factory and inbound message normalization.
|
|
3
3
|
*/
|
|
4
4
|
import path from 'node:path';
|
|
5
|
+
import { createQqStreamAgent } from './stream-proxy.js';
|
|
5
6
|
import {
|
|
6
7
|
Bot,
|
|
7
8
|
ReceiverMode,
|
|
8
9
|
type ApproveJoinRequestOptions,
|
|
9
10
|
type Sendable,
|
|
10
11
|
} from 'qq-official-bot';
|
|
12
|
+
import type { EndpointTransportState } from 'zhin.js/adapter';
|
|
11
13
|
import type { MediaRef, Segment } from '@zhin.js/im-contract';
|
|
12
14
|
import type { QqOutboundMessage } from './outbound.js';
|
|
13
15
|
import type { QqChannelKind, QqInboundMessage, ResolvedQqWebsocketConfig } from './protocol.js';
|
|
@@ -36,6 +38,7 @@ export type QqOfficialApi = Pick<Bot,
|
|
|
36
38
|
|
|
37
39
|
/** Minimal bot surface used by the endpoint (real qq-official-bot or test mock). */
|
|
38
40
|
export interface QqBotTransport {
|
|
41
|
+
readonly transportState?: EndpointTransportState;
|
|
39
42
|
/** Full qq-official-bot business API; lifecycle remains owned by the Endpoint. */
|
|
40
43
|
readonly api: QqOfficialApi;
|
|
41
44
|
start(): Promise<void>;
|
|
@@ -278,6 +281,7 @@ function extractTextContent(message: unknown): string {
|
|
|
278
281
|
|
|
279
282
|
export function defaultCreateBot(config: ResolvedQqWebsocketConfig): QqBotTransport {
|
|
280
283
|
const bot = new Bot({
|
|
284
|
+
...({ handleProcessErrors: false } as Record<string, unknown>),
|
|
281
285
|
appid: config.appid,
|
|
282
286
|
secret: config.secret,
|
|
283
287
|
mode: ReceiverMode.WEBSOCKET,
|
|
@@ -290,14 +294,35 @@ export function defaultCreateBot(config: ResolvedQqWebsocketConfig): QqBotTransp
|
|
|
290
294
|
...(config.gatewayUrl ? { gatewayUrl: config.gatewayUrl } : {}),
|
|
291
295
|
});
|
|
292
296
|
|
|
297
|
+
const receiver = bot.receiver as unknown as { config: { autoReconnect: boolean; agent?: import('node:https').Agent }; on(event: string, listener: (...args: unknown[]) => void): void; removeListener(event: string, listener: (...args: unknown[]) => void): void };
|
|
298
|
+
receiver.config.autoReconnect = false;
|
|
299
|
+
const agent = config.streamProxy ? createQqStreamAgent(config.streamProxy) : undefined;
|
|
300
|
+
receiver.config.agent = agent;
|
|
301
|
+
const receiverListeners: Array<{ event: string; listener: (...args: unknown[]) => void }> = [];
|
|
302
|
+
// Keep receiver error ownership after Session.start removes its temporary listener.
|
|
303
|
+
const receiverError = () => {};
|
|
304
|
+
receiver.on('error', receiverError);
|
|
293
305
|
return {
|
|
306
|
+
get transportState(): EndpointTransportState {
|
|
307
|
+
const receiver = bot.receiver as unknown as { isReady?: boolean; isStarted?: boolean; isClosed?: boolean; handler?: { ws?: { readyState: number } } };
|
|
308
|
+
const state = receiver.handler?.ws?.readyState;
|
|
309
|
+
if (state === 1 && receiver.isReady && receiver.isClosed === false) return 'open';
|
|
310
|
+
if (state === 0) return 'connecting';
|
|
311
|
+
if (receiver.isStarted) return 'reconnecting';
|
|
312
|
+
return 'closed';
|
|
313
|
+
},
|
|
294
314
|
api: bot,
|
|
295
315
|
start: () => bot.start().then(() => undefined),
|
|
296
|
-
stop: () =>
|
|
316
|
+
stop: async () => {
|
|
317
|
+
try { await stopQqOfficialBot(bot as unknown as QqOfficialBotLifecycle); }
|
|
318
|
+
finally { agent?.destroy(); }
|
|
319
|
+
},
|
|
297
320
|
on: (event, listener) => {
|
|
298
|
-
|
|
321
|
+
if (event === 'transport.close') { receiver.on('close', listener); receiverListeners.push({ event: 'close', listener }); }
|
|
322
|
+
else bot.on(event as never, listener as never);
|
|
299
323
|
},
|
|
300
324
|
removeAllListeners: () => {
|
|
325
|
+
for (const entry of receiverListeners.splice(0)) receiver.removeListener(entry.event, entry.listener);
|
|
301
326
|
bot.removeAllListeners(undefined as never);
|
|
302
327
|
},
|
|
303
328
|
sendPrivateMessage: (userId, message) => bot.sendPrivateMessage(userId, message as Sendable),
|