@zhin.js/adapter-icqq 1.1.17 → 1.1.18
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 +46 -0
- package/README.md +44 -3
- package/adapters/icqq/index.js +10 -2
- package/adapters/icqq/index.ts +10 -2
- package/commands/icqq/login/code/index.js +28 -0
- package/commands/icqq/login/code/index.ts +30 -0
- package/commands/icqq/login/confirm/index.js +20 -0
- package/commands/icqq/login/confirm/index.ts +21 -0
- package/commands/icqq/login/definition.js +65 -0
- package/commands/icqq/login/definition.ts +72 -0
- package/commands/icqq/login/qr/index.js +53 -0
- package/commands/icqq/login/qr/index.ts +55 -0
- package/commands/icqq/login/retry/index.js +21 -0
- package/commands/icqq/login/retry/index.ts +23 -0
- package/commands/icqq/login/status/index.js +31 -0
- package/commands/icqq/login/status/index.ts +34 -0
- package/lib/console-spec.d.ts +17 -0
- package/lib/console-spec.js +11 -0
- package/lib/console.d.ts +8 -0
- package/lib/console.js +16 -0
- package/lib/endpoint.d.ts +9 -2
- package/lib/endpoint.js +194 -37
- package/lib/icqq-login-control.d.ts +18 -0
- package/lib/icqq-login-control.js +8 -0
- package/lib/index.d.ts +1 -1
- package/lib/index.js +1 -1
- package/lib/protocol.d.ts +10 -0
- package/lib/protocol.js +24 -9
- package/package.json +17 -9
- package/pages/index/index.js +15 -0
- package/pages/index/index.ts +16 -0
- package/plugin.js +6 -1
- package/schema.json +174 -0
- package/src/console-spec.ts +17 -0
- package/src/console.ts +21 -0
- package/src/endpoint.ts +193 -42
- package/src/icqq-login-control.ts +30 -0
- package/src/index.ts +2 -0
- package/src/protocol.ts +32 -8
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ICQQ login control surface exposed to the Plugin Runtime, Console and the
|
|
3
|
+
* recovery command. One control per endpoint instance (UIN), provided by the
|
|
4
|
+
* ICQQ plugin setup and filled by `adapters/icqq/create()`.
|
|
5
|
+
*/
|
|
6
|
+
import { createToken } from 'zhin.js';
|
|
7
|
+
import type { PendingLoginTask } from '@zhin.js/core';
|
|
8
|
+
|
|
9
|
+
export interface IcqqLoginControlState {
|
|
10
|
+
readonly endpointId: string;
|
|
11
|
+
readonly transportState: string;
|
|
12
|
+
readonly online: boolean;
|
|
13
|
+
readonly pending: readonly PendingLoginTask[];
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface IcqqLoginControl {
|
|
17
|
+
readonly endpointId: string;
|
|
18
|
+
state(): IcqqLoginControlState;
|
|
19
|
+
pending(): readonly PendingLoginTask[];
|
|
20
|
+
/** Force a login attempt; rejects when the endpoint is stopped or the SDK login fails. */
|
|
21
|
+
relogin(): Promise<void>;
|
|
22
|
+
submit(taskId: string, value: string | Record<string, unknown>): boolean;
|
|
23
|
+
cancel(taskId: string, reason?: string): boolean;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** `endpoint id (QQ uin)` → control for the current generation. */
|
|
27
|
+
export const icqqLoginControlToken = createToken<Map<string, IcqqLoginControl>>(
|
|
28
|
+
'zhin.icqq.login-control',
|
|
29
|
+
'ICQQ login control surface for recovery commands',
|
|
30
|
+
);
|
package/src/index.ts
CHANGED
|
@@ -3,12 +3,14 @@ export {
|
|
|
3
3
|
formatInboundContent,
|
|
4
4
|
formatOutboundBody,
|
|
5
5
|
formatOutboundMessages,
|
|
6
|
+
formatOutboundMessageParts,
|
|
6
7
|
icqqInboundConversation,
|
|
7
8
|
icqqOutboundTarget,
|
|
8
9
|
type ActionResult,
|
|
9
10
|
type IcqqEndpointConfig,
|
|
10
11
|
type IcqqInboundMessage,
|
|
11
12
|
type IcqqWireSegment,
|
|
13
|
+
type IcqqOutboundMessagePart,
|
|
12
14
|
type ParsedIcqqSendTarget,
|
|
13
15
|
type ResolvedIcqqConfig,
|
|
14
16
|
} from './protocol.js';
|
package/src/protocol.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { MessageElem, Sendable, ShareElem } from '@icqqjs/icqq';
|
|
2
2
|
import { isMediaRef, type ConversationRef } from '@zhin.js/im-contract';
|
|
3
|
+
import { resolveAdapterNotifyTarget, type AdapterNotifyTarget, type ResolvedAdapterNotifyTarget } from 'zhin.js/adapter';
|
|
3
4
|
import type { MessageSegment, SendContent } from "zhin.js";
|
|
4
5
|
import { resolveIcqqMediaFile } from "./cq-message.js";
|
|
5
6
|
|
|
@@ -246,6 +247,8 @@ export interface IcqqEndpointConfig {
|
|
|
246
247
|
readonly autoServer?: boolean;
|
|
247
248
|
readonly qqnt?: boolean;
|
|
248
249
|
readonly ntLogin?: boolean;
|
|
250
|
+
/** Optional out-of-band outage notification target (usually a QQ adapter instance). */
|
|
251
|
+
readonly notify?: AdapterNotifyTarget;
|
|
249
252
|
}
|
|
250
253
|
|
|
251
254
|
export interface ResolvedIcqqConfig {
|
|
@@ -264,6 +267,7 @@ export interface ResolvedIcqqConfig {
|
|
|
264
267
|
readonly autoServer?: boolean;
|
|
265
268
|
readonly qqnt?: boolean;
|
|
266
269
|
readonly ntLogin?: boolean;
|
|
270
|
+
readonly notify?: ResolvedAdapterNotifyTarget;
|
|
267
271
|
}
|
|
268
272
|
|
|
269
273
|
export interface IcqqWireSegment {
|
|
@@ -311,6 +315,7 @@ export function resolveIcqqConfig(config: IcqqEndpointConfig): ResolvedIcqqConfi
|
|
|
311
315
|
const autoServer = config.autoServer ?? true;
|
|
312
316
|
const qqnt = config.qqnt;
|
|
313
317
|
const ntLogin = config.ntLogin;
|
|
318
|
+
const notify = resolveAdapterNotifyTarget(config.notify);
|
|
314
319
|
return {
|
|
315
320
|
context: 'icqq',
|
|
316
321
|
id,
|
|
@@ -327,6 +332,7 @@ export function resolveIcqqConfig(config: IcqqEndpointConfig): ResolvedIcqqConfi
|
|
|
327
332
|
...(autoServer != null ? { autoServer } : {}),
|
|
328
333
|
...(qqnt != null ? { qqnt } : {}),
|
|
329
334
|
...(ntLogin != null ? { ntLogin } : {}),
|
|
335
|
+
...(notify ? { notify } : {}),
|
|
330
336
|
};
|
|
331
337
|
}
|
|
332
338
|
|
|
@@ -456,19 +462,37 @@ export function formatOutboundBody(payload: unknown): Sendable {
|
|
|
456
462
|
* quote or whitespace are dropped: a standalone element cannot carry the quote.
|
|
457
463
|
*/
|
|
458
464
|
export function formatOutboundMessages(payload: unknown): Sendable[] {
|
|
465
|
+
return formatOutboundMessageParts(payload).map(part => part.message);
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
/** Native bubble and the exact source segment positions which produced it. */
|
|
469
|
+
export interface IcqqOutboundMessagePart {
|
|
470
|
+
readonly message: Sendable;
|
|
471
|
+
readonly sourceIndices?: readonly number[];
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
export function formatOutboundMessageParts(payload: unknown): IcqqOutboundMessagePart[] {
|
|
459
475
|
if (!Array.isArray(payload)) {
|
|
460
|
-
|
|
476
|
+
if (isWireSegment(payload)) return formatOutboundMessageParts([payload]);
|
|
477
|
+
const message = formatOutboundBody(payload);
|
|
478
|
+
return [{ message, ...(typeof payload === 'string' && message !== payload ? {} : { sourceIndices: [0] }) }];
|
|
461
479
|
}
|
|
462
|
-
const groups:
|
|
463
|
-
for (const
|
|
464
|
-
|
|
465
|
-
|
|
480
|
+
const groups: { element: string | MessageElem; sourceIndex: number }[][] = [[]];
|
|
481
|
+
for (const [sourceIndex, source] of payload.entries()) {
|
|
482
|
+
for (const element of formatOutboundElements([source])) {
|
|
483
|
+
const item = { element, sourceIndex };
|
|
484
|
+
if (isStandaloneElement(element)) groups.push([item], []);
|
|
485
|
+
else groups.at(-1)!.push(item);
|
|
486
|
+
}
|
|
466
487
|
}
|
|
467
|
-
const messages = groups.filter(group => group.some(element => typeof element === 'string'
|
|
488
|
+
const messages = groups.filter(group => group.some(({ element }) => typeof element === 'string'
|
|
468
489
|
? element.trim() !== ''
|
|
469
490
|
: element.type !== 'reply' && element.type !== 'quote'));
|
|
470
|
-
if (messages.length === 0) return ['\u200b'];
|
|
471
|
-
return messages.map(group =>
|
|
491
|
+
if (messages.length === 0) return [{ message: '\u200b', sourceIndices: [] }];
|
|
492
|
+
return messages.map(group => ({
|
|
493
|
+
message: group.length === 1 ? group[0]!.element : group.map(item => item.element),
|
|
494
|
+
sourceIndices: [...new Set(group.map(item => item.sourceIndex))],
|
|
495
|
+
}));
|
|
472
496
|
}
|
|
473
497
|
|
|
474
498
|
function isStandaloneElement(element: string | MessageElem): element is MessageElem {
|