@zhin.js/adapter-icqq 1.1.16 → 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.
Files changed (75) hide show
  1. package/CHANGELOG.md +72 -0
  2. package/README.md +44 -3
  3. package/adapters/icqq/index.js +10 -2
  4. package/adapters/icqq/index.ts +10 -2
  5. package/agents/icqq/members.js +16 -0
  6. package/agents/icqq/members.ts +17 -0
  7. package/agents/icqq/skills/icqq-group-admin/tools/essence/index.js +1 -1
  8. package/agents/icqq/skills/icqq-group-admin/tools/essence/index.ts +1 -1
  9. package/agents/icqq/skills/icqq-group-admin/tools/group_invite/index.js +2 -2
  10. package/agents/icqq/skills/icqq-group-admin/tools/group_invite/index.ts +2 -2
  11. package/agents/icqq/skills/icqq-group-admin/tools/group_leave/index.js +1 -0
  12. package/agents/icqq/skills/icqq-group-admin/tools/group_leave/index.ts +1 -0
  13. package/agents/icqq/skills/icqq-group-admin/tools/recall_member_message/index.js +2 -1
  14. package/agents/icqq/skills/icqq-group-admin/tools/recall_member_message/index.ts +2 -1
  15. package/agents/icqq/skills/icqq-group-admin/tools/set_anonymous/index.js +2 -2
  16. package/agents/icqq/skills/icqq-group-admin/tools/set_anonymous/index.ts +2 -2
  17. package/agents/icqq/skills/icqq-group-admin/tools/set_mute/index.js +4 -4
  18. package/agents/icqq/skills/icqq-group-admin/tools/set_mute/index.ts +4 -4
  19. package/agents/icqq/skills/icqq-group-admin/tools/set_title/index.js +4 -4
  20. package/agents/icqq/skills/icqq-group-admin/tools/set_title/index.ts +4 -4
  21. package/agents/icqq/skills/icqq-group-directory/tools/group_member_info/index.js +16 -6
  22. package/agents/icqq/skills/icqq-group-directory/tools/group_member_info/index.ts +16 -5
  23. package/agents/icqq/skills/icqq-messages/tools/forward_messages/index.js +1 -1
  24. package/agents/icqq/skills/icqq-messages/tools/forward_messages/index.ts +1 -1
  25. package/agents/icqq/skills/icqq-messages/tools/quote_reply/index.js +1 -1
  26. package/agents/icqq/skills/icqq-messages/tools/quote_reply/index.ts +1 -1
  27. package/agents/icqq/skills/icqq-messages/tools/recall_own_message/index.js +1 -1
  28. package/agents/icqq/skills/icqq-messages/tools/recall_own_message/index.ts +1 -1
  29. package/agents/icqq/system.md +3 -3
  30. package/commands/icqq/login/code/index.js +28 -0
  31. package/commands/icqq/login/code/index.ts +30 -0
  32. package/commands/icqq/login/confirm/index.js +20 -0
  33. package/commands/icqq/login/confirm/index.ts +21 -0
  34. package/commands/icqq/login/definition.js +65 -0
  35. package/commands/icqq/login/definition.ts +72 -0
  36. package/commands/icqq/login/qr/index.js +53 -0
  37. package/commands/icqq/login/qr/index.ts +55 -0
  38. package/commands/icqq/login/retry/index.js +21 -0
  39. package/commands/icqq/login/retry/index.ts +23 -0
  40. package/commands/icqq/login/status/index.js +31 -0
  41. package/commands/icqq/login/status/index.ts +34 -0
  42. package/lib/console-spec.d.ts +17 -0
  43. package/lib/console-spec.js +11 -0
  44. package/lib/console.d.ts +8 -0
  45. package/lib/console.js +16 -0
  46. package/lib/endpoint.d.ts +9 -2
  47. package/lib/endpoint.js +200 -45
  48. package/lib/group-moderation.js +7 -2
  49. package/lib/group-scene.d.ts +11 -0
  50. package/lib/group-scene.js +71 -0
  51. package/lib/icqq-inbound.d.ts +2 -0
  52. package/lib/icqq-inbound.js +3 -0
  53. package/lib/icqq-inbox.d.ts +5 -0
  54. package/lib/icqq-inbox.js +14 -0
  55. package/lib/icqq-login-control.d.ts +18 -0
  56. package/lib/icqq-login-control.js +8 -0
  57. package/lib/index.d.ts +1 -1
  58. package/lib/index.js +1 -1
  59. package/lib/protocol.d.ts +12 -0
  60. package/lib/protocol.js +28 -11
  61. package/package.json +17 -9
  62. package/pages/index/index.js +15 -0
  63. package/pages/index/index.ts +16 -0
  64. package/plugin.js +6 -1
  65. package/schema.json +174 -0
  66. package/src/console-spec.ts +17 -0
  67. package/src/console.ts +21 -0
  68. package/src/endpoint.ts +199 -49
  69. package/src/group-moderation.ts +7 -2
  70. package/src/group-scene.ts +76 -0
  71. package/src/icqq-inbound.ts +5 -0
  72. package/src/icqq-inbox.ts +15 -0
  73. package/src/icqq-login-control.ts +30 -0
  74. package/src/index.ts +2 -0
  75. package/src/protocol.ts +38 -10
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
 
