@zhin.js/adapter-icqq 6.0.2 → 7.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.
Files changed (125) hide show
  1. package/CHANGELOG.md +65 -0
  2. package/README.md +48 -435
  3. package/adapters/icqq.ts +92 -0
  4. package/agent/tools/announce.ts +2 -2
  5. package/agent/tools/essence.ts +2 -2
  6. package/agent/tools/friend_list.ts +2 -2
  7. package/agent/tools/group_files.ts +2 -2
  8. package/agent/tools/group_invite.ts +2 -2
  9. package/agent/tools/group_list.ts +2 -2
  10. package/agent/tools/group_sign.ts +2 -2
  11. package/agent/tools/list_muted.ts +2 -2
  12. package/agent/tools/poke.ts +2 -2
  13. package/agent/tools/send_user_like.ts +2 -2
  14. package/agent/tools/set_anonymous.ts +2 -2
  15. package/agent/tools/set_title.ts +2 -2
  16. package/lib/agent-prompt.d.ts +2 -0
  17. package/lib/{src/agent-prompt.js → agent-prompt.js} +0 -1
  18. package/lib/cq-message.d.ts +9 -0
  19. package/lib/{src/cq-message.js → cq-message.js} +0 -1
  20. package/lib/endpoint.d.ts +101 -0
  21. package/lib/endpoint.js +715 -0
  22. package/lib/forward-msg.d.ts +26 -0
  23. package/lib/{src/forward-msg.js → forward-msg.js} +0 -1
  24. package/lib/icqq-agent-deps.d.ts +25 -0
  25. package/lib/icqq-agent-deps.js +32 -0
  26. package/lib/icqq-guild.d.ts +53 -0
  27. package/lib/{src/icqq-guild.js → icqq-guild.js} +4 -2
  28. package/lib/icqq-inbound.d.ts +139 -0
  29. package/lib/{src/icqq-inbound.js → icqq-inbound.js} +27 -3
  30. package/lib/icqq-inbox.d.ts +33 -0
  31. package/lib/icqq-inbox.js +129 -0
  32. package/lib/index.d.ts +6 -0
  33. package/lib/index.js +6 -0
  34. package/lib/ipc-client.d.ts +73 -0
  35. package/lib/{src/ipc-client.js → ipc-client.js} +0 -1
  36. package/lib/outbound-media.d.ts +13 -0
  37. package/lib/{src/outbound-media.js → outbound-media.js} +0 -1
  38. package/lib/protocol.d.ts +269 -0
  39. package/lib/{src/protocol.js → protocol.js} +124 -2
  40. package/lib/types.d.ts +87 -0
  41. package/lib/{src/types.js → types.js} +0 -1
  42. package/package.json +49 -45
  43. package/plugin.ts +32 -0
  44. package/schema.json +104 -0
  45. package/src/endpoint.ts +704 -795
  46. package/src/icqq-agent-deps.ts +48 -9
  47. package/src/icqq-guild.ts +10 -4
  48. package/src/icqq-inbound.ts +31 -2
  49. package/src/icqq-inbox.ts +155 -0
  50. package/src/index.ts +36 -69
  51. package/src/protocol.ts +191 -1
  52. package/src/types.ts +16 -0
  53. package/client/ICQQManagement.tsx +0 -147
  54. package/client/LoginAssistPanel.tsx +0 -300
  55. package/client/index.tsx +0 -11
  56. package/client/tsconfig.json +0 -7
  57. package/client/utils/api.ts +0 -30
  58. package/dist/index.js +0 -34
  59. package/lib/agent/tools/announce.js +0 -21
  60. package/lib/agent/tools/announce.js.map +0 -1
  61. package/lib/agent/tools/essence.js +0 -22
  62. package/lib/agent/tools/essence.js.map +0 -1
  63. package/lib/agent/tools/friend_list.js +0 -19
  64. package/lib/agent/tools/friend_list.js.map +0 -1
  65. package/lib/agent/tools/group_files.js +0 -29
  66. package/lib/agent/tools/group_files.js.map +0 -1
  67. package/lib/agent/tools/group_invite.js +0 -20
  68. package/lib/agent/tools/group_invite.js.map +0 -1
  69. package/lib/agent/tools/group_list.js +0 -20
  70. package/lib/agent/tools/group_list.js.map +0 -1
  71. package/lib/agent/tools/group_sign.js +0 -19
  72. package/lib/agent/tools/group_sign.js.map +0 -1
  73. package/lib/agent/tools/list_muted.js +0 -23
  74. package/lib/agent/tools/list_muted.js.map +0 -1
  75. package/lib/agent/tools/poke.js +0 -20
  76. package/lib/agent/tools/poke.js.map +0 -1
  77. package/lib/agent/tools/send_user_like.js +0 -22
  78. package/lib/agent/tools/send_user_like.js.map +0 -1
  79. package/lib/agent/tools/set_anonymous.js +0 -22
  80. package/lib/agent/tools/set_anonymous.js.map +0 -1
  81. package/lib/agent/tools/set_title.js +0 -25
  82. package/lib/agent/tools/set_title.js.map +0 -1
  83. package/lib/src/adapter.js +0 -128
  84. package/lib/src/adapter.js.map +0 -1
  85. package/lib/src/agent-prompt.js.map +0 -1
  86. package/lib/src/cq-message.js.map +0 -1
  87. package/lib/src/endpoint.js +0 -755
  88. package/lib/src/endpoint.js.map +0 -1
  89. package/lib/src/forward-msg.js.map +0 -1
  90. package/lib/src/get-msg.js +0 -46
  91. package/lib/src/get-msg.js.map +0 -1
  92. package/lib/src/icqq-agent-deps.js +0 -10
  93. package/lib/src/icqq-agent-deps.js.map +0 -1
  94. package/lib/src/icqq-guild.js.map +0 -1
  95. package/lib/src/icqq-inbound.js.map +0 -1
  96. package/lib/src/icqq-login-assist-bridge.js +0 -148
  97. package/lib/src/icqq-login-assist-bridge.js.map +0 -1
  98. package/lib/src/icqq-side-events.js +0 -130
  99. package/lib/src/icqq-side-events.js.map +0 -1
  100. package/lib/src/index.js +0 -50
  101. package/lib/src/index.js.map +0 -1
  102. package/lib/src/ipc-client.js.map +0 -1
  103. package/lib/src/login-assist-routes.js +0 -29
  104. package/lib/src/login-assist-routes.js.map +0 -1
  105. package/lib/src/login-ipc-contract.js +0 -35
  106. package/lib/src/login-ipc-contract.js.map +0 -1
  107. package/lib/src/outbound-media.js.map +0 -1
  108. package/lib/src/protocol.js.map +0 -1
  109. package/lib/src/routes.js +0 -67
  110. package/lib/src/routes.js.map +0 -1
  111. package/lib/src/segment-mapper.js +0 -2
  112. package/lib/src/segment-mapper.js.map +0 -1
  113. package/lib/src/tools/index.js +0 -23
  114. package/lib/src/tools/index.js.map +0 -1
  115. package/lib/src/types.js.map +0 -1
  116. package/plugin.yml +0 -3
  117. package/src/adapter.ts +0 -151
  118. package/src/get-msg.ts +0 -56
  119. package/src/icqq-login-assist-bridge.ts +0 -196
  120. package/src/icqq-side-events.ts +0 -143
  121. package/src/login-assist-routes.ts +0 -39
  122. package/src/login-ipc-contract.ts +0 -52
  123. package/src/routes.ts +0 -83
  124. package/src/segment-mapper.ts +0 -1
  125. package/src/tools/index.ts +0 -31
