@zhin.js/adapter-icqq 5.0.2 → 6.0.0
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 +13 -0
- package/README.md +30 -2
- package/client/LoginAssistPanel.tsx +38 -3
- package/dist/index.js +2 -2
- package/lib/adapter.d.ts +1 -0
- package/lib/adapter.d.ts.map +1 -1
- package/lib/adapter.js +2 -1
- package/lib/adapter.js.map +1 -1
- package/lib/endpoint.d.ts.map +1 -1
- package/lib/endpoint.js +28 -6
- package/lib/endpoint.js.map +1 -1
- package/lib/icqq-inbound.d.ts +7 -0
- package/lib/icqq-inbound.d.ts.map +1 -1
- package/lib/icqq-inbound.js +24 -1
- package/lib/icqq-inbound.js.map +1 -1
- package/lib/icqq-login-assist-bridge.d.ts +5 -0
- package/lib/icqq-login-assist-bridge.d.ts.map +1 -0
- package/lib/icqq-login-assist-bridge.js +148 -0
- package/lib/icqq-login-assist-bridge.js.map +1 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +2 -0
- package/lib/index.js.map +1 -1
- package/lib/login-assist-routes.d.ts +7 -0
- package/lib/login-assist-routes.d.ts.map +1 -0
- package/lib/login-assist-routes.js +29 -0
- package/lib/login-assist-routes.js.map +1 -0
- package/lib/login-ipc-contract.d.ts +44 -0
- package/lib/login-ipc-contract.d.ts.map +1 -0
- package/lib/login-ipc-contract.js +35 -0
- package/lib/login-ipc-contract.js.map +1 -0
- package/lib/protocol.d.ts +32 -1
- package/lib/protocol.d.ts.map +1 -1
- package/lib/protocol.js +23 -0
- package/lib/protocol.js.map +1 -1
- package/lib/typing-indicator.d.ts.map +1 -1
- package/lib/typing-indicator.js +4 -0
- package/lib/typing-indicator.js.map +1 -1
- package/package.json +13 -13
- package/src/adapter.ts +2 -1
- package/src/endpoint.ts +35 -6
- package/src/icqq-inbound.ts +36 -2
- package/src/icqq-login-assist-bridge.ts +196 -0
- package/src/index.ts +2 -0
- package/src/login-assist-routes.ts +39 -0
- package/src/login-ipc-contract.ts +52 -0
- package/src/protocol.ts +32 -1
- package/src/typing-indicator.ts +4 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"typing-indicator.d.ts","sourceRoot":"","sources":["../src/typing-indicator.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAIL,KAAK,qBAAqB,EAC1B,KAAK,eAAe,EACrB,MAAM,gBAAgB,CAAC;AAIxB,MAAM,WAAW,yBAAyB;IACxC,WAAW;IACX,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW;IACX,YAAY,EAAE,MAAM,CAAC;IACrB,iBAAiB;IACjB,UAAU,EAAE,OAAO,CAAC;IACpB,iBAAiB;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW;IACX,aAAa,CAAC,EAAE,OAAO,CAAC,qBAAqB,CAAC,CAAC;IAC/C,WAAW;IACX,WAAW,CAAC,EAAE,OAAO,CAAC,qBAAqB,CAAC,CAAC;CAC9C;AAuBD,qBAAa,0BAA0B;IACrC,OAAO,CAAC,OAAO,CAAyB;IACxC,OAAO,CAAC,MAAM,CAA4B;IAC1C,OAAO,CAAC,QAAQ,CAAe;gBAEnB,QAAQ,EAAE,YAAY,EAAE,MAAM,GAAE,OAAO,CAAC,yBAAyB,CAAM;IAgBnF;;OAEG;IACH,OAAO,CAAC,eAAe;
|
|
1
|
+
{"version":3,"file":"typing-indicator.d.ts","sourceRoot":"","sources":["../src/typing-indicator.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAIL,KAAK,qBAAqB,EAC1B,KAAK,eAAe,EACrB,MAAM,gBAAgB,CAAC;AAIxB,MAAM,WAAW,yBAAyB;IACxC,WAAW;IACX,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW;IACX,YAAY,EAAE,MAAM,CAAC;IACrB,iBAAiB;IACjB,UAAU,EAAE,OAAO,CAAC;IACpB,iBAAiB;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW;IACX,aAAa,CAAC,EAAE,OAAO,CAAC,qBAAqB,CAAC,CAAC;IAC/C,WAAW;IACX,WAAW,CAAC,EAAE,OAAO,CAAC,qBAAqB,CAAC,CAAC;CAC9C;AAuBD,qBAAa,0BAA0B;IACrC,OAAO,CAAC,OAAO,CAAyB;IACxC,OAAO,CAAC,MAAM,CAA4B;IAC1C,OAAO,CAAC,QAAQ,CAAe;gBAEnB,QAAQ,EAAE,YAAY,EAAE,MAAM,GAAE,OAAO,CAAC,yBAAyB,CAAM;IAgBnF;;OAEG;IACH,OAAO,CAAC,eAAe;IA2EvB;;OAEG;IACG,KAAK,CAAC,OAAO,EAAE;QACnB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,SAAS,EAAE,MAAM,CAAC;QAClB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC;KAChC,GAAG,OAAO,CAAC,eAAe,CAAC;IAoD5B;;OAEG;IACG,IAAI,CAAC,OAAO,EAAE;QAClB,SAAS,EAAE,MAAM,CAAC;QAClB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,GAAG,OAAO,CAAC,IAAI,CAAC;IAqBjB;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAM9B;;OAEG;IACH,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,yBAAyB,CAAC,GAAG,IAAI;IAI9D;;OAEG;IACH,SAAS,IAAI,yBAAyB;CAGvC;AAID;;GAEG;AACH,wBAAgB,gCAAgC,CAC9C,QAAQ,EAAE,YAAY,EACtB,MAAM,CAAC,EAAE,OAAO,CAAC,yBAAyB,CAAC,GAC1C,0BAA0B,CAE5B;AAED;;GAEG;AACH,wBAAsB,wBAAwB,CAC5C,QAAQ,EAAE,YAAY,EACtB,OAAO,EAAE;IACP,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC;CAChC,EACD,MAAM,CAAC,EAAE,OAAO,CAAC,yBAAyB,CAAC,GAC1C,OAAO,CAAC,eAAe,CAAC,CAG1B;AAID,OAAO,QAAQ,eAAe,CAAC;IAC7B,UAAU,YAAY;QACpB,2BAA2B;QAC3B,gBAAgB,CAAC,EAAE,0BAA0B,CAAC;KAC/C;CACF;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,YAAY,EACtB,MAAM,CAAC,EAAE,OAAO,CAAC,yBAAyB,CAAC,GAC1C,0BAA0B,CAK5B"}
|
package/lib/typing-indicator.js
CHANGED
|
@@ -80,10 +80,14 @@ export class ICQQTypingIndicatorManager {
|
|
|
80
80
|
else if (options.userId) {
|
|
81
81
|
this.endpoint.logger.debug('[ICQQ:TypingIndicator] sending private message', {
|
|
82
82
|
userId: options.userId,
|
|
83
|
+
groupId: options.groupId,
|
|
83
84
|
});
|
|
84
85
|
return await this.endpoint.$sendMessage({
|
|
85
86
|
type: 'private',
|
|
86
87
|
id: options.userId,
|
|
88
|
+
...(options.groupId
|
|
89
|
+
? { parent: { type: 'group', id: options.groupId } }
|
|
90
|
+
: {}),
|
|
87
91
|
context: 'icqq',
|
|
88
92
|
endpoint: this.endpoint.$id,
|
|
89
93
|
content: [{ type: 'text', data: { text: content } }],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"typing-indicator.js","sourceRoot":"","sources":["../src/typing-indicator.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"typing-indicator.js","sourceRoot":"","sources":["../src/typing-indicator.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zhin.js/adapter-icqq",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "6.0.0",
|
|
4
4
|
"description": "Zhin.js adapter for ICQQ (QQ Bot)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/index.js",
|
|
@@ -48,26 +48,26 @@
|
|
|
48
48
|
"@radix-ui/themes": "^3.2.1",
|
|
49
49
|
"@types/react": "^19.2.17",
|
|
50
50
|
"@types/react-dom": "^19.2.3",
|
|
51
|
-
"lucide-react": "^1.
|
|
51
|
+
"lucide-react": "^1.21.0",
|
|
52
52
|
"radix-ui": "^1.5.0",
|
|
53
53
|
"typescript": "^6.0.3",
|
|
54
|
-
"@zhin.js/agent": "0.
|
|
55
|
-
"@zhin.js/cli": "1.0.
|
|
54
|
+
"@zhin.js/agent": "1.0.1",
|
|
55
|
+
"@zhin.js/cli": "1.0.91",
|
|
56
56
|
"@zhin.js/client": "2.0.3",
|
|
57
57
|
"@zhin.js/contract": "1.0.1",
|
|
58
|
-
"@zhin.js/core": "1.3.
|
|
59
|
-
"@zhin.js/host-api": "2.0.
|
|
60
|
-
"@zhin.js/host-router": "2.0.
|
|
61
|
-
"zhin.js": "4.0
|
|
58
|
+
"@zhin.js/core": "1.3.2",
|
|
59
|
+
"@zhin.js/host-api": "2.0.3",
|
|
60
|
+
"@zhin.js/host-router": "2.0.1",
|
|
61
|
+
"zhin.js": "4.1.0"
|
|
62
62
|
},
|
|
63
63
|
"peerDependencies": {
|
|
64
|
-
"@zhin.js/agent": "0.
|
|
64
|
+
"@zhin.js/agent": "1.0.1",
|
|
65
65
|
"@zhin.js/client": "2.0.3",
|
|
66
|
-
"@zhin.js/host-api": "2.0.
|
|
66
|
+
"@zhin.js/host-api": "2.0.3",
|
|
67
67
|
"@zhin.js/contract": "1.0.1",
|
|
68
|
-
"@zhin.js/core": "1.3.
|
|
69
|
-
"@zhin.js/host-router": "2.0.
|
|
70
|
-
"zhin.js": "4.0
|
|
68
|
+
"@zhin.js/core": "1.3.2",
|
|
69
|
+
"@zhin.js/host-router": "2.0.1",
|
|
70
|
+
"zhin.js": "4.1.0"
|
|
71
71
|
},
|
|
72
72
|
"peerDependenciesMeta": {
|
|
73
73
|
"@zhin.js/agent": {
|
package/src/adapter.ts
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* ICQQ 适配器 — 通过 @icqqjs/cli 守护进程 IPC 管理 Endpoint 实例
|
|
3
3
|
*/
|
|
4
|
-
import { formatCompact, Adapter, Plugin } from 'zhin.js';
|
|
4
|
+
import { formatCompact, Adapter, Plugin, OUTBOUND_RICH_SEGMENT_POLICY_IM_FULL } from 'zhin.js';
|
|
5
5
|
import { IcqqEndpoint } from "./endpoint.js";
|
|
6
6
|
import type { IcqqEndpointConfig, IpcMemberInfo } from "./types.js";
|
|
7
7
|
import { Actions } from "./protocol.js";
|
|
8
8
|
|
|
9
9
|
export class IcqqAdapter extends Adapter<IcqqEndpoint> {
|
|
10
10
|
static override readonly capabilities = ['inbound', 'outbound'] as const;
|
|
11
|
+
static override outboundRichSegmentPolicy = OUTBOUND_RICH_SEGMENT_POLICY_IM_FULL;
|
|
11
12
|
|
|
12
13
|
constructor(plugin: Plugin) {
|
|
13
14
|
super(plugin, "icqq", []);
|
package/src/endpoint.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* 不再直接依赖 @icqqjs/icqq 协议库。
|
|
5
5
|
* 登录由 `icqq login` 完成,本 Endpoint 只负责连接守护进程并收发消息。
|
|
6
6
|
*/
|
|
7
|
-
import { formatCompact, Endpoint, Message, segment, SendContent, SendOptions, type QuotedMessagePayload
|
|
7
|
+
import { formatCompact, Endpoint, Message, segment, SendContent, SendOptions, type QuotedMessagePayload,} from 'zhin.js';
|
|
8
8
|
import type {
|
|
9
9
|
IcqqEndpointConfig,
|
|
10
10
|
IcqqSenderInfo,
|
|
@@ -49,9 +49,16 @@ import {
|
|
|
49
49
|
shouldRefreshListsOnMeta,
|
|
50
50
|
type IcqqIpcRawEvent,
|
|
51
51
|
} from "./icqq-side-events.js";
|
|
52
|
-
import {
|
|
52
|
+
import {
|
|
53
|
+
disposeIcqqLoginAssistBridge,
|
|
54
|
+
handleIcqqLoginIpcEvent,
|
|
55
|
+
} from "./icqq-login-assist-bridge.js";
|
|
53
56
|
import { parseIcqqGetMsgResponse } from "./get-msg.js";
|
|
54
57
|
import { enrichQuotedPayloadWithForward, isForwardPlaceholderPayload } from "./forward-msg.js";
|
|
58
|
+
import {
|
|
59
|
+
enableTypingIndicator,
|
|
60
|
+
type ICQQTypingIndicatorManager,
|
|
61
|
+
} from "./typing-indicator.js";
|
|
55
62
|
|
|
56
63
|
export class IcqqEndpoint implements Endpoint<IcqqEndpointConfig, IcqqIpcMessageEvent> {
|
|
57
64
|
$connected = false;
|
|
@@ -280,6 +287,7 @@ export class IcqqEndpoint implements Endpoint<IcqqEndpointConfig, IcqqIpcMessage
|
|
|
280
287
|
}
|
|
281
288
|
this.subscriptions = [];
|
|
282
289
|
this.inboundDeduper.clear();
|
|
290
|
+
disposeIcqqLoginAssistBridge(this.$id);
|
|
283
291
|
this.ipc?.close();
|
|
284
292
|
this.$connected = false;
|
|
285
293
|
this.logger.info(formatCompact( { op: "disconnect", endpoint: this.$id }));
|
|
@@ -288,6 +296,11 @@ export class IcqqEndpoint implements Endpoint<IcqqEndpointConfig, IcqqIpcMessage
|
|
|
288
296
|
// ── 消息处理 ───────────────────────────────────────────────────────
|
|
289
297
|
|
|
290
298
|
private handleEvent(event: IpcEvent): void {
|
|
299
|
+
if (event.event?.startsWith("system.login.")) {
|
|
300
|
+
handleIcqqLoginIpcEvent(this, event.event, event.data);
|
|
301
|
+
return;
|
|
302
|
+
}
|
|
303
|
+
|
|
291
304
|
const payload = unwrapIcqqIpcEventPayload(event);
|
|
292
305
|
if (!payload || typeof payload !== "object") {
|
|
293
306
|
if (process.env.ICQQ_IPC_LOG_RAW === "1") {
|
|
@@ -503,6 +516,9 @@ export class IcqqEndpoint implements Endpoint<IcqqEndpointConfig, IcqqIpcMessage
|
|
|
503
516
|
$channel: {
|
|
504
517
|
id: normalized.channelId,
|
|
505
518
|
type: normalized.channelType,
|
|
519
|
+
...(normalized.channelParentGroupId
|
|
520
|
+
? { parent: { type: 'group' as const, id: normalized.channelParentGroupId } }
|
|
521
|
+
: {}),
|
|
506
522
|
},
|
|
507
523
|
$content: normalized.content,
|
|
508
524
|
$quote_id: quoteId,
|
|
@@ -641,17 +657,30 @@ export class IcqqEndpoint implements Endpoint<IcqqEndpointConfig, IcqqIpcMessage
|
|
|
641
657
|
|
|
642
658
|
async $sendMessage(options: SendOptions): Promise<string> {
|
|
643
659
|
const outboundMedia = resolveIcqqOutboundMediaMode(this.$config);
|
|
644
|
-
const
|
|
660
|
+
const qrcodeContent = options.content;
|
|
661
|
+
const content = materializeOutboundBase64(qrcodeContent, outboundMedia);
|
|
645
662
|
const message = buildIcqqIpcMessageImpl(content);
|
|
646
663
|
|
|
647
664
|
let action: string;
|
|
648
665
|
let params: Record<string, unknown>;
|
|
649
666
|
|
|
650
667
|
switch (options.type) {
|
|
651
|
-
case "private":
|
|
652
|
-
|
|
653
|
-
|
|
668
|
+
case "private": {
|
|
669
|
+
const groupParent =
|
|
670
|
+
options.parent?.type === "group" ? options.parent.id : undefined;
|
|
671
|
+
if (groupParent) {
|
|
672
|
+
action = Actions.SEND_TEMP_MSG;
|
|
673
|
+
params = {
|
|
674
|
+
group_id: Number(groupParent),
|
|
675
|
+
user_id: Number(options.id),
|
|
676
|
+
message,
|
|
677
|
+
};
|
|
678
|
+
} else {
|
|
679
|
+
action = Actions.SEND_PRIVATE_MSG;
|
|
680
|
+
params = { user_id: Number(options.id), message };
|
|
681
|
+
}
|
|
654
682
|
break;
|
|
683
|
+
}
|
|
655
684
|
case "group":
|
|
656
685
|
action = Actions.SEND_GROUP_MSG;
|
|
657
686
|
params = { group_id: Number(options.id), message };
|
package/src/icqq-inbound.ts
CHANGED
|
@@ -30,6 +30,8 @@ export interface IcqqIpcMessageEvent extends IcqqIpcEventBase {
|
|
|
30
30
|
user_uid?: string;
|
|
31
31
|
nickname?: string;
|
|
32
32
|
card?: string;
|
|
33
|
+
/** 群临时会话来源群号 */
|
|
34
|
+
group_id?: number;
|
|
33
35
|
/** NT/IPC 群成员角色:owner | admin | member */
|
|
34
36
|
role?: GroupRole | string;
|
|
35
37
|
};
|
|
@@ -81,6 +83,8 @@ export interface NormalizedIcqqInbound {
|
|
|
81
83
|
idSource: "message_id" | "msg_id" | "seq" | "synthetic";
|
|
82
84
|
channelType: "group" | "private";
|
|
83
85
|
channelId: string;
|
|
86
|
+
/** 群临时会话:来源群号 */
|
|
87
|
+
channelParentGroupId?: string;
|
|
84
88
|
userId: string;
|
|
85
89
|
nickname: string;
|
|
86
90
|
/** 群聊时来自 IPC sender.role(私聊无) */
|
|
@@ -204,9 +208,38 @@ export function shouldSkipSelfInboundMessage(
|
|
|
204
208
|
return Number(data.self_id) === Number(data.user_id);
|
|
205
209
|
}
|
|
206
210
|
|
|
211
|
+
/** 群临时会话私聊:icqq message_type=private & sub_type=group */
|
|
212
|
+
export function isIcqqGroupTempPrivateMessage(data: IcqqIpcMessageEvent): boolean {
|
|
213
|
+
const messageType =
|
|
214
|
+
data.message_type ??
|
|
215
|
+
(data.type === "group" || data.type === "private" ? data.type : undefined);
|
|
216
|
+
if (messageType !== "private") return false;
|
|
217
|
+
if (data.sub_type === "group") return true;
|
|
218
|
+
const groupId = data.sender?.group_id;
|
|
219
|
+
return typeof groupId === "number" && groupId > 0;
|
|
220
|
+
}
|
|
221
|
+
|
|
207
222
|
export function resolveChannelFromIcqqMessage(
|
|
208
223
|
data: IcqqIpcMessageEvent,
|
|
209
|
-
): {
|
|
224
|
+
): {
|
|
225
|
+
channelType: "group" | "private";
|
|
226
|
+
channelId: string;
|
|
227
|
+
channelParentGroupId?: string;
|
|
228
|
+
} {
|
|
229
|
+
if (isIcqqGroupTempPrivateMessage(data)) {
|
|
230
|
+
const groupId = data.sender?.group_id ?? data.group_id;
|
|
231
|
+
const userId = resolveIcqqInboundUserId(
|
|
232
|
+
data as unknown as Record<string, unknown>,
|
|
233
|
+
);
|
|
234
|
+
if (groupId != null && userId != null) {
|
|
235
|
+
return {
|
|
236
|
+
channelType: "private",
|
|
237
|
+
channelId: String(userId),
|
|
238
|
+
channelParentGroupId: String(groupId),
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
210
243
|
const messageType =
|
|
211
244
|
data.message_type ??
|
|
212
245
|
(data.type === "group" || data.type === "private" ? data.type : undefined);
|
|
@@ -594,7 +627,7 @@ export function normalizeIcqqInboundMessage(
|
|
|
594
627
|
const ext = data as IcqqIpcMessageEvent & Record<string, unknown>;
|
|
595
628
|
const userIdNum = resolveIcqqInboundUserId(ext);
|
|
596
629
|
if (userIdNum == null) return null;
|
|
597
|
-
const { channelType, channelId } = resolveChannelFromIcqqMessage(data);
|
|
630
|
+
const { channelType, channelId, channelParentGroupId } = resolveChannelFromIcqqMessage(data);
|
|
598
631
|
const resolved = resolveIcqqInboundMessageId(data, channelId);
|
|
599
632
|
const nickname =
|
|
600
633
|
data.sender?.nickname ?? data.nickname ?? String(userIdNum);
|
|
@@ -608,6 +641,7 @@ export function normalizeIcqqInboundMessage(
|
|
|
608
641
|
idSource: resolved.source,
|
|
609
642
|
channelType,
|
|
610
643
|
channelId,
|
|
644
|
+
channelParentGroupId,
|
|
611
645
|
userId: String(userIdNum),
|
|
612
646
|
nickname,
|
|
613
647
|
senderRole,
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 将 icqq 守护进程 IPC 的 system.login.* 事件桥接到 core LoginAssist。
|
|
3
|
+
*
|
|
4
|
+
* 推送契约(@icqqjs/cli IpcEvent):
|
|
5
|
+
* { id: "*", event: "system.login.auth", data: { url, device } }
|
|
6
|
+
* 须在 endpoint.handleEvent 中按 event.event 先行处理(非 OneBot post_type)。
|
|
7
|
+
*
|
|
8
|
+
* 续传契约(LoginIpcActions ↔ LoginFlow)见 login-ipc-contract.ts。
|
|
9
|
+
*/
|
|
10
|
+
import type { LoginAssist, LoginAssistType } from '@zhin.js/core';
|
|
11
|
+
import type { IcqqEndpoint } from './endpoint.js';
|
|
12
|
+
import {
|
|
13
|
+
LoginIpcActions,
|
|
14
|
+
type IcqqLoginDeviceInfo,
|
|
15
|
+
} from './login-ipc-contract.js';
|
|
16
|
+
|
|
17
|
+
const activeByEndpoint = new Set<string>();
|
|
18
|
+
|
|
19
|
+
function asRecord(value: unknown): Record<string, unknown> | null {
|
|
20
|
+
return value && typeof value === 'object' && !Array.isArray(value)
|
|
21
|
+
? (value as Record<string, unknown>)
|
|
22
|
+
: null;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function resolveQrcodeImage(data: Record<string, unknown>): string | undefined {
|
|
26
|
+
const image = data.image;
|
|
27
|
+
if (image && typeof image === 'object') {
|
|
28
|
+
const buf = image as { type?: string; data?: string };
|
|
29
|
+
if (buf.type === 'Buffer' && typeof buf.data === 'string') {
|
|
30
|
+
return `data:image/png;base64,${buf.data}`;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
if (typeof data.url === 'string' && data.url.startsWith('data:image')) {
|
|
34
|
+
return data.url;
|
|
35
|
+
}
|
|
36
|
+
return undefined;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function mapLoginEvent(
|
|
40
|
+
eventName: string,
|
|
41
|
+
data: Record<string, unknown>,
|
|
42
|
+
): { type: LoginAssistType; payload: Record<string, unknown> } | null {
|
|
43
|
+
switch (eventName) {
|
|
44
|
+
case 'system.login.qrcode':
|
|
45
|
+
return {
|
|
46
|
+
type: 'qrcode',
|
|
47
|
+
payload: {
|
|
48
|
+
message: '请使用手机 QQ 扫码登录',
|
|
49
|
+
image: resolveQrcodeImage(data),
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
case 'system.login.slider':
|
|
53
|
+
return {
|
|
54
|
+
type: 'slider',
|
|
55
|
+
payload: {
|
|
56
|
+
message: '请完成滑块验证并提交 ticket',
|
|
57
|
+
url: String(data.url ?? ''),
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
case 'system.login.device':
|
|
61
|
+
return {
|
|
62
|
+
type: 'device',
|
|
63
|
+
payload: {
|
|
64
|
+
message: data.phone
|
|
65
|
+
? `请完成设备锁验证(密保手机 ${String(data.phone)})`
|
|
66
|
+
: '请完成设备锁验证',
|
|
67
|
+
url: String(data.url ?? ''),
|
|
68
|
+
phone: data.phone,
|
|
69
|
+
},
|
|
70
|
+
};
|
|
71
|
+
case 'system.login.auth':
|
|
72
|
+
return {
|
|
73
|
+
type: 'auth',
|
|
74
|
+
payload: {
|
|
75
|
+
message: '请在浏览器完成身份验证(需使用下方设备信息)',
|
|
76
|
+
url: String(data.url ?? ''),
|
|
77
|
+
device: data.device as IcqqLoginDeviceInfo | undefined,
|
|
78
|
+
},
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/** 对齐 @icqqjs/cli LoginFlow.handleSubmit → Client 方法 */
|
|
85
|
+
async function continueLoginAfterAssist(
|
|
86
|
+
endpoint: IcqqEndpoint,
|
|
87
|
+
loginType: LoginAssistType,
|
|
88
|
+
value: string | Record<string, unknown>,
|
|
89
|
+
): Promise<void> {
|
|
90
|
+
if (!endpoint.ipc || endpoint.ipc.closed) return;
|
|
91
|
+
|
|
92
|
+
try {
|
|
93
|
+
if (loginType === 'slider') {
|
|
94
|
+
const ticket =
|
|
95
|
+
typeof value === 'string'
|
|
96
|
+
? value.trim()
|
|
97
|
+
: typeof value === 'object' && value !== null
|
|
98
|
+
? String((value as { ticket?: string }).ticket ?? '').trim()
|
|
99
|
+
: '';
|
|
100
|
+
if (!ticket) return;
|
|
101
|
+
await endpoint.ipc.request(LoginIpcActions.SUBMIT_SLIDER, { ticket });
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (loginType === 'sms') {
|
|
106
|
+
const code = typeof value === 'string' ? value.trim() : '';
|
|
107
|
+
if (!code) return;
|
|
108
|
+
await endpoint.ipc.request(LoginIpcActions.SUBMIT_SMS_CODE, { code });
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if (loginType === 'device') {
|
|
113
|
+
if (
|
|
114
|
+
typeof value === 'object' &&
|
|
115
|
+
value !== null &&
|
|
116
|
+
(value as { action?: string }).action === 'sms'
|
|
117
|
+
) {
|
|
118
|
+
await endpoint.ipc.request(LoginIpcActions.SEND_SMS_CODE, {});
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
if (typeof value === 'string' && value.trim()) {
|
|
122
|
+
await endpoint.ipc.request(LoginIpcActions.SUBMIT_SMS_CODE, {
|
|
123
|
+
code: value.trim(),
|
|
124
|
+
});
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// qrcode / device 链接确认 / auth 237 确认 → client.login()
|
|
130
|
+
await endpoint.ipc.request(LoginIpcActions.LOGIN, {});
|
|
131
|
+
} catch (err) {
|
|
132
|
+
endpoint.logger.warn(
|
|
133
|
+
`登录辅助提交后 IPC 续传失败:${
|
|
134
|
+
err instanceof Error ? err.message : String(err)
|
|
135
|
+
}(action 须与 @icqqjs/cli action-catalog 一致)`,
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export function handleIcqqLoginIpcEvent(
|
|
141
|
+
endpoint: IcqqEndpoint,
|
|
142
|
+
eventName: string,
|
|
143
|
+
rawData: unknown,
|
|
144
|
+
): void {
|
|
145
|
+
if (!eventName.startsWith('system.login.')) return;
|
|
146
|
+
|
|
147
|
+
const root = endpoint.adapter.plugin.root;
|
|
148
|
+
const loginAssist = root.inject('loginAssist') as LoginAssist | undefined;
|
|
149
|
+
if (!loginAssist) {
|
|
150
|
+
endpoint.logger.debug(`收到 ${eventName},但 loginAssist 未启用`);
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
if (eventName === 'system.login.error') {
|
|
155
|
+
const data = asRecord(rawData);
|
|
156
|
+
endpoint.logger.warn(
|
|
157
|
+
`icqq 登录错误:${String(data?.message ?? 'unknown')}${
|
|
158
|
+
data?.code != null ? ` [code=${String(data.code)}]` : ''
|
|
159
|
+
}`,
|
|
160
|
+
);
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const data = asRecord(rawData);
|
|
165
|
+
if (!data) return;
|
|
166
|
+
|
|
167
|
+
const mapped = mapLoginEvent(eventName, data);
|
|
168
|
+
if (!mapped) return;
|
|
169
|
+
|
|
170
|
+
const guardKey = endpoint.$id;
|
|
171
|
+
if (activeByEndpoint.has(guardKey)) {
|
|
172
|
+
endpoint.logger.debug(`跳过重复登录待办:${eventName}`);
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
activeByEndpoint.add(guardKey);
|
|
176
|
+
|
|
177
|
+
endpoint.logger.info(`icqq 登录待办:${mapped.type}(${eventName})`);
|
|
178
|
+
|
|
179
|
+
void loginAssist
|
|
180
|
+
.waitForInput('icqq', endpoint.$id, mapped.type, mapped.payload)
|
|
181
|
+
.then((value) => continueLoginAfterAssist(endpoint, mapped.type, value))
|
|
182
|
+
.catch((err) => {
|
|
183
|
+
if (err instanceof Error && err.message !== 'cancelled') {
|
|
184
|
+
endpoint.logger.warn(`登录辅助已取消或失败:${err.message}`);
|
|
185
|
+
}
|
|
186
|
+
})
|
|
187
|
+
.finally(() => {
|
|
188
|
+
activeByEndpoint.delete(guardKey);
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
export function disposeIcqqLoginAssistBridge(endpointId: string): void {
|
|
193
|
+
activeByEndpoint.delete(endpointId);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
export type { IcqqLoginDeviceInfo } from './login-ipc-contract.js';
|
package/src/index.ts
CHANGED
|
@@ -14,6 +14,7 @@ import { PageManager } from "@zhin.js/host-api";
|
|
|
14
14
|
import { IcqqAdapter } from "./adapter.js";
|
|
15
15
|
import { registerTools } from "./tools/index.js";
|
|
16
16
|
import { registerRoutes } from "./routes.js";
|
|
17
|
+
import { registerLoginAssistRoutes } from "./login-assist-routes.js";
|
|
17
18
|
|
|
18
19
|
declare module "zhin.js" {
|
|
19
20
|
namespace Plugin {
|
|
@@ -76,4 +77,5 @@ useContext("web", (pageManager) => {
|
|
|
76
77
|
// ── HTTP 路由 ──────────────────────────────────────────────────────
|
|
77
78
|
useContext("router", "icqq", async (router: Router, icqq: IcqqAdapter) => {
|
|
78
79
|
registerRoutes(router, icqq, root);
|
|
80
|
+
registerLoginAssistRoutes(router, root);
|
|
79
81
|
});
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* loginAssist HTTP 路由(供 Web 控制台 /icqq 登录辅助 Tab)
|
|
3
|
+
*/
|
|
4
|
+
import type { Router } from "@zhin.js/host-router";
|
|
5
|
+
import type { Plugin } from "zhin.js";
|
|
6
|
+
|
|
7
|
+
export function registerLoginAssistRoutes(router: Router, root: Plugin): void {
|
|
8
|
+
const loginAssist = root.inject("loginAssist");
|
|
9
|
+
if (!loginAssist) return;
|
|
10
|
+
|
|
11
|
+
router.get("/api/login-assist/pending", async (ctx) => {
|
|
12
|
+
ctx.body = loginAssist.listPending();
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
router.post("/api/login-assist/submit", async (ctx: any) => {
|
|
16
|
+
const body = (ctx.request.body ?? {}) as {
|
|
17
|
+
id?: string;
|
|
18
|
+
value?: string | Record<string, unknown>;
|
|
19
|
+
};
|
|
20
|
+
if (!body.id) {
|
|
21
|
+
ctx.status = 400;
|
|
22
|
+
ctx.body = { success: false, message: "missing id" };
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
const ok = loginAssist.submit(body.id, body.value ?? "");
|
|
26
|
+
ctx.body = { success: ok };
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
router.post("/api/login-assist/cancel", async (ctx: any) => {
|
|
30
|
+
const body = (ctx.request.body ?? {}) as { id?: string; reason?: string };
|
|
31
|
+
if (!body.id) {
|
|
32
|
+
ctx.status = 400;
|
|
33
|
+
ctx.body = { success: false, message: "missing id" };
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
const ok = loginAssist.cancel(body.id, body.reason);
|
|
37
|
+
ctx.body = { success: ok };
|
|
38
|
+
});
|
|
39
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ICQQ 登录 IPC 契约(与 @icqqjs/cli / @icqqjs/icqq 对齐)
|
|
3
|
+
*
|
|
4
|
+
* **推送(Daemon → Client)** — 见 @icqqjs/cli `src/daemon/protocol.ts` 的 `IpcEvent`:
|
|
5
|
+
* ```json
|
|
6
|
+
* { "id": "*", "event": "system.login.auth", "data": { "url", "device" } }
|
|
7
|
+
* ```
|
|
8
|
+
* 事件名与载荷形状以 @icqqjs/icqq `EventMap` 为准(非 OneBot `post_type`)。
|
|
9
|
+
*
|
|
10
|
+
* **续传(Client → Daemon)** — 与 CLI `LoginFlow` / `AccountBootstrap` 对 icqq Client 的调用一致,
|
|
11
|
+
* action 名为 Client 方法的 snake_case;收录于守护进程 `action-catalog` 后可通过 IPC invoke。
|
|
12
|
+
*
|
|
13
|
+
* @see https://github.com/icqqjs/cli/blob/master/src/daemon/protocol.ts
|
|
14
|
+
* @see https://github.com/icqqjs/cli/blob/master/src/lib/account-bootstrap.ts
|
|
15
|
+
* @see https://github.com/icqqjs/cli/blob/master/src/components/LoginFlow.tsx
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
/** system.login.auth 等设备指纹(@icqqjs/icqq EventMap) */
|
|
19
|
+
export interface IcqqLoginDeviceInfo {
|
|
20
|
+
guid?: string;
|
|
21
|
+
qimei?: string;
|
|
22
|
+
qimei36?: string;
|
|
23
|
+
subappid?: string;
|
|
24
|
+
platform?: string;
|
|
25
|
+
brand?: string;
|
|
26
|
+
model?: string;
|
|
27
|
+
bssid?: string;
|
|
28
|
+
devInfo?: string;
|
|
29
|
+
sysVersion?: string;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** 登录续传 IPC action(与 LoginFlow → Client 方法一一对应) */
|
|
33
|
+
export const LoginIpcActions = {
|
|
34
|
+
/** 扫码确认 / 设备锁链接确认 / auth 237 验证完成后继续 — client.login() */
|
|
35
|
+
LOGIN: 'login',
|
|
36
|
+
/** 滑块 ticket — client.submitSlider(ticket) */
|
|
37
|
+
SUBMIT_SLIDER: 'submit_slider',
|
|
38
|
+
/** 设备锁短信验证码 — client.submitSmsCode(code) */
|
|
39
|
+
SUBMIT_SMS_CODE: 'submit_sms_code',
|
|
40
|
+
/** 请求发送设备锁短信 — client.sendSmsCode() */
|
|
41
|
+
SEND_SMS_CODE: 'send_sms_code',
|
|
42
|
+
} as const;
|
|
43
|
+
|
|
44
|
+
export type LoginIpcAction = (typeof LoginIpcActions)[keyof typeof LoginIpcActions];
|
|
45
|
+
|
|
46
|
+
/** CLI LoginFlow 237 验证步骤(供 Web 控制台展示) */
|
|
47
|
+
export const AUTH_DEVICE_STEPS = [
|
|
48
|
+
'打开上方验证链接,正常完成验证流程,直到发送完验证码,不要点击「我已发送」',
|
|
49
|
+
'复制下方 JS,打开浏览器开发者工具(F12)→ Console,粘贴并回车',
|
|
50
|
+
'在弹窗中粘贴设备信息 JSON 并确认(可使用下方单行 JSON)',
|
|
51
|
+
'回到验证页点击「我已发送」,完成 237 验证后回到控制台点击确认',
|
|
52
|
+
] as const;
|