@zhin.js/adapter-icqq 1.1.15 → 1.1.17

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 (80) hide show
  1. package/CHANGELOG.md +62 -0
  2. package/PERMITS.md +14 -18
  3. package/README.md +12 -0
  4. package/adapters/icqq/index.js +2 -0
  5. package/adapters/icqq/index.ts +2 -0
  6. package/agents/icqq/conversation.js +72 -0
  7. package/agents/icqq/conversation.ts +67 -0
  8. package/agents/icqq/members.js +16 -0
  9. package/agents/icqq/members.ts +17 -0
  10. package/agents/icqq/messages.js +144 -0
  11. package/agents/icqq/messages.ts +144 -0
  12. package/agents/icqq/skills/icqq-conversation/SKILL.md +24 -0
  13. package/agents/icqq/skills/icqq-conversation/tools/conversation_info/index.js +61 -0
  14. package/agents/icqq/skills/icqq-conversation/tools/conversation_info/index.ts +61 -0
  15. package/agents/icqq/skills/icqq-directory/tools/user_info/index.js +2 -1
  16. package/agents/icqq/skills/icqq-directory/tools/user_info/index.ts +2 -1
  17. package/agents/icqq/skills/icqq-group-admin/SKILL.md +11 -1
  18. package/agents/icqq/skills/icqq-group-admin/tools/announce/index.js +2 -1
  19. package/agents/icqq/skills/icqq-group-admin/tools/announce/index.ts +2 -1
  20. package/agents/icqq/skills/icqq-group-admin/tools/essence/index.js +3 -2
  21. package/agents/icqq/skills/icqq-group-admin/tools/essence/index.ts +3 -2
  22. package/agents/icqq/skills/icqq-group-admin/tools/group_invite/index.js +6 -5
  23. package/agents/icqq/skills/icqq-group-admin/tools/group_invite/index.ts +5 -4
  24. package/agents/icqq/skills/icqq-group-admin/tools/group_kick/index.js +4 -3
  25. package/agents/icqq/skills/icqq-group-admin/tools/group_kick/index.ts +4 -3
  26. package/agents/icqq/skills/icqq-group-admin/tools/group_leave/index.js +34 -0
  27. package/agents/icqq/skills/icqq-group-admin/tools/group_leave/index.ts +33 -0
  28. package/agents/icqq/skills/icqq-group-admin/tools/recall_member_message/index.js +34 -0
  29. package/agents/icqq/skills/icqq-group-admin/tools/recall_member_message/index.ts +33 -0
  30. package/agents/icqq/skills/icqq-group-admin/tools/set_anonymous/index.js +5 -4
  31. package/agents/icqq/skills/icqq-group-admin/tools/set_anonymous/index.ts +4 -3
  32. package/agents/icqq/skills/icqq-group-admin/tools/set_mute/index.js +8 -7
  33. package/agents/icqq/skills/icqq-group-admin/tools/set_mute/index.ts +6 -5
  34. package/agents/icqq/skills/icqq-group-admin/tools/set_title/index.js +8 -7
  35. package/agents/icqq/skills/icqq-group-admin/tools/set_title/index.ts +6 -5
  36. package/agents/icqq/skills/icqq-group-directory/tools/group_member_info/index.js +18 -7
  37. package/agents/icqq/skills/icqq-group-directory/tools/group_member_info/index.ts +17 -5
  38. package/agents/icqq/skills/icqq-group-interaction/tools/group_sign/index.js +3 -2
  39. package/agents/icqq/skills/icqq-group-interaction/tools/group_sign/index.ts +3 -2
  40. package/agents/icqq/skills/icqq-group-interaction/tools/poke/index.js +2 -1
  41. package/agents/icqq/skills/icqq-group-interaction/tools/poke/index.ts +2 -1
  42. package/agents/icqq/skills/icqq-group-state/tools/group_files/index.js +2 -1
  43. package/agents/icqq/skills/icqq-group-state/tools/group_files/index.ts +2 -1
  44. package/agents/icqq/skills/icqq-interaction/tools/send_user_like/index.js +3 -2
  45. package/agents/icqq/skills/icqq-interaction/tools/send_user_like/index.ts +3 -2
  46. package/agents/icqq/skills/icqq-messages/SKILL.md +28 -0
  47. package/agents/icqq/skills/icqq-messages/tools/forward_messages/index.js +42 -0
  48. package/agents/icqq/skills/icqq-messages/tools/forward_messages/index.ts +40 -0
  49. package/agents/icqq/skills/icqq-messages/tools/quote_reply/index.js +24 -0
  50. package/agents/icqq/skills/icqq-messages/tools/quote_reply/index.ts +24 -0
  51. package/agents/icqq/skills/icqq-messages/tools/recall_own_message/index.js +18 -0
  52. package/agents/icqq/skills/icqq-messages/tools/recall_own_message/index.ts +17 -0
  53. package/agents/icqq/system.md +5 -1
  54. package/commands/icqq/endpoint/definition.js +9 -7
  55. package/commands/icqq/endpoint/definition.ts +9 -9
  56. package/lib/endpoint.d.ts +1 -0
  57. package/lib/endpoint.js +12 -8
  58. package/lib/group-moderation.js +7 -2
  59. package/lib/group-scene.d.ts +11 -0
  60. package/lib/group-scene.js +71 -0
  61. package/lib/i18n.d.ts +1 -0
  62. package/lib/i18n.js +47 -0
  63. package/lib/icqq-inbound.d.ts +2 -0
  64. package/lib/icqq-inbound.js +3 -0
  65. package/lib/icqq-inbox.d.ts +5 -0
  66. package/lib/icqq-inbox.js +14 -0
  67. package/lib/icqq-login-assist.d.ts +2 -0
  68. package/lib/icqq-login-assist.js +8 -7
  69. package/lib/protocol.d.ts +3 -0
  70. package/lib/protocol.js +18 -3
  71. package/package.json +16 -16
  72. package/schema.json +250 -42
  73. package/src/endpoint.ts +13 -7
  74. package/src/group-moderation.ts +7 -2
  75. package/src/group-scene.ts +76 -0
  76. package/src/i18n.ts +48 -0
  77. package/src/icqq-inbound.ts +5 -0
  78. package/src/icqq-inbox.ts +15 -0
  79. package/src/icqq-login-assist.ts +10 -7
  80. package/src/protocol.ts +19 -3