@@ -1,143 +0,0 @@
1
- /**
2
- * icqq IPC 非 message 入站:notice / request / meta(对齐 OneBot 与 @icqqjs/icqq EventMap)
3
- */
4
- import { mapNoticeParts, mapRequestParts, resolveSideEventDedupeKey, senderFromId, buildNotice, buildRequest, formatCompact, type OneBotLikeRawEvent } from 'zhin.js';
5
-
6
- import { Actions } from "./protocol.js";
7
- import type { IpcClient } from "./ipc-client.js";
8
-
9
- export type IcqqIpcRawEvent = OneBotLikeRawEvent;
10
-
11
- export function resolveIcqqEventPostType(
12
- data: Record<string, unknown>,
13
- ): string | undefined {
14
- const pt = data.post_type;
15
- if (typeof pt === "string" && pt !== "") return pt;
16
- if (data.notice_type != null) return "notice";
17
- if (data.request_type != null) return "request";
18
- if (data.meta_event_type != null) return "meta_event";
19
- return undefined;
20
- }
21
-
22
- export function isIcqqNoticePayload(data: unknown): data is IcqqIpcRawEvent {
23
- if (!data || typeof data !== "object") return false;
24
- const pt = resolveIcqqEventPostType(data as Record<string, unknown>);
25
- return pt === "notice" || (typeof pt === "string" && pt.startsWith("notice."));
26
- }
27
-
28
- export function isIcqqRequestPayload(data: unknown): data is IcqqIpcRawEvent {
29
- if (!data || typeof data !== "object") return false;
30
- const pt = resolveIcqqEventPostType(data as Record<string, unknown>);
31
- return pt === "request" || (typeof pt === "string" && pt.startsWith("request."));
32
- }
33
-
34
- export function isIcqqMetaPayload(data: unknown): data is IcqqIpcRawEvent {
35
- if (!data || typeof data !== "object") return false;
36
- const pt = resolveIcqqEventPostType(data as Record<string, unknown>);
37
- return pt === "meta_event" || (typeof pt === "string" && pt.startsWith("system."));
38
- }
39
-
40
- export function formatIcqqNotice(
41
- event: IcqqIpcRawEvent,
42
- endpointName: string,
43
- ) {
44
- const raw = event.notice_type ?? "";
45
- const isGroup = event.group_id != null;
46
- const { scene_type, sub_type } = mapNoticeParts('icqq', raw, { sub_type: event.sub_type, is_group: isGroup });
47
- const sceneId = String(
48
- event.group_id ?? event.user_id ?? event.operator_id ?? "",
49
- );
50
- const tsSec = event.time ?? Math.floor(Date.now() / 1000);
51
-
52
- return buildNotice(event, {
53
- $id: resolveSideEventDedupeKey(event, "notice"),
54
- $adapter: "icqq",
55
- $endpoint: endpointName,
56
- $type: "notice",
57
- $scene_id: sceneId,
58
- $scene_type: scene_type,
59
- $sub_type: sub_type,
60
- $actor: senderFromId(event.operator_id),
61
- $target: senderFromId(event.user_id),
62
- $timestamp: tsSec * 1000,
63
- });
64
- }
65
-
66
- export function formatIcqqRequest(
67
- event: IcqqIpcRawEvent,
68
- endpointName: string,
69
- ipc: IpcClient,
70
- ) {
71
- const { scene_type, sub_type } = mapRequestParts('icqq', event.request_type ?? '', event.sub_type);
72
- const sceneId = String(event.group_id ?? event.user_id ?? "");
73
- const tsSec = event.time ?? Math.floor(Date.now() / 1000);
74
- const flag = event.flag ?? resolveSideEventDedupeKey(event, "request");
75
-
76
- const isFriend =
77
- event.request_type === "friend" ||
78
- (typeof event.request_type === "string" &&
79
- event.request_type.startsWith("friend"));
80
-
81
- return buildRequest(event, {
82
- $id: String(flag),
83
- $adapter: "icqq",
84
- $endpoint: endpointName,
85
- $type: "request",
86
- $scene_id: sceneId,
87
- $scene_type: scene_type,
88
- $sub_type: sub_type,
89
- $actor: senderFromId(event.user_id) ?? { id: "", name: "" },
90
- $comment: typeof event.comment === "string" ? event.comment : undefined,
91
- $timestamp: tsSec * 1000,
92
- $approve: async (remark?: string) => {
93
- const action = isFriend
94
- ? Actions.HANDLE_FRIEND_REQUEST
95
- : Actions.HANDLE_GROUP_REQUEST;
96
- const params: Record<string, unknown> = {
97
- flag: event.flag ?? flag,
98
- approve: true,
99
- };
100
- if (remark) params.remark = remark;
101
- if (!isFriend && event.sub_type) params.sub_type = event.sub_type;
102
- const resp = await ipc.request(action, params);
103
- if (!resp.ok) throw new Error(resp.error ?? "同意请求失败");
104
- },
105
- $reject: async (reason?: string) => {
106
- const action = isFriend
107
- ? Actions.HANDLE_FRIEND_REQUEST
108
- : Actions.HANDLE_GROUP_REQUEST;
109
- const params: Record<string, unknown> = {
110
- flag: event.flag ?? flag,
111
- approve: false,
112
- };
113
- if (reason) params.reason = reason;
114
- if (!isFriend && event.sub_type) params.sub_type = event.sub_type;
115
- const resp = await ipc.request(action, params);
116
- if (!resp.ok) throw new Error(resp.error ?? "拒绝请求失败");
117
- },
118
- });
119
- }
120
-
121
- export function shouldRefreshListsOnMeta(event: IcqqIpcRawEvent): boolean {
122
- if (event.meta_event_type === "lifecycle") {
123
- const sub = event.sub_type;
124
- return sub === "connect" || sub === "enable";
125
- }
126
- const pt = String(event.post_type ?? "");
127
- if (pt === "system.online" || pt.endsWith(".online")) return true;
128
- return false;
129
- }
130
-
131
- export function formatIcqqMetaLog(event: IcqqIpcRawEvent): string {
132
- const meta =
133
- (typeof event.meta_event_type === "string" && event.meta_event_type) ||
134
- (typeof event.post_type === "string" && event.post_type) ||
135
- "meta";
136
- const subType = typeof event.sub_type === "string" ? event.sub_type : undefined;
137
- const time = typeof event.time === "number" ? event.time : undefined;
138
- return formatCompact({
139
- meta,
140
- sub_type: subType,
141
- time,
142
- });
143
- }
@@ -1,39 +0,0 @@
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
- }
@@ -1,52 +0,0 @@
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;
package/src/routes.ts DELETED
@@ -1,83 +0,0 @@
1
- /**
2
- * ICQQ HTTP 路由注册 — 通过 IPC 查询守护进程数据
3
- */
4
- import type { Router } from "@zhin.js/host-router";
5
- import type { Plugin } from "zhin.js";
6
- import type { IcqqAdapter } from "./adapter.js";
7
- import { Actions } from "./protocol.js";
8
-
9
- export function registerRoutes(
10
- router: Router,
11
- icqq: IcqqAdapter,
12
- _root: Plugin,
13
- ) {
14
- router.get("/api/icqq/endpoints", async (ctx) => {
15
- try {
16
- const endpoints = Array.from(icqq.endpoints.values());
17
- if (endpoints.length === 0) {
18
- ctx.body = { success: true, data: [], message: "暂无ICQQEndpoint 实例" };
19
- return;
20
- }
21
- const result = await Promise.all(
22
- endpoints.map(async (endpoint) => {
23
- try {
24
- const base: Record<string, unknown> = {
25
- name: endpoint.$config.name,
26
- connected: endpoint.$connected || false,
27
- groupCount: endpoint.groups.size,
28
- friendCount: endpoint.friends.size,
29
- status: endpoint.$connected ? "online" : "offline",
30
- lastActivity: new Date().toISOString(),
31
- };
32
-
33
- // 尝试从守护进程获取详细状态
34
- if (endpoint.$connected && endpoint.ipc && !endpoint.ipc.closed) {
35
- try {
36
- const statusResp = await endpoint.ipc.request(
37
- Actions.GET_STATUS,
38
- {},
39
- 5000,
40
- );
41
- if (statusResp.ok && statusResp.data) {
42
- const stat = statusResp.data as Record<string, unknown>;
43
- base.receiveCount = stat.recv_msg_cnt ?? 0;
44
- base.sendCount = stat.sent_msg_cnt ?? 0;
45
- }
46
- } catch {
47
- // status 查询超时,忽略
48
- }
49
- }
50
-
51
- return base;
52
- } catch {
53
- return {
54
- name: endpoint.$config.name,
55
- connected: false,
56
- groupCount: 0,
57
- friendCount: 0,
58
- status: "error",
59
- error: "数据获取失败",
60
- };
61
- }
62
- }),
63
- );
64
- ctx.body = {
65
- success: true,
66
- data: result,
67
- timestamp: new Date().toISOString(),
68
- };
69
- } catch (error) {
70
- ctx.status = 500;
71
- ctx.body = {
72
- success: false,
73
- error: "ICQQ_API_ERROR",
74
- message: "获取 Endpoint 数据失败",
75
- details:
76
- process.env.NODE_ENV === "development"
77
- ? (error as Error).message
78
- : undefined,
79
- timestamp: new Date().toISOString(),
80
- };
81
- }
82
- });
83
- }
@@ -1 +0,0 @@
1
- export { toCanonicalSegments, fromCanonicalSegments } from 'zhin.js';
@@ -1,31 +0,0 @@
1
- /**
2
- * ICQQ 场景管理工具注册
3
- *
4
- * 平台特有工具已迁移至 agent/tools/;本模块仅注册通用群管工具。
5
- */
6
- import { createSceneManagementTools, type ToolFeature } from 'zhin.js';
7
-
8
- import type { IcqqAdapter } from "../adapter.js";
9
- import { setIcqqAgentDeps } from "../icqq-agent-deps.js";
10
-
11
- export function registerTools(
12
- toolService: ToolFeature,
13
- icqq: IcqqAdapter,
14
- pluginName: string,
15
- ): () => void {
16
- const disposers: (() => void)[] = [];
17
-
18
- setIcqqAgentDeps({
19
- getEndpoint: (endpointId) => {
20
- const endpoint = icqq.endpoints.get(endpointId);
21
- if (!endpoint) throw new Error(`Endpoint ${endpointId} 不存在`);
22
- return endpoint;
23
- },
24
- getAdapter: () => icqq,
25
- });
26
-
27
- const sceneTools = createSceneManagementTools(icqq, "icqq");
28
- disposers.push(...sceneTools.map((t) => toolService.addTool(t, pluginName)));
29
-
30
- return () => disposers.forEach((d) => d());
31
- }