@@ -342,6 +348,8 @@ export function icqqInboundConversation(endpointKey: string, input: {
342
348
  readonly channelId: string;
343
349
  readonly channelParentGroupId?: string;
344
350
  readonly guildId?: string;
351
+ /** 群名(仅 group 会话使用) */
352
+ readonly name?: string;
345
353
  }): ConversationRef {
346
354
  const endpoint = { id: endpointKey, adapter: ICQQ_ADAPTER_NAME };
347
355
  if (input.channelType === 'private' && input.channelParentGroupId) {
@@ -360,7 +368,8 @@ export function icqqInboundConversation(endpointKey: string, input: {
360
368
  parent: { kind: 'channel', id: input.guildId },
361
369
  };
362
370
  }
363
- return { endpoint, kind: input.channelType, id: input.channelId };
371
+ const name = input.channelType === 'group' ? input.name?.trim() : undefined;
372
+ return { endpoint, kind: input.channelType, id: input.channelId, ...(name ? { name } : {}) };
364
373
  }
365
374
 
366
375
  /**
@@ -453,19 +462,37 @@ export function formatOutboundBody(payload: unknown): Sendable {
453
462
  * quote or whitespace are dropped: a standalone element cannot carry the quote.
454
463
  */
455
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[] {
456
475
  if (!Array.isArray(payload)) {
457
- return isWireSegment(payload) ? formatOutboundMessages([payload]) : [formatOutboundBody(payload)];
476
+ if (isWireSegment(payload)) return formatOutboundMessageParts([payload]);
477
+ const message = formatOutboundBody(payload);
478
+ return [{ message, ...(typeof payload === 'string' && message !== payload ? {} : { sourceIndices: [0] }) }];
458
479
  }
459
- const groups: (string | MessageElem)[][] = [[]];
460
- for (const element of formatOutboundElements(payload)) {
461
- if (isStandaloneElement(element)) groups.push([element], []);
462
- else groups.at(-1)!.push(element);
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
+ }
463
487
  }
464
- const messages = groups.filter(group => group.some(element => typeof element === 'string'
488
+ const messages = groups.filter(group => group.some(({ element }) => typeof element === 'string'
465
489
  ? element.trim() !== ''
466
490
  : element.type !== 'reply' && element.type !== 'quote'));
467
- if (messages.length === 0) return ['\u200b'];
468
- return messages.map(group => group.length === 1 ? group[0]! : 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
+ }));
469
496
  }
470
497
 
471
498
  function isStandaloneElement(element: string | MessageElem): element is MessageElem {
@@ -487,7 +514,8 @@ function formatOutboundElements(payload: readonly unknown[]): (string | MessageE
487
514
  if (!Number.isSafeInteger(qq) || qq <= 0) {
488
515
  throw new TypeError(`Invalid ICQQ mention target: ${String(target ?? '')}`);
489
516
  }
490
- return { type: 'at', qq };
517
+ const name = typeof item.data?.name === 'string' ? item.data.name.trim() : '';
518
+ return name ? { type: 'at', qq, text: name.startsWith('@') ? name : `@${name}` } : { type: 'at', qq };
491
519
  }
492
520
  case 'image': {
493
521
  const arg = resolveIcqqMediaFile(normalizeIcqqImageData(item.data));