@zhin.js/adapter-icqq 1.1.13 → 1.1.14
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 +9 -0
- package/README.md +1 -1
- package/lib/endpoint.js +33 -6
- package/package.json +5 -5
- package/src/endpoint.ts +35 -6
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# @zhin.js/adapter-icqq
|
|
2
2
|
|
|
3
|
+
## 1.1.14
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 860faa0: Group and private share cards are now confirmed with a real message id: ICQQ's share API returns none, so after an accepted share the adapter reads the conversation history for the bot's own newest card (once more after a short wait). When it cannot be found the delivery stays unconfirmed as before; no id is invented.
|
|
8
|
+
- Updated dependencies [974fa85]
|
|
9
|
+
- Updated dependencies [1e9b3d6]
|
|
10
|
+
- @zhin.js/core@1.1.49
|
|
11
|
+
|
|
3
12
|
## 1.1.13
|
|
4
13
|
|
|
5
14
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -184,7 +184,7 @@ MIT
|
|
|
184
184
|
|
|
185
185
|
发送成功回执只接受平台真实消息 ID。网络超时、断线、缺少消息 ID 的响应会报告 `deliveryUnknown`,框架不会自动重发;手动重发可能重复发送。
|
|
186
186
|
|
|
187
|
-
ICQQ 原生分享和文件 API 可能已经成功,但只返回空值或文件 ID;这类结果不能当作可引用、可撤回的消息 ID
|
|
187
|
+
ICQQ 原生分享和文件 API 可能已经成功,但只返回空值或文件 ID;这类结果不能当作可引用、可撤回的消息 ID。群聊和私聊的分享卡片发出后,适配器会读一次会话记录,找到机器人自己刚发出的卡片消息,用它的真实消息 ID 作为回执(记录有延迟时半秒后再读一次)。找不到时(以及临时会话、频道和文件)仍报告投递结果未知,不编造 ID。平台操作仍只执行一次。文件撤回应使用平台专用文件 API。
|
|
188
188
|
|
|
189
189
|
### 独立元素按顺序拆分发送
|
|
190
190
|
|
package/lib/endpoint.js
CHANGED
|
@@ -331,15 +331,42 @@ export class IcqqEndpoint extends Endpoint {
|
|
|
331
331
|
prepared.dispose();
|
|
332
332
|
}
|
|
333
333
|
}
|
|
334
|
+
/**
|
|
335
|
+
* ICQQ's share API returns no message id; a resolved call only means the server accepted it.
|
|
336
|
+
* The card is the bot's own newest card message in the conversation history, so read the id
|
|
337
|
+
* from there (once more after a short wait, history can lag). Undefined keeps the delivery
|
|
338
|
+
* unconfirmed rather than inventing an id.
|
|
339
|
+
*/
|
|
340
|
+
async #findOwnCard(history, sentAt) {
|
|
341
|
+
const self = Number(this.client.uin);
|
|
342
|
+
for (const wait of [0, 500]) {
|
|
343
|
+
if (wait)
|
|
344
|
+
await new Promise(resolve => setTimeout(resolve, wait));
|
|
345
|
+
// A missing or throwing history API must not turn an accepted share into a send failure.
|
|
346
|
+
const messages = await Promise.resolve().then(history).catch(() => []);
|
|
347
|
+
const card = [...messages].reverse().find(item => Number(item.sender?.user_id ?? item.user_id) === self
|
|
348
|
+
&& (item.time ?? 0) >= sentAt - 2
|
|
349
|
+
&& (item.message ?? []).some(element => element.type === 'json' || element.type === 'xml' || element.type === 'share'));
|
|
350
|
+
if (card && card.message_id != null && String(card.message_id).trim())
|
|
351
|
+
return String(card.message_id);
|
|
352
|
+
}
|
|
353
|
+
return undefined;
|
|
354
|
+
}
|
|
334
355
|
async #sendNative(target, message) {
|
|
335
356
|
if (isIcqqShareElement(message)) {
|
|
336
357
|
switch (target.kind) {
|
|
337
|
-
case 'private':
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
await this
|
|
342
|
-
|
|
358
|
+
case 'private': {
|
|
359
|
+
const sentAt = Math.floor(Date.now() / 1000);
|
|
360
|
+
const friend = this.client.pickFriend(target.userId);
|
|
361
|
+
await friend.share(message);
|
|
362
|
+
return { message_id: await this.#findOwnCard(() => friend.getChatHistory(), sentAt) };
|
|
363
|
+
}
|
|
364
|
+
case 'group': {
|
|
365
|
+
const sentAt = Math.floor(Date.now() / 1000);
|
|
366
|
+
const group = this.client.pickGroup(target.groupId);
|
|
367
|
+
await group.share(message);
|
|
368
|
+
return { message_id: await this.#findOwnCard(() => group.getChatHistory(), sentAt) };
|
|
369
|
+
}
|
|
343
370
|
case 'temp':
|
|
344
371
|
await this.client.pickMember(target.groupId, target.userId).share(message);
|
|
345
372
|
return {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zhin.js/adapter-icqq",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.14",
|
|
4
4
|
"description": "Zhin.js ICQQ adapter — direct connection to @icqqjs/icqq",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/index.js",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"@zhin.js/adapter": "1.1.21",
|
|
37
37
|
"@zhin.js/agent-feature": "1.1.8",
|
|
38
|
-
"@zhin.js/core": "1.1.
|
|
38
|
+
"@zhin.js/core": "1.1.49",
|
|
39
39
|
"@zhin.js/feature-kit": "1.1.7",
|
|
40
40
|
"@zhin.js/im-contract": "1.1.5",
|
|
41
41
|
"@zhin.js/logger": "1.1.2",
|
|
@@ -48,9 +48,9 @@
|
|
|
48
48
|
"zod": "^4.0.0",
|
|
49
49
|
"@zhin.js/adapter": "^1.1.21",
|
|
50
50
|
"@zhin.js/command": "^1.1.9",
|
|
51
|
-
"@zhin.js/core": "^1.1.
|
|
51
|
+
"@zhin.js/core": "^1.1.49",
|
|
52
52
|
"@zhin.js/prompt-section": "^1.1.7",
|
|
53
|
-
"zhin.js": "^1.1.
|
|
53
|
+
"zhin.js": "^1.1.14"
|
|
54
54
|
},
|
|
55
55
|
"peerDependenciesMeta": {
|
|
56
56
|
"@icqqjs/icqq": {
|
|
@@ -76,7 +76,7 @@
|
|
|
76
76
|
"vitest": "^4.1.10",
|
|
77
77
|
"zod": "^4.4.3",
|
|
78
78
|
"@zhin.js/prompt-section": "1.1.7",
|
|
79
|
-
"zhin.js": "1.1.
|
|
79
|
+
"zhin.js": "1.1.14"
|
|
80
80
|
},
|
|
81
81
|
"files": [
|
|
82
82
|
"adapters",
|
package/src/endpoint.ts
CHANGED
|
@@ -389,18 +389,47 @@ export class IcqqEndpoint extends Endpoint<Client> {
|
|
|
389
389
|
}
|
|
390
390
|
}
|
|
391
391
|
|
|
392
|
+
/**
|
|
393
|
+
* ICQQ's share API returns no message id; a resolved call only means the server accepted it.
|
|
394
|
+
* The card is the bot's own newest card message in the conversation history, so read the id
|
|
395
|
+
* from there (once more after a short wait, history can lag). Undefined keeps the delivery
|
|
396
|
+
* unconfirmed rather than inventing an id.
|
|
397
|
+
*/
|
|
398
|
+
async #findOwnCard(
|
|
399
|
+
history: () => Promise<readonly { message_id?: unknown; time?: number; message?: readonly { type?: string }[]; sender?: { user_id?: number }; user_id?: number }[]>,
|
|
400
|
+
sentAt: number,
|
|
401
|
+
): Promise<string | undefined> {
|
|
402
|
+
const self = Number(this.client.uin);
|
|
403
|
+
for (const wait of [0, 500]) {
|
|
404
|
+
if (wait) await new Promise(resolve => setTimeout(resolve, wait));
|
|
405
|
+
// A missing or throwing history API must not turn an accepted share into a send failure.
|
|
406
|
+
const messages = await Promise.resolve().then(history).catch(() => []);
|
|
407
|
+
const card = [...messages].reverse().find(item => Number(item.sender?.user_id ?? item.user_id) === self
|
|
408
|
+
&& (item.time ?? 0) >= sentAt - 2
|
|
409
|
+
&& (item.message ?? []).some(element => element.type === 'json' || element.type === 'xml' || element.type === 'share'));
|
|
410
|
+
if (card && card.message_id != null && String(card.message_id).trim()) return String(card.message_id);
|
|
411
|
+
}
|
|
412
|
+
return undefined;
|
|
413
|
+
}
|
|
414
|
+
|
|
392
415
|
async #sendNative(
|
|
393
416
|
target: ReturnType<typeof icqqOutboundTarget>,
|
|
394
417
|
message: Sendable,
|
|
395
418
|
): Promise<{ message_id?: unknown }> {
|
|
396
419
|
if (isIcqqShareElement(message)) {
|
|
397
420
|
switch (target.kind) {
|
|
398
|
-
case 'private':
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
await this
|
|
403
|
-
|
|
421
|
+
case 'private': {
|
|
422
|
+
const sentAt = Math.floor(Date.now() / 1000);
|
|
423
|
+
const friend = this.client.pickFriend(target.userId);
|
|
424
|
+
await friend.share(message);
|
|
425
|
+
return { message_id: await this.#findOwnCard(() => friend.getChatHistory(), sentAt) };
|
|
426
|
+
}
|
|
427
|
+
case 'group': {
|
|
428
|
+
const sentAt = Math.floor(Date.now() / 1000);
|
|
429
|
+
const group = this.client.pickGroup(target.groupId);
|
|
430
|
+
await group.share(message);
|
|
431
|
+
return { message_id: await this.#findOwnCard(() => group.getChatHistory(), sentAt) };
|
|
432
|
+
}
|
|
404
433
|
case 'temp':
|
|
405
434
|
await this.client.pickMember(target.groupId, target.userId).share(message);
|
|
406
435
|
return {};
|