@zhin.js/adapter-icqq 8.0.2 → 8.0.5
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 +87 -0
- package/README.md +9 -9
- package/adapters/icqq.js +2 -2
- package/adapters/icqq.ts +2 -2
- package/lib/endpoint.d.ts +2 -5
- package/lib/endpoint.js +61 -89
- package/lib/icqq-agent-deps.d.ts +2 -2
- package/lib/icqq-agent-deps.js +7 -7
- package/lib/icqq-endpoint-commands.js +7 -7
- package/lib/icqq-inbox.d.ts +1 -1
- package/lib/icqq-inbox.js +3 -3
- package/lib/index.d.ts +1 -1
- package/lib/index.js +1 -1
- package/lib/ipc-client.d.ts +1 -1
- package/lib/ipc-client.js +1 -1
- package/lib/protocol.d.ts +20 -9
- package/lib/protocol.js +40 -34
- package/package.json +14 -13
- package/schema.json +11 -11
- package/src/endpoint.ts +80 -94
- package/src/icqq-agent-deps.ts +8 -8
- package/src/icqq-endpoint-commands.ts +7 -7
- package/src/icqq-inbox.ts +4 -4
- package/src/index.ts +2 -2
- package/src/ipc-client.ts +1 -1
- package/src/protocol.ts +47 -38
- /package/commands/endpoint/add/{[name:string=].js → [[id]].js} +0 -0
- /package/commands/endpoint/add/{[name:string=].ts → [[id]].ts} +0 -0
- /package/commands/endpoint/remove/{[name:string].js → [id].js} +0 -0
- /package/commands/endpoint/remove/{[name:string].ts → [id].ts} +0 -0
package/lib/icqq-inbox.js
CHANGED
|
@@ -27,7 +27,7 @@ export function buildIcqqInboxRequestRow(payload, base) {
|
|
|
27
27
|
const isGroup = requestType === 'group' || groupId != null;
|
|
28
28
|
return {
|
|
29
29
|
adapter: base.adapter,
|
|
30
|
-
endpoint_id: base.
|
|
30
|
+
endpoint_id: base.endpointKey,
|
|
31
31
|
platform_request_id: platformRequestId,
|
|
32
32
|
type: isGroup ? 'group' : (requestType ?? 'friend'),
|
|
33
33
|
scene_type: isGroup ? 'group' : null,
|
|
@@ -63,7 +63,7 @@ export function buildIcqqInboxNoticeRow(payload, base) {
|
|
|
63
63
|
const targetId = userId != null && String(userId) !== String(actorId ?? '') ? userId : undefined;
|
|
64
64
|
return {
|
|
65
65
|
adapter: base.adapter,
|
|
66
|
-
endpoint_id: base.
|
|
66
|
+
endpoint_id: base.endpointKey,
|
|
67
67
|
platform_notice_id: platformNoticeId,
|
|
68
68
|
type: noticeType,
|
|
69
69
|
scene_type: groupId != null ? 'group' : null,
|
|
@@ -92,7 +92,7 @@ export function buildIcqqSystemRequestRow(message, kind, base) {
|
|
|
92
92
|
return null;
|
|
93
93
|
return {
|
|
94
94
|
adapter: base.adapter,
|
|
95
|
-
endpoint_id: base.
|
|
95
|
+
endpoint_id: base.endpointKey,
|
|
96
96
|
platform_request_id: platformRequestId,
|
|
97
97
|
type: kind,
|
|
98
98
|
scene_type: kind === 'group' ? 'group' : null,
|
package/lib/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { Actions, formatInboundContent,
|
|
1
|
+
export { Actions, formatInboundContent, formatOutboundBody, icqqInboundConversation, icqqOutboundTarget, resolveIcqqConfig, type IcqqAdapterConfig, type IcqqInboundMessage, type IcqqWireSegment, type IpcEvent, type IpcMessage, type IpcRequest, type IpcResponse, type ParsedIcqqSendTarget, type ResolvedIcqqConfig, } from './protocol.js';
|
|
2
2
|
export { IcqqIpcEndpoint, type CreateIcqqIpc, type IcqqEndpointOptions, type IcqqInboxHooks, type IcqqIpcTransport, } from './endpoint.js';
|
|
3
3
|
export * from './types.js';
|
|
4
4
|
export { getIcqqAgentDeps, registerIcqqAgentEndpoint, setIcqqAgentDeps, type IcqqAgentDeps, type IcqqAgentEndpoint, } from './icqq-agent-deps.js';
|
package/lib/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { Actions, formatInboundContent,
|
|
1
|
+
export { Actions, formatInboundContent, formatOutboundBody, icqqInboundConversation, icqqOutboundTarget, resolveIcqqConfig, } from './protocol.js';
|
|
2
2
|
export { IcqqIpcEndpoint, } from './endpoint.js';
|
|
3
3
|
export * from './types.js';
|
|
4
4
|
export { getIcqqAgentDeps, registerIcqqAgentEndpoint, setIcqqAgentDeps, } from './icqq-agent-deps.js';
|
package/lib/ipc-client.d.ts
CHANGED
|
@@ -61,7 +61,7 @@ export declare class IpcClient {
|
|
|
61
61
|
*/
|
|
62
62
|
request(action: string, params?: Record<string, unknown>, timeoutMs?: number): Promise<IpcResponse>;
|
|
63
63
|
/**
|
|
64
|
-
*
|
|
64
|
+
* 订阅 daemon 推送事件:服务端自动推送全部事件,type/id 过滤在客户端完成。
|
|
65
65
|
* @returns 订阅句柄,包含 unsubscribe() 方法
|
|
66
66
|
*/
|
|
67
67
|
subscribe(_action: string, params: Record<string, unknown>, onEvent: (event: IpcEvent) => void): {
|
package/lib/ipc-client.js
CHANGED
package/lib/protocol.d.ts
CHANGED
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
*
|
|
12
12
|
* 登录相关:**推送**走 IpcEvent(`system.login.*`)。
|
|
13
13
|
*/
|
|
14
|
+
import type { ConversationRef } from '@zhin.js/im-contract';
|
|
14
15
|
import type { MessageSegment } from "zhin.js";
|
|
15
16
|
/** CLI → Daemon 请求 */
|
|
16
17
|
export type IpcRequest = {
|
|
@@ -198,7 +199,7 @@ export declare const Actions: {
|
|
|
198
199
|
};
|
|
199
200
|
/** Plugin Runtime owner config (`plugins.<instanceKey>` / schema.json). */
|
|
200
201
|
export interface IcqqAdapterConfig {
|
|
201
|
-
readonly
|
|
202
|
+
readonly id?: string;
|
|
202
203
|
readonly autoReconnect?: boolean;
|
|
203
204
|
readonly outboundMedia?: 'file' | 'base64';
|
|
204
205
|
readonly rpc?: {
|
|
@@ -209,7 +210,7 @@ export interface IcqqAdapterConfig {
|
|
|
209
210
|
/** Transitional: legacy root `endpoints[]` with `context: icqq`. */
|
|
210
211
|
readonly endpoints?: ReadonlyArray<{
|
|
211
212
|
readonly context?: string;
|
|
212
|
-
readonly
|
|
213
|
+
readonly id?: string;
|
|
213
214
|
readonly autoReconnect?: boolean;
|
|
214
215
|
readonly outboundMedia?: 'file' | 'base64';
|
|
215
216
|
readonly rpc?: {
|
|
@@ -221,7 +222,7 @@ export interface IcqqAdapterConfig {
|
|
|
221
222
|
}
|
|
222
223
|
export interface ResolvedIcqqConfig {
|
|
223
224
|
readonly context: 'icqq';
|
|
224
|
-
readonly
|
|
225
|
+
readonly id: string;
|
|
225
226
|
readonly autoReconnect: boolean;
|
|
226
227
|
readonly outboundMedia?: 'file' | 'base64';
|
|
227
228
|
readonly rpc?: {
|
|
@@ -236,14 +237,17 @@ export interface IcqqWireSegment {
|
|
|
236
237
|
}
|
|
237
238
|
export interface IcqqInboundMessage {
|
|
238
239
|
readonly id: string;
|
|
239
|
-
readonly
|
|
240
|
+
readonly conversation: ConversationRef;
|
|
240
241
|
readonly content: string;
|
|
241
242
|
/**
|
|
242
243
|
* 结构化段视图(canonical Segment,经 toCanonicalSegments 归一)。
|
|
243
244
|
* 与 content(CQ 原文纯文本视图)同源,随 gateway.receive 上送。
|
|
244
245
|
*/
|
|
245
246
|
readonly segments?: readonly MessageSegment[];
|
|
246
|
-
readonly sender:
|
|
247
|
+
readonly sender: {
|
|
248
|
+
readonly id: string;
|
|
249
|
+
readonly name?: string;
|
|
250
|
+
};
|
|
247
251
|
readonly channelType: 'private' | 'group' | 'channel';
|
|
248
252
|
readonly metadata?: Record<string, unknown>;
|
|
249
253
|
}
|
|
@@ -263,13 +267,20 @@ export type ParsedIcqqSendTarget = {
|
|
|
263
267
|
readonly channelId: string;
|
|
264
268
|
};
|
|
265
269
|
export declare function resolveIcqqConfig(config?: IcqqAdapterConfig): ResolvedIcqqConfig;
|
|
266
|
-
/**
|
|
267
|
-
|
|
270
|
+
/**
|
|
271
|
+
* 入站归一化 → ConversationRef:群临时会话(temp)映射为群容器内的 private
|
|
272
|
+
* 会话(parent kind 'group');频道消息的所属 guild 进 `parent`(kind 'channel')。
|
|
273
|
+
*/
|
|
274
|
+
export declare function icqqInboundConversation(endpointKey: string, input: {
|
|
268
275
|
readonly channelType: 'private' | 'group' | 'channel';
|
|
269
276
|
readonly channelId: string;
|
|
270
277
|
readonly channelParentGroupId?: string;
|
|
271
278
|
readonly guildId?: string;
|
|
272
|
-
}):
|
|
273
|
-
|
|
279
|
+
}): ConversationRef;
|
|
280
|
+
/**
|
|
281
|
+
* 出站:从 ConversationRef 派生 IPC action 路由。
|
|
282
|
+
* 群容器(parent kind 'group')内的 private 会话即 ICQQ 群临时会话(temp)。
|
|
283
|
+
*/
|
|
284
|
+
export declare function icqqOutboundTarget(conversation: ConversationRef): ParsedIcqqSendTarget;
|
|
274
285
|
export declare function formatOutboundBody(payload: unknown): string;
|
|
275
286
|
export declare function formatInboundContent(rawMessage: string): string;
|
package/lib/protocol.js
CHANGED
|
@@ -188,9 +188,9 @@ export const Actions = {
|
|
|
188
188
|
};
|
|
189
189
|
export function resolveIcqqConfig(config = {}) {
|
|
190
190
|
const entry = config.endpoints?.find((item) => item.context === 'icqq');
|
|
191
|
-
const
|
|
192
|
-
if (!/^\d+$/.test(
|
|
193
|
-
throw new TypeError('ICQQ adapter requires numeric
|
|
191
|
+
const id = pickCredential(config.id, entry?.id, process.env.ICQQ_ACCOUNT);
|
|
192
|
+
if (!/^\d+$/.test(id)) {
|
|
193
|
+
throw new TypeError('ICQQ adapter requires numeric id (QQ uin) via plugins.<key>.id or ICQQ_ACCOUNT');
|
|
194
194
|
}
|
|
195
195
|
const autoReconnect = config.autoReconnect ?? entry?.autoReconnect ?? true;
|
|
196
196
|
const outboundMedia = config.outboundMedia ?? entry?.outboundMedia;
|
|
@@ -200,53 +200,59 @@ export function resolveIcqqConfig(config = {}) {
|
|
|
200
200
|
: undefined;
|
|
201
201
|
return {
|
|
202
202
|
context: 'icqq',
|
|
203
|
-
|
|
203
|
+
id,
|
|
204
204
|
autoReconnect,
|
|
205
205
|
...(outboundMedia ? { outboundMedia } : {}),
|
|
206
206
|
...(rpc ? { rpc } : {}),
|
|
207
207
|
};
|
|
208
208
|
}
|
|
209
|
-
/**
|
|
210
|
-
|
|
209
|
+
/**
|
|
210
|
+
* 入站归一化 → ConversationRef:群临时会话(temp)映射为群容器内的 private
|
|
211
|
+
* 会话(parent kind 'group');频道消息的所属 guild 进 `parent`(kind 'channel')。
|
|
212
|
+
*/
|
|
213
|
+
export function icqqInboundConversation(endpointKey, input) {
|
|
214
|
+
const endpoint = { id: endpointKey, adapter: endpointKey.split('\0')[0] ?? endpointKey };
|
|
211
215
|
if (input.channelType === 'private' && input.channelParentGroupId) {
|
|
212
|
-
return
|
|
216
|
+
return {
|
|
217
|
+
endpoint,
|
|
218
|
+
kind: 'private',
|
|
219
|
+
id: input.channelId,
|
|
220
|
+
parent: { kind: 'group', id: input.channelParentGroupId },
|
|
221
|
+
};
|
|
213
222
|
}
|
|
214
223
|
if (input.channelType === 'channel' && input.guildId) {
|
|
215
|
-
return
|
|
224
|
+
return {
|
|
225
|
+
endpoint,
|
|
226
|
+
kind: 'channel',
|
|
227
|
+
id: input.channelId,
|
|
228
|
+
parent: { kind: 'channel', id: input.guildId },
|
|
229
|
+
};
|
|
216
230
|
}
|
|
217
|
-
return
|
|
231
|
+
return { endpoint, kind: input.channelType, id: input.channelId };
|
|
218
232
|
}
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
throw new TypeError(`Invalid icqq temp target: ${target}`);
|
|
226
|
-
return { kind: 'temp', groupId: Number(groupId), userId: Number(userId) };
|
|
227
|
-
}
|
|
228
|
-
if (trimmed.startsWith('channel:')) {
|
|
229
|
-
const rest = trimmed.slice(8);
|
|
230
|
-
const idx = rest.indexOf(':');
|
|
231
|
-
if (idx <= 0)
|
|
232
|
-
throw new TypeError(`Invalid icqq channel target: ${target}`);
|
|
233
|
+
/**
|
|
234
|
+
* 出站:从 ConversationRef 派生 IPC action 路由。
|
|
235
|
+
* 群容器(parent kind 'group')内的 private 会话即 ICQQ 群临时会话(temp)。
|
|
236
|
+
*/
|
|
237
|
+
export function icqqOutboundTarget(conversation) {
|
|
238
|
+
if (conversation.kind === 'private' && conversation.parent?.kind === 'group') {
|
|
233
239
|
return {
|
|
234
|
-
kind: '
|
|
235
|
-
|
|
236
|
-
|
|
240
|
+
kind: 'temp',
|
|
241
|
+
groupId: Number(conversation.parent.id),
|
|
242
|
+
userId: Number(conversation.id),
|
|
237
243
|
};
|
|
238
244
|
}
|
|
239
|
-
if (
|
|
240
|
-
return { kind: 'private', userId: Number(
|
|
245
|
+
if (conversation.kind === 'private') {
|
|
246
|
+
return { kind: 'private', userId: Number(conversation.id) };
|
|
241
247
|
}
|
|
242
|
-
if (
|
|
243
|
-
return { kind: 'group', groupId: Number(
|
|
248
|
+
if (conversation.kind === 'group') {
|
|
249
|
+
return { kind: 'group', groupId: Number(conversation.id) };
|
|
244
250
|
}
|
|
245
|
-
|
|
246
|
-
if (
|
|
247
|
-
|
|
251
|
+
const guildId = conversation.parent?.kind === 'channel' ? conversation.parent.id : undefined;
|
|
252
|
+
if (!guildId) {
|
|
253
|
+
throw new TypeError(`Invalid icqq channel conversation (missing guild parent): ${conversation.id}`);
|
|
248
254
|
}
|
|
249
|
-
|
|
255
|
+
return { kind: 'channel', guildId, channelId: conversation.id };
|
|
250
256
|
}
|
|
251
257
|
export function formatOutboundBody(payload) {
|
|
252
258
|
if (typeof payload === 'string') {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zhin.js/adapter-icqq",
|
|
3
|
-
"version": "8.0.
|
|
3
|
+
"version": "8.0.5",
|
|
4
4
|
"description": "Zhin.js ICQQ adapter for Plugin Runtime (IPC daemon client)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/index.js",
|
|
@@ -34,19 +34,20 @@
|
|
|
34
34
|
"directory": "plugins/adapters/icqq"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@zhin.js/adapter": "1.1.
|
|
38
|
-
"@zhin.js/command": "1.0.
|
|
39
|
-
"@zhin.js/core": "1.5.
|
|
40
|
-
"@zhin.js/
|
|
41
|
-
"@zhin.js/
|
|
37
|
+
"@zhin.js/adapter": "1.1.7",
|
|
38
|
+
"@zhin.js/command": "1.0.9",
|
|
39
|
+
"@zhin.js/core": "1.5.4",
|
|
40
|
+
"@zhin.js/im-contract": "1.0.3",
|
|
41
|
+
"@zhin.js/logger": "1.0.76",
|
|
42
|
+
"@zhin.js/plugin-runtime": "1.1.5"
|
|
42
43
|
},
|
|
43
44
|
"peerDependencies": {
|
|
44
45
|
"zod": "^4.0.0",
|
|
45
|
-
"@zhin.js/adapter": "1.1.
|
|
46
|
-
"@zhin.js/agent": "1.1.
|
|
47
|
-
"@zhin.js/core": "1.5.
|
|
48
|
-
"@zhin.js/plugin-runtime": "1.1.
|
|
49
|
-
"zhin.js": "6.0.
|
|
46
|
+
"@zhin.js/adapter": "1.1.7",
|
|
47
|
+
"@zhin.js/agent": "1.1.5",
|
|
48
|
+
"@zhin.js/core": "1.5.4",
|
|
49
|
+
"@zhin.js/plugin-runtime": "1.1.5",
|
|
50
|
+
"zhin.js": "6.0.4"
|
|
50
51
|
},
|
|
51
52
|
"peerDependenciesMeta": {
|
|
52
53
|
"zhin.js": {
|
|
@@ -64,8 +65,8 @@
|
|
|
64
65
|
"typescript": "^6.0.3",
|
|
65
66
|
"vitest": "^4.1.10",
|
|
66
67
|
"zod": "^4.4.3",
|
|
67
|
-
"@zhin.js/agent": "1.1.
|
|
68
|
-
"zhin.js": "6.0.
|
|
68
|
+
"@zhin.js/agent": "1.1.5",
|
|
69
|
+
"zhin.js": "6.0.4"
|
|
69
70
|
},
|
|
70
71
|
"files": [
|
|
71
72
|
"adapters",
|
package/schema.json
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"string",
|
|
9
9
|
"number"
|
|
10
10
|
],
|
|
11
|
-
"description": "
|
|
11
|
+
"description": "框架 master QQ uin(/approve、AI/工具权限);endpoints[i].master 可逐项覆盖"
|
|
12
12
|
},
|
|
13
13
|
"trusted": {
|
|
14
14
|
"type": "array",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
],
|
|
20
20
|
"description": "Trusted QQ uin"
|
|
21
21
|
},
|
|
22
|
-
"description": "
|
|
22
|
+
"description": "框架 trusted QQ uin 列表(弱于 master)"
|
|
23
23
|
},
|
|
24
24
|
"autoReconnect": {
|
|
25
25
|
"type": "boolean",
|
|
@@ -35,21 +35,17 @@
|
|
|
35
35
|
},
|
|
36
36
|
"endpoints": {
|
|
37
37
|
"type": "array",
|
|
38
|
-
"description": "多账号:一个插件实例挂多个 endpoint。每项与顶层字段同构(
|
|
38
|
+
"description": "多账号:一个插件实例挂多个 endpoint。每项与顶层字段同构(id 必填,其余覆盖顶层)",
|
|
39
39
|
"items": {
|
|
40
40
|
"type": "object",
|
|
41
41
|
"additionalProperties": true,
|
|
42
42
|
"properties": {
|
|
43
|
-
"name": {
|
|
44
|
-
"type": "string",
|
|
45
|
-
"description": "QQ uin (must match icqq login account)"
|
|
46
|
-
},
|
|
47
43
|
"master": {
|
|
48
44
|
"type": [
|
|
49
45
|
"string",
|
|
50
46
|
"number"
|
|
51
47
|
],
|
|
52
|
-
"description": "
|
|
48
|
+
"description": "本 endpoint 的框架 master QQ uin;覆盖顶层 master"
|
|
53
49
|
},
|
|
54
50
|
"trusted": {
|
|
55
51
|
"type": "array",
|
|
@@ -60,7 +56,7 @@
|
|
|
60
56
|
],
|
|
61
57
|
"description": "Trusted QQ uin"
|
|
62
58
|
},
|
|
63
|
-
"description": "
|
|
59
|
+
"description": "本 endpoint 的 trusted 列表"
|
|
64
60
|
},
|
|
65
61
|
"rpc": {
|
|
66
62
|
"type": "object",
|
|
@@ -84,10 +80,14 @@
|
|
|
84
80
|
"port",
|
|
85
81
|
"token"
|
|
86
82
|
]
|
|
83
|
+
},
|
|
84
|
+
"id": {
|
|
85
|
+
"type": "string",
|
|
86
|
+
"description": "QQ uin (must match icqq login account)"
|
|
87
87
|
}
|
|
88
88
|
},
|
|
89
89
|
"required": [
|
|
90
|
-
"
|
|
90
|
+
"id"
|
|
91
91
|
]
|
|
92
92
|
}
|
|
93
93
|
},
|
|
@@ -101,4 +101,4 @@
|
|
|
101
101
|
"master",
|
|
102
102
|
"endpoints"
|
|
103
103
|
]
|
|
104
|
-
}
|
|
104
|
+
}
|