@@ -1,3 +1,5 @@
1
+ import type { Locale } from 'zhin.js/i18n';
2
+ import { messages as t } from './i18n.js';
1
3
  import type { LoginAssist, LoginAssistType, PendingLoginTaskPayload } from '@zhin.js/core';
2
4
  import { formatCompact } from '@zhin.js/logger';
3
5
 
@@ -27,11 +29,12 @@ export async function runIcqqLoginAssistStep(input: {
27
29
  logger: Logger;
28
30
  step: LoginAssistType;
29
31
  event: unknown;
32
+ locale?: Locale;
30
33
  }): Promise<void> {
31
34
  const { assist, client, adapter, endpointKey, owner, logger, step, event } = input;
32
35
  assist.cancelOwned(owner, `replaced_by_${step}`);
33
36
 
34
- const payload = buildPayload(step, event);
37
+ const payload = buildPayload(step, event, input.locale);
35
38
  logger.info(formatCompact({
36
39
  op: 'login_assist_pending',
37
40
  endpoint: endpointKey,
@@ -82,33 +85,33 @@ export async function runIcqqLoginAssistStep(input: {
82
85
  }
83
86
  }
84
87
 
85
- function buildPayload(step: LoginAssistType, event: unknown): PendingLoginTaskPayload {
88
+ function buildPayload(step: LoginAssistType, event: unknown, locale?: Locale): PendingLoginTaskPayload {
86
89
  const raw = event && typeof event === 'object' ? event as Record<string, unknown> : {};
87
90
  switch (step) {
88
91
  case 'qrcode':
89
92
  return {
90
- message: '扫码登录:请在手机 QQ 扫描二维码,完成后在 Console / 终端确认继续',
93
+ message: t(locale, 'loginQr'),
91
94
  image: bufferToDataUrl(raw.image),
92
95
  };
93
96
  case 'slider':
94
97
  return {
95
- message: '滑动验证:打开链接完成滑块,将返回的 ticket(可含 randstr)提交继续',
98
+ message: t(locale, 'loginSlider'),
96
99
  url: typeof raw.url === 'string' ? raw.url : undefined,
97
100
  };
98
101
  case 'device':
99
102
  return {
100
- message: '设备锁:已请求短信验证码,请提交短信验证码继续',
103
+ message: t(locale, 'loginSms'),
101
104
  url: typeof raw.url === 'string' ? raw.url : undefined,
102
105
  phone: raw.phone,
103
106
  };
104
107
  case 'auth':
105
108
  return {
106
- message: '身份验证:完成后在 Console / 终端确认继续',
109
+ message: t(locale, 'loginAuth'),
107
110
  url: typeof raw.url === 'string' ? raw.url : undefined,
108
111
  device: raw.device,
109
112
  };
110
113
  default:
111
- return { message: `登录辅助(${step})` };
114
+ return { message: t(locale, 'loginOther', { step }) };
112
115
  }
113
116
  }
114
117
 
package/src/protocol.ts CHANGED
@@ -269,6 +269,7 @@ export interface ResolvedIcqqConfig {
269
269
  export interface IcqqWireSegment {
270
270
  readonly type: string;
271
271
  readonly data?: Record<string, unknown>;
272
+ readonly platform?: Readonly<Record<string, unknown>>;
272
273
  }
273
274
 
274
275
  export interface IcqqInboundMessage {
@@ -341,6 +342,8 @@ export function icqqInboundConversation(endpointKey: string, input: {
341
342
  readonly channelId: string;
342
343
  readonly channelParentGroupId?: string;
343
344
  readonly guildId?: string;
345
+ /** 群名(仅 group 会话使用) */
346
+ readonly name?: string;
344
347
  }): ConversationRef {
345
348
  const endpoint = { id: endpointKey, adapter: ICQQ_ADAPTER_NAME };
346
349
  if (input.channelType === 'private' && input.channelParentGroupId) {
@@ -359,7 +362,8 @@ export function icqqInboundConversation(endpointKey: string, input: {
359
362
  parent: { kind: 'channel', id: input.guildId },
360
363
  };
361
364
  }
362
- return { endpoint, kind: input.channelType, id: input.channelId };
365
+ const name = input.channelType === 'group' ? input.name?.trim() : undefined;
366
+ return { endpoint, kind: input.channelType, id: input.channelId, ...(name ? { name } : {}) };
363
367
  }
364
368
 
365
369
  /**
@@ -394,6 +398,7 @@ const ICQQ_STANDALONE_ELEMENTS = new Set([
394
398
  'json',
395
399
  'share',
396
400
  'long_msg',
401
+ 'multimsg',
397
402
  ] as const);
398
403
 
399
404
  /** Normalize inline image bytes before either temporary-file or native-base64 delivery. */
@@ -461,7 +466,7 @@ export function formatOutboundMessages(payload: unknown): Sendable[] {
461
466
  }
462
467
  const messages = groups.filter(group => group.some(element => typeof element === 'string'
463
468
  ? element.trim() !== ''
464
- : element.type !== 'reply'));
469
+ : element.type !== 'reply' && element.type !== 'quote'));
465
470
  if (messages.length === 0) return ['\u200b'];
466
471
  return messages.map(group => group.length === 1 ? group[0]! : group);
467
472
  }
@@ -485,7 +490,8 @@ function formatOutboundElements(payload: readonly unknown[]): (string | MessageE
485
490
  if (!Number.isSafeInteger(qq) || qq <= 0) {
486
491
  throw new TypeError(`Invalid ICQQ mention target: ${String(target ?? '')}`);
487
492
  }
488
- return { type: 'at', qq };
493
+ const name = typeof item.data?.name === 'string' ? item.data.name.trim() : '';
494
+ return name ? { type: 'at', qq, text: name.startsWith('@') ? name : `@${name}` } : { type: 'at', qq };
489
495
  }
490
496
  case 'image': {
491
497
  const arg = resolveIcqqMediaFile(normalizeIcqqImageData(item.data));
@@ -502,6 +508,13 @@ function formatOutboundElements(payload: readonly unknown[]): (string | MessageE
502
508
  case 'reply': {
503
509
  const id = String(item.data?.message_id ?? item.data?.id ?? '').trim();
504
510
  if (!id) throw new TypeError('ICQQ reply segment requires message_id');
511
+ const quote = item.platform?.icqqQuote as Record<string, unknown> | undefined;
512
+ if (quote) {
513
+ const { user_id, seq, rand, time, message } = quote;
514
+ if (typeof user_id !== 'number' || typeof seq !== 'number' || typeof rand !== 'number'
515
+ || typeof time !== 'number' || typeof message !== 'string') throw new TypeError('Invalid ICQQ quote source');
516
+ return { type: 'quote', user_id, seq, rand, time, message };
517
+ }
505
518
  return { type: 'reply', id };
506
519
  }
507
520
  case 'record':
@@ -528,6 +541,9 @@ function formatOutboundElements(payload: readonly unknown[]): (string | MessageE
528
541
  case 'forward': {
529
542
  const resid = String(item.data?.forward_id ?? item.data?.resid ?? item.data?.id ?? '').trim();
530
543
  if (!resid) throw new TypeError('ICQQ forward segment requires forward_id');
544
+ // Prepared merged forwards need their filename; a long_msg would expand inline.
545
+ const filename = item.platform?.icqqForwardFilename;
546
+ if (typeof filename === 'string' && filename) return { type: 'multimsg', resid, filename };
531
547
  return { type: 'long_msg', resid };
532
548
  }
533
549
  case 'share':