weaver-work-cli 0.1.29 → 0.1.32

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 (185) hide show
  1. package/dist/chunks/archive-UMGX72K6.js +2537 -0
  2. package/dist/chunks/archive-oa-N2IYBLF3.js +1317 -0
  3. package/dist/chunks/asset-GLEGKFG5.js +2109 -0
  4. package/dist/chunks/attachment-content-AQNX5N3S.js +23 -0
  5. package/dist/chunks/blog-E44OTVDA.js +2157 -0
  6. package/dist/chunks/caizhilian-DQUFZXZL.js +10087 -0
  7. package/dist/chunks/calendar-JKPIRKFD.js +1195 -0
  8. package/dist/chunks/chunk-2GA5ZIQL.js +1615 -0
  9. package/dist/chunks/chunk-4YC43QQ4.js +403 -0
  10. package/dist/chunks/chunk-6EFWDL7Y.js +161 -0
  11. package/dist/chunks/chunk-6RKD4DRZ.js +5556 -0
  12. package/dist/chunks/chunk-AJ62BGAW.js +29 -0
  13. package/dist/chunks/chunk-BUSC6UAE.js +43 -0
  14. package/dist/chunks/chunk-C6R3B2ML.js +358 -0
  15. package/dist/chunks/chunk-CVZ2JOSW.js +62 -0
  16. package/dist/chunks/chunk-DW6AUUKS.js +508 -0
  17. package/dist/chunks/chunk-E4Z23GHM.js +6962 -0
  18. package/dist/chunks/chunk-EG6ZU444.js +654 -0
  19. package/dist/chunks/chunk-EZALDOQH.js +383 -0
  20. package/dist/chunks/chunk-FMPJJYYI.js +106 -0
  21. package/dist/chunks/chunk-G2JSIUWF.js +769 -0
  22. package/dist/chunks/chunk-G3QJULO2.js +387 -0
  23. package/dist/chunks/chunk-GCG2NMWR.js +703 -0
  24. package/dist/chunks/chunk-GPMFD4RD.js +75 -0
  25. package/dist/chunks/chunk-H6XSTSLM.js +2357 -0
  26. package/dist/chunks/chunk-H7J4DC5R.js +464 -0
  27. package/dist/chunks/chunk-IURUFGZK.js +477 -0
  28. package/dist/chunks/chunk-LUSPKZKY.js +53 -0
  29. package/dist/chunks/chunk-NIAJ5ZCG.js +73 -0
  30. package/dist/chunks/chunk-NOODWMCL.js +584 -0
  31. package/dist/chunks/chunk-OOUTBLZ4.js +51 -0
  32. package/dist/chunks/chunk-P26ZWSKU.js +73 -0
  33. package/dist/chunks/chunk-QWY6PGL6.js +3472 -0
  34. package/dist/chunks/chunk-WKI2FBIQ.js +15606 -0
  35. package/dist/chunks/chunk-WSKBSQ2U.js +231 -0
  36. package/dist/chunks/chunk-YLCYX7LE.js +371 -0
  37. package/dist/chunks/chunk-YRVDW4WN.js +205 -0
  38. package/dist/chunks/chunk-ZEDWSH32.js +68 -0
  39. package/dist/chunks/continuation-2CKSBLA6.js +11 -0
  40. package/dist/chunks/continuation-HZIZRZBX.js +13 -0
  41. package/dist/chunks/continuation-NLECEJPX.js +11 -0
  42. package/dist/chunks/ebuilder-form-V5FG2EHC.js +2276 -0
  43. package/dist/chunks/ehr-HMFY6VIL.js +5241 -0
  44. package/dist/chunks/employee-SAK2QYXX.js +11 -0
  45. package/dist/chunks/esb-ZYSVB7SG.js +141 -0
  46. package/dist/chunks/fna-B7RKPAZD.js +1444 -0
  47. package/dist/chunks/host-45WED2KK.js +21 -0
  48. package/dist/chunks/host-I4Z6BFYX.js +23 -0
  49. package/dist/chunks/host-KNZ52LJZ.js +17 -0
  50. package/dist/chunks/host-OCH2BCCV.js +19 -0
  51. package/dist/chunks/hrm-2KAZGUHI.js +244 -0
  52. package/dist/chunks/im-ACJJWH4U.js +252 -0
  53. package/dist/chunks/invoice-ZK3WCX2U.js +5179 -0
  54. package/dist/chunks/jiuchuanhui-5PQD3IL2.js +1940 -0
  55. package/dist/chunks/lazy-dispatch-JQXBW3GM.js +28 -0
  56. package/dist/chunks/mail-S2HDDXO2.js +2695 -0
  57. package/dist/chunks/meeting-QVN3I37L.js +504 -0
  58. package/dist/chunks/msg-parse-4GSQ2WTO.js +41 -0
  59. package/dist/chunks/okr-QNG4VC2Q.js +2482 -0
  60. package/dist/chunks/plan-A25EMW6U.js +2025 -0
  61. package/dist/chunks/project-G6XV66DZ.js +1361 -0
  62. package/dist/chunks/registry-2VLUAESA.js +14 -0
  63. package/dist/chunks/registry-7C5UMIPL.js +19 -0
  64. package/dist/chunks/registry-DC6KR3NH.js +18 -0
  65. package/dist/chunks/registry-NYPYMZXG.js +16 -0
  66. package/dist/chunks/registry-TI3CIUXF.js +19 -0
  67. package/dist/chunks/room-recommend-WRTHO6Y2.js +20 -0
  68. package/dist/chunks/schedule-KFIITGSK.js +24 -0
  69. package/dist/chunks/state-Y2XBP6YE.js +15 -0
  70. package/dist/chunks/workflow-DJ7SYWAF.js +245 -0
  71. package/dist/cmd/argv.js +45 -0
  72. package/dist/cmd/docs/index.js +3 -3
  73. package/dist/cmd/lazy-dispatch.js +20 -0
  74. package/dist/cmd/root.js +2 -4
  75. package/dist/cmd/setup/index.js +2 -2
  76. package/dist/cmd/skills/index.js +2 -2
  77. package/dist/core/package-paths.js +61 -0
  78. package/dist/index.js +163 -7
  79. package/dist/internal/e10/auth/xiaoe.js +3 -3
  80. package/dist/internal/e10/request-runtime.js +18 -62
  81. package/dist/internal/skills/detector.js +2 -2
  82. package/dist/shortcuts/contract/data/performance-catalog.js +1306 -0
  83. package/dist/shortcuts/contract/host.js +91 -35
  84. package/dist/shortcuts/contract/index.js +213 -0
  85. package/dist/shortcuts/contract/manifest.js +928 -0
  86. package/dist/shortcuts/contract/ooxml/docx.js +295 -0
  87. package/dist/shortcuts/contract/ooxml/xlsx.js +221 -0
  88. package/dist/shortcuts/contract/ooxml/zip.js +158 -0
  89. package/dist/shortcuts/contract/operations/assistant.js +1156 -0
  90. package/dist/shortcuts/contract/operations/clause-library.js +522 -0
  91. package/dist/shortcuts/contract/operations/compare.js +193 -0
  92. package/dist/shortcuts/contract/operations/credit-page.js +34 -0
  93. package/dist/shortcuts/contract/operations/flow.js +98 -0
  94. package/dist/shortcuts/contract/operations/page.js +66 -0
  95. package/dist/shortcuts/contract/operations/performance.js +733 -0
  96. package/dist/shortcuts/contract/operations/quote.js +557 -0
  97. package/dist/shortcuts/contract/operations/recommend.js +78 -0
  98. package/dist/shortcuts/contract/operations/registry.js +18 -0
  99. package/dist/shortcuts/contract/operations/review.js +83 -0
  100. package/dist/shortcuts/contract/operations/shared.js +37 -0
  101. package/dist/shortcuts/contract/operations/upload.js +108 -0
  102. package/dist/shortcuts/contract/operations/write.js +3 -2
  103. package/dist/shortcuts/index.js +140 -40
  104. package/dist/shortcuts/invoice/manifest.js +34 -11
  105. package/dist/shortcuts/invoice/operations/reim-auto.js +9 -0
  106. package/dist/shortcuts/invoice/operations/reim.js +81 -5
  107. package/dist/shortcuts/invoice/operations/shared.js +12 -5
  108. package/dist/shortcuts/meeting/host.js +45 -3
  109. package/dist/shortcuts/meeting/invitation/docx.js +442 -0
  110. package/dist/shortcuts/meeting/operations/attachment-content.js +418 -0
  111. package/dist/shortcuts/meeting/operations/attachment.js +442 -0
  112. package/dist/shortcuts/meeting/operations/eb/cache.js +57 -0
  113. package/dist/shortcuts/meeting/operations/eb/catalog.js +343 -28
  114. package/dist/shortcuts/meeting/operations/eb/conflict.js +372 -11
  115. package/dist/shortcuts/meeting/operations/eb/create-flow.js +710 -0
  116. package/dist/shortcuts/meeting/operations/eb/decision.js +47 -1
  117. package/dist/shortcuts/meeting/operations/eb/factory.js +129 -11
  118. package/dist/shortcuts/meeting/operations/eb/index.js +122 -2
  119. package/dist/shortcuts/meeting/operations/eb/room-recommend.js +378 -0
  120. package/dist/shortcuts/meeting/operations/eb/room-summary.js +84 -0
  121. package/dist/shortcuts/meeting/operations/eb/schedule.js +450 -0
  122. package/dist/shortcuts/meeting/operations/from-group-chat.js +576 -0
  123. package/dist/shortcuts/meeting/operations/invitation.js +458 -0
  124. package/dist/shortcuts/meeting/operations/minute-content.js +266 -0
  125. package/dist/shortcuts/meeting/operations/pipeline.js +489 -0
  126. package/dist/shortcuts/meeting/operations/qrcode.js +131 -0
  127. package/dist/shortcuts/meeting/operations/receipts.js +1 -1
  128. package/dist/shortcuts/meeting/operations/registry.js +18 -0
  129. package/dist/shortcuts/meeting/operations/summary.js +276 -0
  130. package/dist/shortcuts/meeting/operations/task-notify.js +325 -0
  131. package/dist/shortcuts/meeting/operations.js +42 -1
  132. package/dist/shortcuts/meeting/qr/encoder.js +427 -0
  133. package/dist/shortcuts/meeting/qr/render.js +103 -0
  134. package/dist/shortcuts/workflow/operations/form.js +17 -5
  135. package/docs/contract.md +39 -4
  136. package/docs/invoice.md +5 -5
  137. package/package.json +3 -2
  138. package/scripts/bundle.mjs +63 -0
  139. package/skill-template/business-info.json +25 -4
  140. package/skill-template/domains/jinchengda.md +16 -3
  141. package/skill-template/domains/yepiaotong.md +1 -1
  142. package/skills/weaver-e10-jinchengda/SKILL.md +111 -31
  143. package/skills/weaver-e10-jinchengda/references/contract-agent-entry.md +7 -13
  144. package/skills/weaver-e10-jinchengda/references/contract-ai-assistant.md +150 -0
  145. package/skills/weaver-e10-jinchengda/references/contract-ai-review.md +87 -0
  146. package/skills/weaver-e10-jinchengda/references/contract-clause-library-crud.md +111 -0
  147. package/skills/weaver-e10-jinchengda/references/contract-clause-recommender.md +0 -15
  148. package/skills/weaver-e10-jinchengda/references/contract-clause-reference-save.md +0 -13
  149. package/skills/weaver-e10-jinchengda/references/contract-credit-page.md +50 -0
  150. package/skills/weaver-e10-jinchengda/references/contract-disabled-capabilities.md +4 -2
  151. package/skills/weaver-e10-jinchengda/references/contract-doc-compare.md +74 -0
  152. package/skills/weaver-e10-jinchengda/references/contract-flow-launch.md +84 -0
  153. package/skills/weaver-e10-jinchengda/references/contract-performance-query.md +29 -0
  154. package/skills/weaver-e10-jinchengda/references/contract-quote-to-contract.md +28 -0
  155. package/skills/weaver-e10-jinchengda/references/contract-request-status.md +2 -21
  156. package/skills/weaver-e10-jinchengda/references/contract-request-write.md +0 -24
  157. package/skills/weaver-e10-jinchengda/references/contract-signing-subjects.md +0 -15
  158. package/skills/weaver-e10-jinchengda/references/contract-subject-create.md +0 -17
  159. package/skills/weaver-e10-jinchengda/references/contract-template-recommend.md +70 -0
  160. package/skills/weaver-e10-jinchengda/references/contract-template-selector.md +0 -15
  161. package/skills/weaver-e10-jinchengda/references/contract-workflow-discovery.md +0 -15
  162. package/skills/weaver-e10-jinchengda/references/source-manifest.json +1168 -152
  163. package/skills/weaver-e10-meeting/SKILL.md +493 -17
  164. package/skills/weaver-e10-meeting/references/meeting-change.md +4 -4
  165. package/skills/weaver-e10-meeting/references/meeting-create.md +6 -6
  166. package/skills/weaver-e10-meeting/references/meeting-eb.md +503 -27
  167. package/skills/weaver-e10-meeting/references/meeting-invitation.md +113 -0
  168. package/skills/weaver-e10-meeting/references/meeting-lifecycle.md +6 -6
  169. package/skills/weaver-e10-meeting/references/meeting-minute-file.md +425 -0
  170. package/skills/weaver-e10-meeting/references/meeting-queries.md +4 -4
  171. package/skills/weaver-e10-meeting/references/meeting-receipts-signs.md +15 -15
  172. package/skills/weaver-e10-meeting/references/meeting-verification.md +19 -11
  173. package/skills/weaver-e10-meeting.zip +0 -0
  174. package/skills/weaver-e10-yepiaotong/SKILL.md +9 -5
  175. package/skills/weaver-e10-yepiaotong/references/invoice-enterprise-list.md +1 -1
  176. package/skills/weaver-e10-yepiaotong/references/invoice-personal-list.md +6 -5
  177. package/skills/weaver-e10-yepiaotong/references/invoice-reim.md +14 -11
  178. package/skills/weaver-e10-yepiaotong/references/reim-api-reference.md +97 -56
  179. package/skills/weaver-e10-yepiaotong/references/reim-examples.md +84 -60
  180. package/skills/weaver-e10-yepiaotong/references/reim-form-fill-rules.md +142 -105
  181. package/skills/weaver-e10-yepiaotong/references/reim-matching-rules.md +53 -194
  182. package/skills/weaver-e10-yepiaotong/references/reim-phone-subsidy-rules.md +7 -7
  183. package/skills/weaver-e10-yepiaotong/references/reim-workflow.md +164 -72
  184. package/skills/weaver-e10-yepiaotong/references/source-manifest.json +6 -0
  185. package/templates/meeting/invitation.docx +0 -0
@@ -0,0 +1,3472 @@
1
+ import { createRequire as __esbuildCreateRequire } from 'node:module';
2
+ const require = __esbuildCreateRequire(import.meta.url);
3
+ import {
4
+ collapseNewlines,
5
+ collectI18nIds,
6
+ collectPersonIds,
7
+ escapePipe,
8
+ extractFiles,
9
+ extractImgs,
10
+ extractVideos,
11
+ parseContent,
12
+ senderName
13
+ } from "./chunk-YLCYX7LE.js";
14
+ import {
15
+ imBusinessError,
16
+ imConfirmationError,
17
+ imValidationError
18
+ } from "./chunk-ZEDWSH32.js";
19
+
20
+ // src/shortcuts/im/operations/types.ts
21
+ var READ = "read";
22
+ var WRITE = "write";
23
+ function imSuccess(action, data, meta) {
24
+ const payload = { ok: true, action, data };
25
+ if (meta && Object.keys(meta).length > 0) payload.meta = meta;
26
+ return payload;
27
+ }
28
+ function schemaOf(properties, options = {}) {
29
+ return {
30
+ type: "object",
31
+ additionalProperties: false,
32
+ properties,
33
+ ...options.required?.length ? { required: options.required } : {},
34
+ ...options.description ? { description: options.description } : {}
35
+ };
36
+ }
37
+
38
+ // src/shortcuts/im/operations/shared.ts
39
+ var DEFAULT_PAGE_SIZE = 50;
40
+ var MAX_PAGE_SIZE = 50;
41
+ var MAX_AUTO_PAGES = 100;
42
+ var AUTO_PAGE_INTERVAL_MS = 60;
43
+ var TIME_RANGE_MAX_DAYS = 7;
44
+ var SECONDS_PER_DAY = 24 * 3600;
45
+ var FORBIDDEN_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype", "user", "sender", "operator"]);
46
+ function asObject(value) {
47
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
48
+ throw imValidationError("input_not_object", "\u8F93\u5165\u5FC5\u987B\u662F JSON \u5BF9\u8C61");
49
+ }
50
+ return value;
51
+ }
52
+ function assertNoForbiddenKeys(input) {
53
+ for (const key of Object.keys(input)) {
54
+ if (FORBIDDEN_KEYS.has(key)) {
55
+ throw imValidationError("forbidden_key", `\u8F93\u5165\u5305\u542B\u975E\u6CD5\u5B57\u6BB5\uFF1A${key}`);
56
+ }
57
+ }
58
+ }
59
+ function splitIds(value, field) {
60
+ if (value === void 0 || value === null || value === "") {
61
+ throw imValidationError("id_list_required", `${field} \u5FC5\u586B`);
62
+ }
63
+ const list = String(value).split(",").map((s) => s.trim()).filter(Boolean);
64
+ if (list.length === 0) {
65
+ throw imValidationError("id_list_empty", `${field} \u4E0D\u80FD\u4E3A\u7A7A`);
66
+ }
67
+ for (const item of list) {
68
+ if (!/^\d+$/.test(item) || item === "0") {
69
+ throw imValidationError("id_invalid", `${field} \u542B\u975E\u6CD5 id\uFF08\u5FC5\u987B\u975E 0 \u6570\u5B57\uFF09\uFF1A${item}`);
70
+ }
71
+ }
72
+ return list;
73
+ }
74
+ function toUint(value, field) {
75
+ if (value === void 0 || value === null || value === "") return void 0;
76
+ const numeric = Number(value);
77
+ if (!Number.isInteger(numeric) || numeric < 0) {
78
+ throw imValidationError("number_invalid", `${field} \u5FC5\u987B\u662F\u975E\u8D1F\u6574\u6570`);
79
+ }
80
+ return numeric;
81
+ }
82
+ function toPositiveInt(value, field) {
83
+ if (value === void 0 || value === null || value === "") return void 0;
84
+ const numeric = Number(value);
85
+ if (!Number.isInteger(numeric) || numeric <= 0) {
86
+ throw imValidationError("number_invalid", `${field} \u5FC5\u987B\u662F\u6B63\u6574\u6570`);
87
+ }
88
+ return numeric;
89
+ }
90
+ function compact(body) {
91
+ for (const key of Object.keys(body)) {
92
+ if (body[key] === void 0) delete body[key];
93
+ }
94
+ return body;
95
+ }
96
+ function normalizeAliases(input, aliases) {
97
+ const out = { ...input };
98
+ for (const [canonical, oldKeys] of Object.entries(aliases)) {
99
+ for (const oldKey of oldKeys) {
100
+ if (!(oldKey in out)) continue;
101
+ const oldValue = out[oldKey];
102
+ if (oldValue === void 0 || oldValue === null || oldValue === "") {
103
+ delete out[oldKey];
104
+ continue;
105
+ }
106
+ const canonicalValue = out[canonical];
107
+ const hasCanonical = canonicalValue !== void 0 && canonicalValue !== null && canonicalValue !== "";
108
+ if (hasCanonical && JSON.stringify(canonicalValue) !== JSON.stringify(oldValue)) {
109
+ throw imValidationError(
110
+ "alias_conflict",
111
+ `\u5B57\u6BB5 ${canonical} \u4E0E\u65E7\u5B57\u6BB5 ${oldKey} \u540C\u65F6\u51FA\u73B0\u4E14\u53D6\u503C\u4E0D\u4E00\u81F4\uFF0C\u8BF7\u53EA\u4FDD\u7559\u4E00\u4E2A`
112
+ );
113
+ }
114
+ if (!hasCanonical) out[canonical] = oldValue;
115
+ delete out[oldKey];
116
+ }
117
+ }
118
+ return out;
119
+ }
120
+ function makeMinMaxIdByTm(tmSec) {
121
+ if (!tmSec || tmSec <= 0) return { min: "0", max: "0" };
122
+ const base = BigInt(Math.floor(tmSec)) * 1000000000n;
123
+ return { min: base.toString(), max: (base + 999999999n).toString() };
124
+ }
125
+ function parseTimeToSec(arg, isEnd) {
126
+ if (arg === void 0 || arg === null || arg === "") return 0;
127
+ const s = String(arg).trim();
128
+ if (/^\d{10}$/.test(s)) return Number(s);
129
+ const m = s.match(/^(\d{4})-(\d{1,2})-(\d{1,2})(?:[ T](\d{1,2}):(\d{1,2})(?::(\d{1,2}))?)?$/);
130
+ if (!m) {
131
+ throw imValidationError("time_invalid", `\u65E0\u6CD5\u89E3\u6790\u65F6\u95F4\u53C2\u6570: ${s}\uFF08\u652F\u6301 unix \u79D2 / YYYY-MM-DD / YYYY-MM-DD HH:mm:ss\uFF09`);
132
+ }
133
+ const hh = m[4] !== void 0 ? Number(m[4]) : isEnd ? 23 : 0;
134
+ const mm = m[5] !== void 0 ? Number(m[5]) : isEnd ? 59 : 0;
135
+ const ss = m[6] !== void 0 ? Number(m[6]) : isEnd ? 59 : 0;
136
+ return Math.floor(new Date(Number(m[1]), Number(m[2]) - 1, Number(m[3]), hh, mm, ss).getTime() / 1e3);
137
+ }
138
+ function todayRange() {
139
+ const now = /* @__PURE__ */ new Date();
140
+ const start = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0);
141
+ const end = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 23, 59, 59);
142
+ return { fromSec: Math.floor(start.getTime() / 1e3), toSec: Math.floor(end.getTime() / 1e3) };
143
+ }
144
+ function clampTimeRangeTo7Days(fromSec, toSec) {
145
+ let f = Number(fromSec) > 0 ? Number(fromSec) : 0;
146
+ let t = Number(toSec) > 0 ? Number(toSec) : 0;
147
+ if (f <= 0 && t <= 0) {
148
+ return { fromSec: f, toSec: t, shrunk: false, origFromSec: f, origToSec: t };
149
+ }
150
+ const nowSec = Math.floor(Date.now() / 1e3);
151
+ if (t <= 0) t = nowSec;
152
+ if (f <= 0) f = t - TIME_RANGE_MAX_DAYS * SECONDS_PER_DAY;
153
+ const maxSpan = TIME_RANGE_MAX_DAYS * SECONDS_PER_DAY;
154
+ if (t - f > maxSpan) {
155
+ const d = new Date(t * 1e3);
156
+ const start = new Date(d.getFullYear(), d.getMonth(), d.getDate() - (TIME_RANGE_MAX_DAYS - 1), 0, 0, 0);
157
+ return {
158
+ fromSec: Math.floor(start.getTime() / 1e3),
159
+ toSec: t,
160
+ shrunk: true,
161
+ origFromSec: f,
162
+ origToSec: t
163
+ };
164
+ }
165
+ return { fromSec: f, toSec: t, shrunk: false, origFromSec: f, origToSec: t };
166
+ }
167
+ function formatSec(sec) {
168
+ const pad = (n) => String(n).padStart(2, "0");
169
+ const d = new Date(Number(sec) * 1e3);
170
+ return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`;
171
+ }
172
+ function timeRangeShrinkNotice(clamp) {
173
+ return `\u26A0\uFE0F \u6307\u5B9A\u65F6\u95F4\u8303\u56F4\u8D85\u8FC7 ${TIME_RANGE_MAX_DAYS} \u5929\uFF0C\u5DF2\u81EA\u52A8\u7F29\u77ED\u4E3A\u8BE5\u8303\u56F4\u6700\u540E ${TIME_RANGE_MAX_DAYS} \u5929\uFF1A${formatSec(clamp.origFromSec)} ~ ${formatSec(clamp.origToSec)} \u2192 ${formatSec(clamp.fromSec)} ~ ${formatSec(clamp.toSec)}\uFF08\u5982\u9700\u66F4\u65E9\u5386\u53F2\uFF0C\u8BF7\u5206\u6BB5\u6307\u5B9A \u2264 ${TIME_RANGE_MAX_DAYS} \u5929\u7684\u65F6\u95F4\u8303\u56F4\uFF09`;
174
+ }
175
+ function formatFullTime(ts) {
176
+ if (ts === void 0 || ts === null || ts === "") return "-";
177
+ const d = new Date(Number(ts) * 1e3);
178
+ if (Number.isNaN(d.getTime())) return "-";
179
+ const p = (n) => String(n).padStart(2, "0");
180
+ return `${d.getFullYear()}/${d.getMonth() + 1}/${d.getDate()} ${p(d.getHours())}:${p(d.getMinutes())}:${p(d.getSeconds())}`;
181
+ }
182
+ function findActionMsg(value) {
183
+ const candidate = value?.data?.actionMsg ?? value?.actionMsg;
184
+ if (candidate === void 0 || candidate === null) return null;
185
+ return {
186
+ code: candidate.code !== void 0 ? candidate.code : 0,
187
+ message: candidate.message ?? candidate.msg ?? ""
188
+ };
189
+ }
190
+ function assertImOk(value, actionLabel) {
191
+ const msg = findActionMsg(value);
192
+ if (msg === null) {
193
+ if (Number(value?.code) === 200 && value?.status) return;
194
+ throw imBusinessError("business_error", `${actionLabel}\u5931\u8D25\uFF1A\u7F3A\u5C11 actionMsg`, {
195
+ details: { raw: value }
196
+ });
197
+ }
198
+ if (Number(msg.code) === 0) return;
199
+ const message = msg.message || `${actionLabel}\u5931\u8D25\uFF08actionMsg.code=${msg.code}\uFF09`;
200
+ throw imBusinessError("action_failed", message, { code: msg.code });
201
+ }
202
+ function unwrapInner(value) {
203
+ return value?.data?.data ?? value?.data;
204
+ }
205
+ function isMemberRow(value) {
206
+ return Boolean(value) && typeof value === "object" && (value.uid !== void 0 || value.user !== void 0);
207
+ }
208
+ function extractGroupMembers(inner) {
209
+ if (!inner || typeof inner !== "object") return [];
210
+ for (const key of ["users", "members"]) {
211
+ const list = inner[key];
212
+ if (Array.isArray(list) && list.some(isMemberRow)) return list;
213
+ }
214
+ const datas = Array.isArray(inner.datas) ? inner.datas : [];
215
+ if (datas.some(isMemberRow)) return datas;
216
+ const nested = [];
217
+ for (const group of datas) {
218
+ if (Array.isArray(group?.datas)) nested.push(...group.datas);
219
+ }
220
+ return nested;
221
+ }
222
+ async function resolveAuthUid(host) {
223
+ try {
224
+ const session = await host.getSession();
225
+ return str(session?.userId);
226
+ } catch {
227
+ return "";
228
+ }
229
+ }
230
+ async function pullPaged(options) {
231
+ const maxNum = Math.min(options.num > 0 ? options.num : DEFAULT_PAGE_SIZE, MAX_PAGE_SIZE);
232
+ const idOf = options.idOf ?? ((row) => str(row?.ser_msgid));
233
+ const endBig = /^\d+$/.test(String(options.end ?? "")) ? BigInt(String(options.end)) : 0n;
234
+ const rows = [];
235
+ const seen = /* @__PURE__ */ new Set();
236
+ let curStart = options.start;
237
+ let pages = 0;
238
+ let lastStart = "";
239
+ let exhausted = false;
240
+ let hasMore = false;
241
+ let cappedAtMaxPages = false;
242
+ for (; ; ) {
243
+ const page = await options.requestOnePage(curStart, options.end, maxNum);
244
+ pages += 1;
245
+ if (!page || page.length === 0) {
246
+ exhausted = true;
247
+ break;
248
+ }
249
+ let added = 0;
250
+ let minId = "";
251
+ for (const row of page) {
252
+ const id = idOf(row);
253
+ if (!/^\d+$/.test(id) || seen.has(id)) continue;
254
+ seen.add(id);
255
+ rows.push(row);
256
+ added += 1;
257
+ if (minId === "" || BigInt(id) < BigInt(minId)) minId = id;
258
+ }
259
+ if (added === 0 || minId === "") {
260
+ exhausted = true;
261
+ break;
262
+ }
263
+ lastStart = minId;
264
+ curStart = minId;
265
+ if (endBig > 0n && BigInt(curStart) <= endBig) {
266
+ exhausted = true;
267
+ break;
268
+ }
269
+ if (!options.autoLoop) {
270
+ if (page.length >= maxNum) hasMore = endBig > 0n ? BigInt(curStart) > endBig : true;
271
+ break;
272
+ }
273
+ if (pages >= MAX_AUTO_PAGES) {
274
+ hasMore = true;
275
+ cappedAtMaxPages = true;
276
+ break;
277
+ }
278
+ if (AUTO_PAGE_INTERVAL_MS > 0) {
279
+ await new Promise((resolve3) => setTimeout(resolve3, AUTO_PAGE_INTERVAL_MS));
280
+ }
281
+ }
282
+ return { rows, pages, lastStart, exhausted, hasMore, autoPaged: options.autoLoop, cappedAtMaxPages };
283
+ }
284
+ function paginationMeta(result, num) {
285
+ return {
286
+ pageSize: num,
287
+ pages: result.pages,
288
+ autoPaged: result.autoPaged,
289
+ maxAutoPages: MAX_AUTO_PAGES,
290
+ exhausted: result.exhausted,
291
+ hasMore: result.hasMore,
292
+ ...result.hasMore && result.lastStart ? {
293
+ nextStart: result.lastStart,
294
+ resumeHint: "\u9700\u8981\u66F4\u65E9\u6570\u636E\u65F6\uFF0C\u7528\u76F8\u540C\u8303\u56F4\u518D\u6B21\u8C03\u7528\u5E76\u4F20 start=nextStart\uFF08\u670D\u52A1\u7AEF\u4F1A\u91CD\u590D\u8FD4\u56DE\u8FB9\u754C\u90A3\u6761\uFF0C\u5DF2\u6309\u6D88\u606F id \u53BB\u91CD\uFF09"
295
+ } : {},
296
+ ...result.cappedAtMaxPages ? {
297
+ cappedAtMaxPages: true,
298
+ cappedNote: `\u5DF2\u8FBE\u5355\u6B21\u81EA\u52A8\u7FFB\u9875\u4E0A\u9650 ${MAX_AUTO_PAGES} \u9875\uFF0C\u533A\u95F4\u5185\u4ECD\u6709\u66F4\u65E7\u6570\u636E\uFF0C\u7528 nextStart \u7EE7\u7EED`
299
+ } : {}
300
+ };
301
+ }
302
+ function rangeShrinkMeta(clamp) {
303
+ return {
304
+ shrunk: true,
305
+ maxDays: TIME_RANGE_MAX_DAYS,
306
+ originalFrom: formatSec(clamp.origFromSec),
307
+ originalTo: formatSec(clamp.origToSec),
308
+ from: formatSec(clamp.fromSec),
309
+ to: formatSec(clamp.toSec),
310
+ notice: timeRangeShrinkNotice(clamp)
311
+ };
312
+ }
313
+ function sortMessagesNewestFirst(messages) {
314
+ return messages.sort((a, b) => {
315
+ const ai = str(a.msgid);
316
+ const bi = str(b.msgid);
317
+ const aOk = /^\d+$/.test(ai);
318
+ const bOk = /^\d+$/.test(bi);
319
+ if (!aOk && !bOk) return 0;
320
+ if (!aOk) return 1;
321
+ if (!bOk) return -1;
322
+ return BigInt(bi) === BigInt(ai) ? 0 : BigInt(bi) > BigInt(ai) ? 1 : -1;
323
+ });
324
+ }
325
+ function str(value) {
326
+ if (value === void 0 || value === null) return "";
327
+ return String(value);
328
+ }
329
+ function parseMsg(value) {
330
+ if (!value) return null;
331
+ if (typeof value === "string") {
332
+ try {
333
+ return JSON.parse(value);
334
+ } catch {
335
+ return null;
336
+ }
337
+ }
338
+ if (typeof value === "object") return value;
339
+ return null;
340
+ }
341
+ var MAX_UPLOAD_BYTES = 1024 * 1024 * 200;
342
+
343
+ // src/shortcuts/im/operations/group-read.ts
344
+ var SEARCH_TYPE_MASK = {
345
+ type: 1,
346
+ key: 2,
347
+ members: 8,
348
+ precise: 16,
349
+ owners: 32,
350
+ creators: 64,
351
+ create: 256
352
+ };
353
+ function requireCidUid(cid, uid) {
354
+ const c = String(cid ?? "");
355
+ const u = String(uid ?? "");
356
+ if (!c || !u || c === "0" || u === "0") {
357
+ throw imValidationError("self_identity_missing", "\u8BE5\u67E5\u8BE2\u9700\u8981\u5F53\u524D\u767B\u5F55\u4EBA\u7684 cid/uid\uFF08\u975E 0\uFF09\uFF0C\u8BF7\u786E\u8BA4\u767B\u5F55\u6001\u5B8C\u6574");
358
+ }
359
+ return { cid: c, uid: u };
360
+ }
361
+ function requireGroupId(value) {
362
+ const text = String(value ?? "").trim();
363
+ if (!/^\d+$/.test(text) || text === "0") {
364
+ throw imValidationError("id_invalid", `groupId \u5FC5\u987B\u662F\u975E 0 \u6570\u5B57 ID\uFF08\u6536\u5230\uFF1A${text || "(\u7A7A)"}\uFF09`);
365
+ }
366
+ return text;
367
+ }
368
+ function dayRangeShanghai(offsetDay) {
369
+ const now = /* @__PURE__ */ new Date();
370
+ const tzMs = 8 * 3600 * 1e3;
371
+ const local = new Date(now.getTime() + tzMs);
372
+ const dayStart = Date.UTC(local.getUTCFullYear(), local.getUTCMonth(), local.getUTCDate() + offsetDay);
373
+ return { begin: Math.floor((dayStart - tzMs) / 1e3), end: Math.floor((dayStart + 864e5 - tzMs) / 1e3) - 1 };
374
+ }
375
+ function maskTypeName(mask) {
376
+ const names = [
377
+ [1, "\u5168\u5458\u7FA4"],
378
+ [2, "\u90E8\u95E8\u7FA4"],
379
+ [4, "\u5916\u90E8\u7FA4"],
380
+ [8, "\u4E8B\u9879\u7FA4"],
381
+ [16, "\u8BDD\u9898\u7FA4"]
382
+ ];
383
+ const hit = names.filter(([bit]) => (mask & bit) !== 0).map(([, name]) => name);
384
+ return hit.length ? hit.join("|") : String(mask);
385
+ }
386
+ function stateName(state) {
387
+ if (state === 1) return "\u6B63\u5E38";
388
+ if (state === 0) return "\u5DF2\u9500\u6BC1";
389
+ return `\u72B6\u6001${state}`;
390
+ }
391
+ var groupSearch = {
392
+ name: "im.group.search",
393
+ resource: "group",
394
+ method: "group.search",
395
+ action: "im.group.search",
396
+ summary: "\u6309\u6761\u4EF6\u641C\u7D22\u7FA4\uFF08cond+mask \u5168\u670D\u52A1\u7AEF\u8FC7\u6EE4\uFF0C\u7981\u6B62\u672C\u5730\u8FC7\u6EE4\uFF09",
397
+ capability: "group",
398
+ risk: READ,
399
+ inputSchema: schemaOf({
400
+ name: { type: "string", description: "\u7FA4\u540D\u5173\u952E\u5B57" },
401
+ precise: { type: "boolean", description: "\u7CBE\u786E\u5339\u914D\u540D\u79F0" },
402
+ type: { type: "integer", description: "\u7FA4\u7C7B\u578B\u7B5B\u9009\uFF081 \u666E\u901A/6 \u90E8\u95E8/7 \u5168\u5458\u7B49\uFF09" },
403
+ members: { type: "boolean", description: "\u6211\u6240\u5728\u7684\u7FA4" },
404
+ owner: { type: "boolean", description: "\u6211\u662F\u7FA4\u4E3B\u7684\u7FA4" },
405
+ creator: { type: "boolean", description: "\u6211\u521B\u5EFA\u7684\u7FA4" },
406
+ today: { type: "boolean", description: "\u4ECA\u5929\u521B\u5EFA\u7684\u7FA4" },
407
+ yesterday: { type: "boolean", description: "\u6628\u5929\u521B\u5EFA\u7684\u7FA4" },
408
+ createBegin: { type: "integer", description: "\u521B\u5EFA\u65F6\u95F4\u4E0B\u754C\uFF08unix \u79D2\uFF09" },
409
+ createEnd: { type: "integer", description: "\u521B\u5EFA\u65F6\u95F4\u4E0A\u754C\uFF08unix \u79D2\uFF09" },
410
+ pageSize: { type: "integer", minimum: 1, maximum: 200, description: "\u6BCF\u9875\u5927\u5C0F\uFF08\u9ED8\u8BA4 100\uFF09" }
411
+ }, { description: "\u81F3\u5C11\u63D0\u4F9B\u4E00\u4E2A\u641C\u7D22\u6761\u4EF6" }),
412
+ handler: async (args, { host }) => {
413
+ const cond = {};
414
+ let mask = 0;
415
+ if (args.type !== void 0) {
416
+ mask |= SEARCH_TYPE_MASK.type;
417
+ cond.type = toUint(args.type, "type");
418
+ }
419
+ if (args.name !== void 0 && args.name !== "") {
420
+ mask |= SEARCH_TYPE_MASK.key;
421
+ cond.key = String(args.name);
422
+ }
423
+ if (args.members === true) {
424
+ const self = await host.getSelfIdentity();
425
+ const { cid, uid } = requireCidUid(self.cid, self.uid);
426
+ mask |= SEARCH_TYPE_MASK.members;
427
+ cond.members = [{ cid, uid }];
428
+ }
429
+ if (args.precise === true) {
430
+ mask |= SEARCH_TYPE_MASK.precise;
431
+ cond.precise = 1;
432
+ }
433
+ if (args.owner === true) {
434
+ const self = await host.getSelfIdentity();
435
+ const { cid, uid } = requireCidUid(self.cid, self.uid);
436
+ mask |= SEARCH_TYPE_MASK.owners;
437
+ cond.owners = [{ cid, uid }];
438
+ }
439
+ if (args.creator === true) {
440
+ const self = await host.getSelfIdentity();
441
+ const { cid, uid } = requireCidUid(self.cid, self.uid);
442
+ mask |= SEARCH_TYPE_MASK.creators;
443
+ cond.creators = [{ cid, uid }];
444
+ }
445
+ let create;
446
+ if (args.today === true) create = dayRangeShanghai(0);
447
+ else if (args.yesterday === true) create = dayRangeShanghai(-1);
448
+ else if (args.createBegin !== void 0 || args.createEnd !== void 0) {
449
+ create = { begin: Number(args.createBegin ?? 0), end: Number(args.createEnd ?? 0) };
450
+ }
451
+ if (create) {
452
+ mask |= SEARCH_TYPE_MASK.create;
453
+ cond.create = create;
454
+ }
455
+ if (mask === 0) throw imValidationError("cond_required", "\u81F3\u5C11\u63D0\u4F9B\u4E00\u4E2A\u641C\u7D22\u6761\u4EF6\uFF08name/type/members/owner/creator/today/yesterday/create*\uFF09");
456
+ cond.mask = mask;
457
+ const pageSize = Math.min(toPositiveInt(args.pageSize, "pageSize") ?? 100, 200);
458
+ const body = { page: { size: pageSize, num: 1 }, cond };
459
+ const res = await host.request({
460
+ method: "POST",
461
+ path: "/api/em/msg/executeIm/group/searchGroup",
462
+ body,
463
+ operation: "im.group.search"
464
+ });
465
+ assertImOk(res, "\u641C\u7D22\u7FA4");
466
+ const inner = unwrapInner(res);
467
+ const datas = inner?.datas || [];
468
+ return imSuccess("im.group.search", {
469
+ total: inner?.total ?? datas.length,
470
+ groups: datas.map((g) => ({
471
+ id: str(g.id),
472
+ name: g.name ?? "",
473
+ type: g.type,
474
+ num: g.num,
475
+ createTime: formatFullTime(g.create)
476
+ }))
477
+ });
478
+ }
479
+ };
480
+ var groupInfo = {
481
+ name: "im.group.info",
482
+ resource: "group",
483
+ method: "group.info",
484
+ action: "im.group.info",
485
+ summary: "\u6309\u7FA4 id \u67E5\u57FA\u7840\u4FE1\u606F\uFF08\u652F\u6301\u6279\u91CF\uFF1B\u7C7B\u578B\u4F4D\u7EC4\u5408 + \u72B6\u6001\u5C55\u793A\uFF09",
486
+ capability: "group",
487
+ risk: READ,
488
+ inputSchema: schemaOf({
489
+ groupIds: { type: "array", items: { type: "string" }, description: "\u7FA4 id \u5217\u8868\uFF08\u9017\u53F7\u4E32\u6216\u6570\u7EC4\uFF09" },
490
+ groupId: { type: "string", description: "\u5355\u7FA4 id\uFF08groupIds \u7684\u4FBF\u6377\u5F62\u5F0F\uFF09" }
491
+ }, { description: "groupIds / groupId \u81F3\u5C11\u5176\u4E00" }),
492
+ handler: async (args, { host }) => {
493
+ let ids = [];
494
+ if (Array.isArray(args.groupIds)) ids = args.groupIds.map((x) => String(x));
495
+ else if (args.groupIds) ids = splitIds(args.groupIds, "groupIds");
496
+ if (args.groupId) ids.push(String(args.groupId));
497
+ ids = [...new Set(ids)];
498
+ if (ids.length === 0) throw imValidationError("group_ids_required", "groupIds / groupId \u81F3\u5C11\u5176\u4E00");
499
+ for (const id of ids) {
500
+ if (!/^\d+$/.test(id) || id === "0") throw imValidationError("id_invalid", `\u7FA4 id \u5FC5\u987B\u975E 0 \u6570\u5B57\uFF1A${id}`);
501
+ }
502
+ const body = { trans_id: 0, type: 0, mask: 0, group_id: ids, flag: 0 };
503
+ const res = await host.request({
504
+ method: "POST",
505
+ path: "/api/em/msg/executeIm/group/queryGroupInfo",
506
+ body,
507
+ operation: "im.group.info"
508
+ });
509
+ assertImOk(res, "\u67E5\u8BE2\u7FA4\u4FE1\u606F");
510
+ const inner = unwrapInner(res);
511
+ const datas = inner?.datas || [];
512
+ const groups = datas.map((g) => ({
513
+ groupId: str(g.group_id ?? g.id),
514
+ name: g.name ?? "",
515
+ mask: Number(g.mask ?? 0),
516
+ maskName: maskTypeName(Number(g.mask ?? 0)),
517
+ userNum: g.user_num,
518
+ maxNum: g.max_num,
519
+ hostUid: str(g.host_uid ?? g.hostUid ?? ""),
520
+ state: Number(g.state ?? -1),
521
+ stateName: stateName(Number(g.state ?? -1)),
522
+ createTime: formatFullTime(g.create_time ?? g.createTime)
523
+ }));
524
+ return imSuccess("im.group.info", { total: groups.length, groups });
525
+ }
526
+ };
527
+ var groupUsers = {
528
+ name: "im.group.users",
529
+ resource: "group",
530
+ method: "group.users",
531
+ action: "im.group.users",
532
+ summary: "\u62C9\u53D6\u7FA4\u6210\u5458\u5217\u8868\uFF08\u59D3\u540D\u4E00\u5F8B\u8D70 hrm\uFF0C\u9ED8\u8BA4 mask \u4E0D\u542B name \u4F4D\uFF09",
533
+ capability: "group",
534
+ risk: READ,
535
+ inputSchema: schemaOf({
536
+ groupId: { type: "string", pattern: "^\\d+$", description: "\u7FA4 id" },
537
+ mask: { type: "integer", description: "member_mask\uFF08\u9ED8\u8BA4 142=cid|uid|role|add_time\uFF09" },
538
+ syncType: { type: "integer", enum: [0, 1], description: "0 \u5168\u91CF\uFF08\u9ED8\u8BA4\uFF09/1 \u589E\u91CF" },
539
+ clientUc: { type: "string", description: "\u589E\u91CF\u6E38\u6807 server_uc" }
540
+ }, { required: ["groupId"], description: "\u62C9\u53D6\u7FA4\u6210\u5458" }),
541
+ handler: async (args, { host }) => {
542
+ const groupId = requireGroupId(args.groupId);
543
+ const memberMask = Number(args.mask ?? 142);
544
+ const body = compact({
545
+ group_id: groupId,
546
+ type: 0,
547
+ sync_type: Number(args.syncType ?? 0),
548
+ member_mask: memberMask,
549
+ client_uc: args.clientUc !== void 0 ? String(args.clientUc) : "0"
550
+ });
551
+ const res = await host.request({
552
+ method: "POST",
553
+ path: "/api/em/msg/executeIm/group/getGroupUsers",
554
+ body,
555
+ operation: "im.group.users"
556
+ });
557
+ assertImOk(res, "\u62C9\u53D6\u7FA4\u6210\u5458");
558
+ const inner = unwrapInner(res);
559
+ const members = extractGroupMembers(inner);
560
+ const hasRole = (memberMask & 8) !== 0;
561
+ const hasAddTime = (memberMask & 128) !== 0;
562
+ const hasCid = (memberMask & 2) !== 0;
563
+ const hasUid = (memberMask & 4) !== 0;
564
+ const roleNames = { 0: "\u4E0D\u53EF\u7528", 1: "\u666E\u901A\u6210\u5458", 2: "\u7BA1\u7406\u5458", 3: "\u7FA4\u4E3B", 4: "\u5BA2\u6237", 5: "\u8D1F\u8D23\u4EBA", 6: "\u534F\u52A9\u4EBA\u5458" };
565
+ const personIds = members.map((m) => String(m?.uid ?? "")).filter((x) => x && x !== "0");
566
+ const personMap = personIds.length ? await host.resolveUsersByIds([...new Set(personIds)]) : {};
567
+ const rows = members.map((m) => ({
568
+ uid: hasUid ? str(m.uid) : void 0,
569
+ cid: hasCid ? str(m.cid) : void 0,
570
+ name: personMap[str(m.uid)]?.name || str(m.uid),
571
+ role: hasRole ? Number(m.role_type ?? m.role ?? -1) : void 0,
572
+ roleName: hasRole ? roleNames[Number(m.role_type ?? m.role ?? -1)] ?? "-" : void 0,
573
+ addTime: hasAddTime ? formatFullTime(m.add_time ?? m.addTime) : void 0
574
+ }));
575
+ return imSuccess("im.group.users", {
576
+ groupId,
577
+ totalNum: inner?.total_num ?? rows.length,
578
+ endFlag: inner?.end_flag,
579
+ serverUc: str(inner?.server_uc ?? ""),
580
+ members: rows
581
+ });
582
+ }
583
+ };
584
+ var groupAdmins = {
585
+ name: "im.group.admins",
586
+ resource: "group",
587
+ method: "group.admins",
588
+ action: "im.group.admins",
589
+ summary: "\u6279\u91CF\u83B7\u53D6\u7FA4\u4E3B/\u7BA1\u7406\u5458\uFF08mask \u4F4D 1=\u7FA4\u4E3B/\u8D1F\u8D23\u4EBA 2=\u7BA1\u7406\u5458\uFF0C\u9ED8\u8BA4 3\uFF09",
590
+ capability: "group",
591
+ risk: READ,
592
+ inputSchema: schemaOf({
593
+ groupIds: { type: "array", items: { type: "string" }, description: "\u7FA4 id \u5217\u8868" },
594
+ mask: { type: "integer", description: "\u89D2\u8272\u4F4D\u63A9\u7801\uFF08\u9ED8\u8BA4 3\uFF09" }
595
+ }, { required: ["groupIds"], description: "\u6279\u91CF\u67E5\u8BE2\u7FA4\u7BA1\u7406\u5458" }),
596
+ handler: async (args, { host }) => {
597
+ const ids = Array.isArray(args.groupIds) ? args.groupIds.map((x) => String(x)) : splitIds(args.groupIds, "groupIds");
598
+ const body = { group_ids: ids, mask: Number(args.mask ?? 3) };
599
+ const res = await host.request({
600
+ method: "POST",
601
+ path: "/api/em/msg/executeIm/group/getGroupAdminBatch",
602
+ body,
603
+ operation: "im.group.admins"
604
+ });
605
+ assertImOk(res, "\u67E5\u8BE2\u7FA4\u7BA1\u7406\u5458");
606
+ const inner = unwrapInner(res);
607
+ const datas = inner?.datas || [];
608
+ const roleNames = { 3: "\u7FA4\u4E3B", 2: "\u7BA1\u7406\u5458" };
609
+ const allUids = /* @__PURE__ */ new Set();
610
+ for (const g of datas) {
611
+ for (const it of g?.datas || []) {
612
+ if (it?.user?.uid) allUids.add(String(it.user.uid));
613
+ }
614
+ }
615
+ const personMap = await host.resolveUsersByIds([...allUids]);
616
+ const groups = datas.map((g) => ({
617
+ groupId: str(g.group_id),
618
+ admins: (g?.datas || []).map((it) => ({
619
+ name: personMap[str(it.user?.uid)]?.name || str(it.user?.uid),
620
+ uid: str(it.user?.uid),
621
+ cid: str(it.user?.cid),
622
+ role: Number(it.role ?? -1),
623
+ roleName: roleNames[Number(it.role ?? -1)] ?? "-"
624
+ }))
625
+ }));
626
+ return imSuccess("im.group.admins", { total: groups.length, groups });
627
+ }
628
+ };
629
+ var groupExist = {
630
+ name: "im.group.exist",
631
+ resource: "group",
632
+ method: "group.exist",
633
+ action: "im.group.exist",
634
+ summary: "\u6279\u91CF\u5224\u65AD\u7FA4\u662F\u5426\u5B58\u5728\uFF08ret=0 \u5B58\u5728\uFF1B1209 \u4E0D\u5B58\u5728\uFF09",
635
+ capability: "group",
636
+ risk: READ,
637
+ inputSchema: schemaOf({
638
+ groupIds: { type: "array", items: { type: "string" }, description: "\u7FA4 id \u5217\u8868" }
639
+ }, { required: ["groupIds"], description: "\u6279\u91CF\u5224\u65AD\u7FA4\u662F\u5426\u5B58\u5728" }),
640
+ handler: async (args, { host }) => {
641
+ const ids = Array.isArray(args.groupIds) ? args.groupIds.map((x) => String(x)) : splitIds(args.groupIds, "groupIds");
642
+ for (const id of ids) {
643
+ if (!/^\d+$/.test(id) || id === "0") throw imValidationError("id_invalid", `\u7FA4 id \u5FC5\u987B\u975E 0 \u6570\u5B57\uFF1A${id || "(\u7A7A)"}`);
644
+ }
645
+ const body = { groupIds: ids };
646
+ const res = await host.request({
647
+ method: "POST",
648
+ path: "/api/em/msg/executeIm/group/checkGroupExist",
649
+ body,
650
+ operation: "im.group.exist"
651
+ });
652
+ assertImOk(res, "\u68C0\u67E5\u7FA4\u662F\u5426\u5B58\u5728");
653
+ const inner = unwrapInner(res);
654
+ const results = inner?.results || [];
655
+ return imSuccess("im.group.exist", {
656
+ groups: results.map((r) => ({
657
+ groupId: str(r.group_id),
658
+ exists: Number(r.ret) === 0,
659
+ ret: r.ret
660
+ }))
661
+ });
662
+ }
663
+ };
664
+ var groupUserExist = {
665
+ name: "im.group.userExist",
666
+ resource: "group",
667
+ method: "group.userExist",
668
+ action: "im.group.userExist",
669
+ summary: "\u68C0\u67E5\u7528\u6237\u662F\u5426\u5728\u67D0\u7FA4\u5185\uFF08tenantKey \u81EA\u52A8\u6CE8\u5165\uFF09",
670
+ capability: "group",
671
+ risk: READ,
672
+ inputSchema: schemaOf({
673
+ groupId: { type: "string", pattern: "^\\d+$", description: "\u7FA4 id" },
674
+ users: { type: "array", items: { type: "string" }, description: "\u5F85\u68C0\u67E5 uid \u5217\u8868" }
675
+ }, { required: ["groupId", "users"], description: "\u68C0\u67E5\u7528\u6237\u662F\u5426\u5728\u7FA4\u5185" }),
676
+ handler: async (args, { host }) => {
677
+ const groupId = requireGroupId(args.groupId);
678
+ const users = Array.isArray(args.users) ? args.users.map((x) => String(x)) : splitIds(args.users, "users");
679
+ const session = await host.getSession();
680
+ if (!session.tenantKey) throw imValidationError("tenant_key_missing", "\u767B\u5F55\u6001\u7F3A\u5C11 tenantKey\uFF0C\u8BF7\u91CD\u65B0\u767B\u5F55");
681
+ const body = { tenantKey: session.tenantKey, groupId, users };
682
+ const res = await host.request({
683
+ method: "POST",
684
+ path: "/api/em/msg/executeIm/group/checkGroupUserExist",
685
+ body,
686
+ operation: "im.group.userExist"
687
+ });
688
+ assertImOk(res, "\u68C0\u67E5\u7FA4\u6210\u5458");
689
+ const inner = unwrapInner(res);
690
+ const inGroup = Array.isArray(inner?.users) ? inner.users.map((x) => String(x)) : [];
691
+ const inSet = new Set(inGroup);
692
+ const personMap = await host.resolveUsersByIds(users);
693
+ const rows = users.map((uid) => ({
694
+ uid,
695
+ name: personMap[uid]?.name || uid,
696
+ inGroup: inSet.has(uid)
697
+ }));
698
+ return imSuccess("im.group.userExist", { groupId, total: rows.length, users: rows });
699
+ }
700
+ };
701
+ var groupAnnounceGet = {
702
+ name: "im.group.announce.get",
703
+ resource: "group",
704
+ method: "group.announce.get",
705
+ action: "im.group.announce.get",
706
+ summary: "\u83B7\u53D6\u7FA4\u516C\u544A\uFF08aid=0/\u4E0D\u4F20=\u6700\u65B0\u516C\u544A\uFF09",
707
+ capability: "group",
708
+ risk: READ,
709
+ inputSchema: schemaOf({
710
+ groupId: { type: "string", pattern: "^\\d+$", description: "\u7FA4 id" },
711
+ aid: { type: "string", description: "\u516C\u544A id\uFF08\u9ED8\u8BA4 0=\u6700\u65B0\uFF09" }
712
+ }, { required: ["groupId"], description: "\u83B7\u53D6\u7FA4\u516C\u544A" }),
713
+ handler: async (args, { host }) => {
714
+ const body = { groupId: requireGroupId(args.groupId), aid: args.aid !== void 0 ? String(args.aid) : "0" };
715
+ const res = await host.request({
716
+ method: "POST",
717
+ path: "/api/em/msg/executeIm/group/getAnnouce",
718
+ body,
719
+ operation: "im.group.announce.get"
720
+ });
721
+ assertImOk(res, "\u83B7\u53D6\u7FA4\u516C\u544A");
722
+ const inner = unwrapInner(res);
723
+ const data = inner && typeof inner === "object" && inner.data && typeof inner.data === "object" ? inner.data : inner;
724
+ if (!data || data.aid === void 0 && data.annouce === void 0) {
725
+ return imSuccess("im.group.announce.get", { found: false });
726
+ }
727
+ const personMap = await host.resolveUsersByIds(data?.add_user?.uid ? [String(data.add_user.uid)] : []);
728
+ return imSuccess("im.group.announce.get", {
729
+ found: true,
730
+ aid: str(data.aid),
731
+ annouce: data.annouce ?? "",
732
+ addUserName: personMap[str(data.add_user?.uid)]?.name || str(data.add_user?.uid),
733
+ time: formatFullTime(data.time),
734
+ updateTime: formatFullTime(data.update_tm ?? data.update_time),
735
+ fmark: Number(data.fmark ?? 0),
736
+ mustRead: Number(data.fmark ?? 0) === 1,
737
+ related: str(data.related ?? "")
738
+ });
739
+ }
740
+ };
741
+ var groupAnnounceList = {
742
+ name: "im.group.announce.list",
743
+ resource: "group",
744
+ method: "group.announce.list",
745
+ action: "im.group.announce.list",
746
+ summary: "\u7FA4\u516C\u544A\u5217\u8868\uFF08\u6309 id \u964D\u5E8F\uFF0Cend_flag=1 \u8FD8\u6709\u4E0B\u4E00\u9875\uFF09",
747
+ capability: "group",
748
+ risk: READ,
749
+ inputSchema: schemaOf({
750
+ groupId: { type: "string", pattern: "^\\d+$", description: "\u7FA4 id" },
751
+ aid: { type: "string", description: "\u5206\u9875\u8D77\u59CB\u516C\u544A id\uFF08\u9ED8\u8BA4 0\uFF09" },
752
+ pageSize: { type: "integer", description: "\u5206\u9875\u5927\u5C0F\uFF08\u9ED8\u8BA4\u670D\u52A1\u7AEF\u6700\u5927\uFF09" }
753
+ }, { required: ["groupId"], description: "\u7FA4\u516C\u544A\u5217\u8868" }),
754
+ handler: async (args, { host }) => {
755
+ const body = compact({
756
+ groupId: requireGroupId(args.groupId),
757
+ aid: args.aid !== void 0 ? String(args.aid) : "0",
758
+ pageSize: args.pageSize !== void 0 ? toUint(args.pageSize, "pageSize") : void 0
759
+ });
760
+ const res = await host.request({
761
+ method: "POST",
762
+ path: "/api/em/msg/executeIm/group/getAnnouceList",
763
+ body,
764
+ operation: "im.group.announce.list"
765
+ });
766
+ assertImOk(res, "\u83B7\u53D6\u516C\u544A\u5217\u8868");
767
+ const inner = unwrapInner(res);
768
+ const datas = inner?.datas || inner?.list || [];
769
+ const personIds = datas.map((d) => String(d?.add_user?.uid ?? "")).filter((x) => x && x !== "0");
770
+ const personMap = await host.resolveUsersByIds([...new Set(personIds)]);
771
+ const rows = datas.map((d) => ({
772
+ aid: str(d.aid),
773
+ annouce: d.annouce ?? "",
774
+ deleted: d.annouce === void 0 || d.annouce === null || d.annouce === "",
775
+ addUserName: personMap[str(d.add_user?.uid)]?.name || str(d.add_user?.uid),
776
+ time: formatFullTime(d.time),
777
+ updateTime: formatFullTime(d.update_tm ?? d.update_time),
778
+ mustRead: Number(d.fmark ?? 0) === 1,
779
+ related: str(d.related ?? "")
780
+ }));
781
+ return imSuccess("im.group.announce.list", {
782
+ total: rows.length,
783
+ endFlag: inner?.end_flag,
784
+ hasMore: Number(inner?.end_flag) === 1,
785
+ announcements: rows
786
+ });
787
+ }
788
+ };
789
+ var groupReadOperations = [
790
+ groupSearch,
791
+ groupInfo,
792
+ groupUsers,
793
+ groupAdmins,
794
+ groupExist,
795
+ groupUserExist,
796
+ groupAnnounceGet,
797
+ groupAnnounceList
798
+ ];
799
+
800
+ // src/shortcuts/im/operations/write-util.ts
801
+ import { createHash } from "node:crypto";
802
+ function fingerprint(value) {
803
+ return createHash("sha256").update(JSON.stringify(value ?? null)).digest("hex").slice(0, 32);
804
+ }
805
+ function requireConfirm(action) {
806
+ throw imConfirmationError(action, { hint: "\u91CD\u65B0\u8C03\u7528\u65F6\u4F20\u5165 confirm=true \u4E0E prepare \u8FD4\u56DE\u7684 continuation" });
807
+ }
808
+ async function verifyLease(continuationToken, action, env) {
809
+ const lease = await env.continuation.verify(continuationToken, action);
810
+ const session = await env.host.getSession();
811
+ if (lease.baseUrl !== session.baseUrl || lease.profile !== session.profile || lease.userId !== session.userId) {
812
+ throw imValidationError("context_mismatch", "\u786E\u8BA4\u4E0A\u4E0B\u6587\u5DF2\u53D8\u5316\uFF08\u79DF\u6237\u6216\u767B\u5F55\u8D26\u53F7\u4E0D\u540C\uFF09\uFF0C\u8BF7\u91CD\u65B0\u6267\u884C prepare");
813
+ }
814
+ return lease;
815
+ }
816
+ function makeWritePair(options) {
817
+ return {
818
+ async prepare(args, env) {
819
+ assertNoForbiddenKeys(args);
820
+ const plan = await options.plan(args, env);
821
+ const session = await env.host.getSession();
822
+ const token = await env.continuation.issue({
823
+ operation: options.action,
824
+ baseUrl: session.baseUrl,
825
+ profile: session.profile,
826
+ userId: session.userId,
827
+ snapshotFingerprint: fingerprint(plan.snapshot),
828
+ plan: plan.snapshot
829
+ });
830
+ return imSuccess(`${options.action}.prepare`, {
831
+ summary: plan.summary,
832
+ continuation: token,
833
+ hint: "\u786E\u8BA4\u65E0\u8BEF\u540E\u8C03\u7528 " + options.action + ".apply\uFF0C\u4F20 confirm:true \u4E0E continuation"
834
+ });
835
+ },
836
+ async apply(args, env) {
837
+ assertNoForbiddenKeys(args);
838
+ if (args.confirm !== true) requireConfirm(options.action);
839
+ const lease = await verifyLease(String(args.continuation ?? ""), options.action, env);
840
+ const plan = lease.plan;
841
+ if (lease.snapshotFingerprint !== fingerprint(plan)) {
842
+ throw imValidationError("target_changed", "\u5199\u5165\u76EE\u6807/\u5185\u5BB9\u4E0E prepare \u65F6\u4E0D\u4E00\u81F4\uFF0C\u8BF7\u91CD\u65B0\u6267\u884C prepare");
843
+ }
844
+ const data = await options.execute(plan, env);
845
+ return imSuccess(`${options.action}.apply`, data);
846
+ }
847
+ };
848
+ }
849
+ function fileObjToImg(fileObj) {
850
+ const img = { src: String(fileObj.id || fileObj.fileid) };
851
+ if (fileObj.name) img.nm = String(fileObj.name);
852
+ if (fileObj.type) img.t = String(fileObj.type);
853
+ if (fileObj.imgWidth !== void 0 && fileObj.imgWidth !== null) img.w = String(fileObj.imgWidth);
854
+ if (fileObj.imgHeight !== void 0 && fileObj.imgHeight !== null) img.h = String(fileObj.imgHeight);
855
+ if (fileObj.size !== void 0 && fileObj.size !== null) img.s = String(fileObj.size);
856
+ return img;
857
+ }
858
+ function fileObjToFile(fileObj) {
859
+ const f = { id: String(fileObj.id || fileObj.fileid) };
860
+ if (fileObj.name) f.nm = String(fileObj.name);
861
+ if (fileObj.type) f.t = String(fileObj.type);
862
+ if (fileObj.size !== void 0 && fileObj.size !== null) f.s = String(fileObj.size);
863
+ return f;
864
+ }
865
+
866
+ // src/shortcuts/im/operations/group-write.ts
867
+ async function resolveMembers(args, env) {
868
+ const raw = Array.isArray(args.users) ? args.users.map((x) => String(x)) : splitIds(args.users, "users");
869
+ const map = await env.host.resolveUsersByIds(raw);
870
+ const users = [];
871
+ const failed = [];
872
+ const names = {};
873
+ for (const uid of raw) {
874
+ const p = map[uid];
875
+ const cid = p?.cid || "";
876
+ if (p?.name) names[uid] = p.name;
877
+ if (!uid || uid === "0" || !cid || cid === "0") {
878
+ failed.push({ uid, name: p?.name || "" });
879
+ continue;
880
+ }
881
+ users.push({ cid, uid });
882
+ }
883
+ return { users, failed, names };
884
+ }
885
+ async function defaultGroupName(members, nameOf, selfUid, env) {
886
+ let selfName = selfUid ? nameOf(selfUid) : "";
887
+ if (!selfName) {
888
+ try {
889
+ const self = await env.host.getSelfIdentity();
890
+ if (self.name) selfName = self.name;
891
+ } catch {
892
+ }
893
+ }
894
+ if (!selfName) selfName = selfUid || "\u6211";
895
+ const others = [];
896
+ for (const member of members) {
897
+ if (member.uid === selfUid) continue;
898
+ if (others.length >= 4) break;
899
+ others.push(nameOf(member.uid));
900
+ }
901
+ return [selfName, ...others].join("\u3001");
902
+ }
903
+ var groupCreatePair = makeWritePair({
904
+ action: "im.group.create",
905
+ async plan(args, env) {
906
+ const rawUsers = Array.isArray(args.users) ? args.users.map((x) => String(x)) : splitIds(args.users, "users");
907
+ const names = Array.isArray(args.names) ? args.names.map((x) => String(x)) : [];
908
+ if (names.length && names.length !== rawUsers.length) {
909
+ throw imValidationError("names_mismatch", "names \u6570\u91CF\u5FC5\u987B\u4E0E users \u4E00\u81F4\uFF08\u987A\u5E8F\u4E00\u4E00\u5BF9\u5E94\uFF09");
910
+ }
911
+ const { users, failed, names: resolvedNames } = await resolveMembers(args, env);
912
+ if (failed.length && args.removeFailed !== true) {
913
+ throw imValidationError("members_resolve_failed", `\u4EE5\u4E0B\u6210\u5458\u4FE1\u606F\u83B7\u53D6\u5931\u8D25\uFF08cid/uid \u7F3A\u5931\u6216\u4E3A 0\uFF09\uFF1A${failed.map((f) => f.name || f.uid).join("\u3001")}\uFF1B\u786E\u8BA4\u79FB\u9664\u8BF7\u4F20 removeFailed:true`, { details: failed });
914
+ }
915
+ if (users.length === 0) throw imValidationError("members_empty", "\u6CA1\u6709\u53EF\u5165\u7FA4\u7684\u6210\u5458");
916
+ const selfUid = str((await env.host.getSession()).userId);
917
+ if (selfUid && !users.some((u) => u.uid === selfUid)) {
918
+ throw imValidationError(
919
+ "self_not_included",
920
+ `\u4E0D\u5141\u8BB8\u521B\u5EFA\u4E0D\u5305\u542B\u81EA\u5DF1\u7684\u7FA4\u804A\uFF1Ausers \u5FC5\u987B\u5305\u542B\u64CD\u4F5C\u8005\u81EA\u5DF1\uFF08uid=${selfUid}\uFF09`
921
+ );
922
+ }
923
+ const providedNames = {};
924
+ rawUsers.forEach((uid, index) => {
925
+ if (names[index]) providedNames[uid] = names[index];
926
+ });
927
+ const nameOf = (uid) => providedNames[uid] || resolvedNames[uid] || uid;
928
+ const name = args.name ? String(args.name) : await defaultGroupName(users, nameOf, selfUid, env);
929
+ let admins = [];
930
+ if (args.admins) {
931
+ const adminRaw = Array.isArray(args.admins) ? args.admins.map((x) => String(x)) : splitIds(args.admins, "admins");
932
+ const adminMap = await env.host.resolveUsersByIds(adminRaw);
933
+ const adminFailed = adminRaw.filter((uid) => {
934
+ const cid = adminMap[uid]?.cid || "";
935
+ return !uid || uid === "0" || !cid || cid === "0";
936
+ });
937
+ if (adminFailed.length) {
938
+ throw imValidationError(
939
+ "admins_resolve_failed",
940
+ `\u7BA1\u7406\u5458\u4FE1\u606F\u83B7\u53D6\u5931\u8D25\uFF08cid/uid \u7F3A\u5931\u6216\u4E3A 0\uFF09\uFF1A${adminFailed.map((uid) => adminMap[uid]?.name || uid).join("\u3001")}\uFF1B\u8BF7\u786E\u8BA4\u540E\u91CD\u8BD5\uFF08\u4E0D\u53EF\u9759\u9ED8\u66FF\u6362\u64CD\u4F5C\u4EBA\u8EAB\u4EFD\uFF09`,
941
+ { details: adminFailed }
942
+ );
943
+ }
944
+ admins = adminRaw.map((uid) => ({ cid: adminMap[uid]?.cid || "", uid }));
945
+ }
946
+ return {
947
+ summary: {
948
+ action: "\u521B\u5EFA\u666E\u901A\u7FA4",
949
+ name,
950
+ memberCount: users.length,
951
+ members: users.map((u) => u.uid),
952
+ adminCount: admins.length,
953
+ removeFailed: args.removeFailed === true ? failed.map((f) => f.uid) : []
954
+ },
955
+ snapshot: { name, users, admins, failed, removeFailed: args.removeFailed === true }
956
+ };
957
+ },
958
+ async execute(plan, env) {
959
+ const { name, users, admins } = plan;
960
+ const body = compact({
961
+ name,
962
+ type: 0,
963
+ users,
964
+ attr: admins.length ? { admins } : {}
965
+ });
966
+ const res = await env.host.request({
967
+ method: "POST",
968
+ path: "/api/em/msg/executeIm/group/groupCreate",
969
+ body,
970
+ operation: "im.group.create"
971
+ });
972
+ assertImOk(res, "\u521B\u5EFA\u7FA4");
973
+ const payload = res?.data ?? {};
974
+ const inner = payload?.data ?? {};
975
+ const groupId = str(
976
+ inner.groupId ?? inner.group_id ?? inner.id ?? payload.groupId ?? payload.group_id ?? payload.id ?? ""
977
+ );
978
+ return { groupId, name, rawData: inner && Object.keys(inner).length ? inner : payload };
979
+ }
980
+ });
981
+ var groupInvitePair = makeWritePair({
982
+ action: "im.group.invite",
983
+ async plan(args, env) {
984
+ const groupId = str(args.groupId);
985
+ if (!groupId || groupId === "0") throw imValidationError("id_invalid", "groupId \u5FC5\u987B\u975E 0");
986
+ const { users, failed } = await resolveMembers(args, env);
987
+ if (failed.length && args.removeFailed !== true) {
988
+ throw imValidationError("members_resolve_failed", `\u4EE5\u4E0B\u6210\u5458\u89E3\u6790\u5931\u8D25\uFF1A${failed.map((f) => f.name || f.uid).join("\u3001")}\uFF1B\u786E\u8BA4\u79FB\u9664\u8BF7\u4F20 removeFailed:true`);
989
+ }
990
+ if (users.length === 0) throw imValidationError("members_empty", "\u6CA1\u6709\u53EF\u9080\u8BF7\u7684\u6210\u5458");
991
+ return {
992
+ summary: { action: "\u9080\u8BF7\u5165\u7FA4", groupId, inviteCount: users.length, users: users.map((u) => u.uid), removeFailed: args.removeFailed === true ? failed.map((f) => f.uid) : [] },
993
+ snapshot: { groupId, users }
994
+ };
995
+ },
996
+ async execute(plan, env) {
997
+ const body = { groupId: plan.groupId, users: plan.users };
998
+ const res = await env.host.request({
999
+ method: "POST",
1000
+ path: "/api/em/msg/executeIm/group/inviteGroupUsers",
1001
+ body,
1002
+ operation: "im.group.invite"
1003
+ });
1004
+ assertImOk(res, "\u9080\u8BF7\u5165\u7FA4");
1005
+ return { groupId: plan.groupId, invited: plan.users.length };
1006
+ }
1007
+ });
1008
+ var groupKickPair = makeWritePair({
1009
+ action: "im.group.kick",
1010
+ async plan(args, env) {
1011
+ const groupId = str(args.groupId);
1012
+ if (!groupId || groupId === "0") throw imValidationError("id_invalid", "groupId \u5FC5\u987B\u975E 0");
1013
+ const { users, failed } = await resolveMembers(args, env);
1014
+ if (failed.length && args.removeFailed !== true) {
1015
+ throw imValidationError("members_resolve_failed", `\u4EE5\u4E0B\u6210\u5458\u89E3\u6790\u5931\u8D25\uFF1A${failed.map((f) => f.name || f.uid).join("\u3001")}\uFF1B\u786E\u8BA4\u79FB\u9664\u8BF7\u4F20 removeFailed:true`);
1016
+ }
1017
+ if (users.length === 0) throw imValidationError("members_empty", "\u6CA1\u6709\u53EF\u79FB\u9664\u7684\u6210\u5458");
1018
+ return {
1019
+ summary: { action: "\u8E22\u51FA\u7FA4\u6210\u5458", groupId, kickCount: users.length, users: users.map((u) => u.uid) },
1020
+ snapshot: { groupId, users }
1021
+ };
1022
+ },
1023
+ async execute(plan, env) {
1024
+ const body = { groupId: plan.groupId, users: plan.users };
1025
+ const res = await env.host.request({
1026
+ method: "POST",
1027
+ path: "/api/em/msg/executeIm/group/kickGroupUsers",
1028
+ body,
1029
+ operation: "im.group.kick"
1030
+ });
1031
+ assertImOk(res, "\u8E22\u51FA\u7FA4\u6210\u5458");
1032
+ return { groupId: plan.groupId, kicked: plan.users.length };
1033
+ }
1034
+ });
1035
+ var groupExitPair = makeWritePair({
1036
+ action: "im.group.exit",
1037
+ async plan(args, env) {
1038
+ const groupId = str(args.groupId);
1039
+ if (!groupId || groupId === "0") throw imValidationError("id_invalid", "groupId \u5FC5\u987B\u975E 0");
1040
+ let memberCount;
1041
+ let isOwner = false;
1042
+ try {
1043
+ const infoRes = await env.host.request({
1044
+ method: "POST",
1045
+ path: "/api/em/msg/executeIm/group/queryGroupInfo",
1046
+ body: { trans_id: 0, type: 0, mask: 0, group_id: [groupId], flag: 0 },
1047
+ operation: "im.group.exit.plan.info"
1048
+ });
1049
+ const info = (unwrapInner(infoRes)?.datas || [])[0];
1050
+ if (info) {
1051
+ const raw = info.user_num ?? info.userNum;
1052
+ memberCount = raw === void 0 || raw === null ? void 0 : Number(raw);
1053
+ const hostUid = str(info.host_uid ?? info.hostUid ?? "");
1054
+ if (hostUid) {
1055
+ const self = await env.host.getSelfIdentity();
1056
+ isOwner = hostUid === String(self.uid);
1057
+ }
1058
+ }
1059
+ } catch {
1060
+ }
1061
+ const orphanRisk = isOwner || memberCount !== void 0 && memberCount <= 1;
1062
+ if (orphanRisk && args.acknowledgeOrphanRisk !== true) {
1063
+ throw imValidationError(
1064
+ "owner_exit_ack_required",
1065
+ `\u9000\u7FA4\u98CE\u9669\u786E\u8BA4\u7F3A\u5931\uFF1A${isOwner ? "\u4F60\u662F\u8BE5\u7FA4\u7FA4\u4E3B" : "\u4F60\u662F\u8BE5\u7FA4\u6700\u540E\u4E00\u4E2A\u6210\u5458"}\uFF0C\u9000\u7FA4\u540E\u8BE5\u7FA4\u4F1A\u53D8\u6210\u65E0\u4E3B\u7A7A\u7FA4\uFF0C\u4E4B\u540E join/destroy \u90FD\u4F1A\u88AB\u670D\u52A1\u7AEF\u62D2\u7EDD\uFF081210\uFF09\uFF0C\u53EA\u80FD\u7531\u5BA2\u6237\u7AEF\u6216\u7BA1\u7406\u5458\u5904\u7406\u3002\u786E\u8BA4\u4ECD\u8981\u9000\u7FA4\u8BF7\u4F20 acknowledgeOrphanRisk:true`,
1066
+ { details: { groupId, isOwner, memberCount } }
1067
+ );
1068
+ }
1069
+ return {
1070
+ summary: {
1071
+ action: "\u9000\u51FA\u7FA4\u804A",
1072
+ groupId,
1073
+ ...memberCount === void 0 ? {} : { memberCount },
1074
+ isOwner,
1075
+ ...orphanRisk ? {
1076
+ orphanRisk: true,
1077
+ riskNote: `${isOwner ? "\u4F60\u662F\u7FA4\u4E3B" : "\u4F60\u662F\u6700\u540E\u4E00\u4E2A\u6210\u5458"}\uFF1A\u9000\u7FA4\u540E\u8BE5\u7FA4\u4F1A\u6210\u4E3A\u65E0\u4E3B\u7A7A\u7FA4\uFF0C\u65E0\u6CD5\u518D\u4ECE CLI \u91CD\u65B0\u8FDB\u7FA4\u6216\u89E3\u6563\uFF08\u5B9E\u6D4B 1210 \u6CA1\u6709\u6743\u9650\uFF09\uFF0C\u9700\u7531\u5BA2\u6237\u7AEF\u6216\u7BA1\u7406\u5458\u5904\u7406\u3002`
1078
+ } : {}
1079
+ },
1080
+ snapshot: { groupId, acknowledgeOrphanRisk: args.acknowledgeOrphanRisk === true }
1081
+ };
1082
+ },
1083
+ async execute(plan, env) {
1084
+ const res = await env.host.request({
1085
+ method: "POST",
1086
+ path: "/api/em/msg/executeIm/group/exit",
1087
+ body: { groupId: plan.groupId },
1088
+ operation: "im.group.exit"
1089
+ });
1090
+ assertImOk(res, "\u9000\u51FA\u7FA4\u804A");
1091
+ return { groupId: plan.groupId };
1092
+ }
1093
+ });
1094
+ var groupDestroyPair = makeWritePair({
1095
+ action: "im.group.destroy",
1096
+ async plan(args, env) {
1097
+ const groupId = str(args.groupId);
1098
+ if (!groupId || groupId === "0") throw imValidationError("id_invalid", "groupId \u5FC5\u987B\u975E 0");
1099
+ return {
1100
+ summary: { action: "\u89E3\u6563\u7FA4\u804A\uFF08\u4EC5\u7FA4\u4E3B\u53EF\u6267\u884C\uFF0C\u4E0D\u53EF\u6062\u590D\uFF09", groupId },
1101
+ snapshot: { groupId }
1102
+ };
1103
+ },
1104
+ async execute(plan, env) {
1105
+ const res = await env.host.request({
1106
+ method: "POST",
1107
+ path: "/api/em/msg/executeIm/group/destroy",
1108
+ body: { groupId: plan.groupId },
1109
+ operation: "im.group.destroy"
1110
+ });
1111
+ assertImOk(res, "\u89E3\u6563\u7FA4\u804A");
1112
+ return { groupId: plan.groupId };
1113
+ }
1114
+ });
1115
+ var groupJoinPair = makeWritePair({
1116
+ action: "im.group.join",
1117
+ async plan(args, env) {
1118
+ const groupId = args.groupId !== void 0 && args.groupId !== "" ? str(args.groupId) : "";
1119
+ const token = args.token !== void 0 && args.token !== "" ? String(args.token) : "";
1120
+ if (!groupId && !token) throw imValidationError("target_required", "groupId \u4E0E token \u81F3\u5C11\u5176\u4E00");
1121
+ if (groupId && groupId === "0") throw imValidationError("id_invalid", "groupId \u5FC5\u987B\u975E 0");
1122
+ if (token && token.length > 500) throw imValidationError("token_invalid", "token \u8FC7\u957F");
1123
+ const mark = args.mark !== void 0 && args.mark !== "" ? String(args.mark) : "";
1124
+ if (mark.length > 100) throw imValidationError("mark_too_long", "mark \u4E0D\u80FD\u8D85\u8FC7 100 \u5B57\u8282");
1125
+ return {
1126
+ summary: { action: "\u7533\u8BF7\u52A0\u5165\u7FA4\u804A", groupId: groupId || "(token)", hasMark: Boolean(mark), needApproval: true },
1127
+ snapshot: compact({ groupId: groupId || void 0, token: token || void 0, mark: mark || void 0 })
1128
+ };
1129
+ },
1130
+ async execute(plan, env) {
1131
+ const body = compact({
1132
+ trans_id: 0,
1133
+ dev: 4,
1134
+ rule: 0,
1135
+ auto: 0,
1136
+ group_id: plan.groupId || void 0,
1137
+ mark: plan.mark || void 0,
1138
+ token: plan.token || void 0
1139
+ });
1140
+ const res = await env.host.request({
1141
+ method: "POST",
1142
+ path: "/api/em/msg/executeIm/group/joinGroup",
1143
+ body,
1144
+ operation: "im.group.join"
1145
+ });
1146
+ assertImOk(res, "\u7533\u8BF7\u5165\u7FA4");
1147
+ const flag = Number(res?.data?.data?.flag ?? res?.data?.flag ?? -1);
1148
+ return {
1149
+ flag,
1150
+ note: flag === 1 ? "\u65E0\u9700\u9A8C\u8BC1\uFF0C\u5DF2\u76F4\u63A5\u52A0\u5165" : flag === 0 ? "\u9700\u7BA1\u7406\u5458/\u7FA4\u4E3B\u5BA1\u6279" : "\u672A\u77E5\u7ED3\u679C"
1151
+ };
1152
+ }
1153
+ });
1154
+ function parseSwitchs(raw) {
1155
+ const text = String(raw ?? "");
1156
+ if (!text) return [];
1157
+ return text.split(",").map((pair) => {
1158
+ const [flagRaw, onoffRaw] = pair.split(":");
1159
+ const flag = Number(flagRaw);
1160
+ const onOff = Number(onoffRaw);
1161
+ if (!Number.isInteger(flag) || !Number.isInteger(onOff)) {
1162
+ throw imValidationError("switchs_invalid", `switchs \u5FC5\u987B\u5F62\u5982 flag:onoff\uFF08\u5982 1:1,2:0\uFF09\uFF0C\u6536\u5230\uFF1A${pair}`);
1163
+ }
1164
+ return { flag, on_off: onOff };
1165
+ });
1166
+ }
1167
+ var groupModifyPair = makeWritePair({
1168
+ action: "im.group.modify",
1169
+ async plan(args, env) {
1170
+ const groupId = str(args.groupId);
1171
+ if (!groupId || groupId === "0") throw imValidationError("id_invalid", "groupId \u5FC5\u987B\u975E 0");
1172
+ if (args.onoff !== void 0) {
1173
+ throw imValidationError("field_forbidden", "onoff \u5B57\u6BB5\u670D\u52A1\u7AEF\u4E0D\u5904\u7406\uFF0C\u8BF7\u7528 switchs");
1174
+ }
1175
+ const body = { group_id: groupId };
1176
+ let mask = 0;
1177
+ const set = (bit, key, value) => {
1178
+ if (value !== void 0) {
1179
+ mask |= bit;
1180
+ body[key] = value;
1181
+ }
1182
+ };
1183
+ if (args.num !== void 0) set(1 << 1, "num", toUint(args.num, "num"));
1184
+ if (args.rsonoff !== void 0) set(1 << 3, "rsonoff", toUint(args.rsonoff, "rsonoff"));
1185
+ if (args.history !== void 0) set(1 << 5, "history", toUint(args.history, "history"));
1186
+ if (args.switchs !== void 0) {
1187
+ const list = parseSwitchs(args.switchs);
1188
+ if (list.length) set(1 << 8, "switchs", list);
1189
+ }
1190
+ if (args.gtId !== void 0) set(1 << 11, "gt_id", String(args.gtId));
1191
+ if (args.copyGroupids) {
1192
+ const ids = Array.isArray(args.copyGroupids) ? args.copyGroupids.map((x) => String(x)) : splitIds(args.copyGroupids, "copyGroupids");
1193
+ set(1 << 9, "copy_groupids", ids.map((x) => Number(x)));
1194
+ }
1195
+ const resolveOrFail = async (raw, label) => {
1196
+ const { users, failed } = await resolveMembers({ users: raw }, env);
1197
+ if (failed.length && args.removeFailed !== true) {
1198
+ throw imValidationError(
1199
+ "members_resolve_failed",
1200
+ `${label}\u4FE1\u606F\u83B7\u53D6\u5931\u8D25\uFF08cid/uid \u7F3A\u5931\u6216\u4E3A 0\uFF09\uFF1A${failed.map((f) => f.name ? `${f.name}(${f.uid})` : f.uid).join("\u3001")}\uFF1B\u786E\u8BA4\u79FB\u9664\u8BF7\u4F20 removeFailed:true`,
1201
+ { details: failed }
1202
+ );
1203
+ }
1204
+ return users;
1205
+ };
1206
+ if (args.admins) {
1207
+ const users = await resolveOrFail(args.admins, "\u7BA1\u7406\u5458");
1208
+ if (users.length === 0) throw imValidationError("members_empty", "\u7BA1\u7406\u5458\u89E3\u6790\u4E3A\u7A7A");
1209
+ set(1 << 7, "admins", users);
1210
+ }
1211
+ if (args.delAdmins) {
1212
+ const users = await resolveOrFail(args.delAdmins, "\u5F85\u79FB\u9664\u7BA1\u7406\u5458");
1213
+ if (users.length === 0) throw imValidationError("members_empty", "\u5F85\u79FB\u9664\u7BA1\u7406\u5458\u89E3\u6790\u4E3A\u7A7A");
1214
+ set(1 << 7, "del_admins", users);
1215
+ }
1216
+ if (args.creator) {
1217
+ const users = await resolveOrFail(args.creator, "\u65B0\u7FA4\u4E3B");
1218
+ if (!users.length) throw imValidationError("members_empty", "\u65B0\u7FA4\u4E3B\u89E3\u6790\u5931\u8D25");
1219
+ set(1 << 6, "creator", users[0]);
1220
+ }
1221
+ if (mask === 0) throw imValidationError("field_required", "\u81F3\u5C11\u4FEE\u6539\u4E00\u9879\uFF08num/rsonoff/history/switchs/gtId/copyGroupids/admins/delAdmins/creator\uFF09");
1222
+ body.mask = mask;
1223
+ return {
1224
+ summary: { action: "\u6279\u91CF\u4FEE\u6539\u7FA4\u5C5E\u6027", groupId, mask, changedFields: Object.keys(body).filter((k) => k !== "group_id" && k !== "mask") },
1225
+ snapshot: { groupId, body }
1226
+ };
1227
+ },
1228
+ async execute(plan, env) {
1229
+ const res = await env.host.request({
1230
+ method: "POST",
1231
+ path: "/api/em/msg/executeIm/group/batModGroupInfo",
1232
+ body: plan.body,
1233
+ operation: "im.group.modify"
1234
+ });
1235
+ assertImOk(res, "\u4FEE\u6539\u7FA4\u5C5E\u6027");
1236
+ return { groupId: plan.groupId };
1237
+ }
1238
+ });
1239
+ var groupRenamePair = makeWritePair({
1240
+ action: "im.group.rename",
1241
+ async plan(args, env) {
1242
+ const groupId = str(args.groupId);
1243
+ if (!groupId || groupId === "0") throw imValidationError("id_invalid", "groupId \u5FC5\u987B\u975E 0");
1244
+ const forbidden = ["announce", "type", "state"];
1245
+ for (const key of forbidden) {
1246
+ if (args[key] !== void 0) throw imValidationError("field_forbidden", `${key} \u5B57\u6BB5\u7981\u7528\uFF1Aannounce \u8BF7\u7528\u516C\u544A\u64CD\u4F5C\uFF0Ctype/state \u4F1A\u89E6\u53D1\u9AD8\u5371\u884C\u4E3A`);
1247
+ }
1248
+ const fieldKeys = ["name", "history", "host", "display", "msgSetting", "mark", "gtid"].filter((k) => args[k] !== void 0);
1249
+ if (fieldKeys.length === 0) throw imValidationError("field_required", "\u81F3\u5C11\u4FEE\u6539\u4E00\u9879\uFF1Aname/history/host/display/msgSetting/mark/gtid");
1250
+ if (fieldKeys.length > 1) throw imValidationError("field_conflict", "\u672C\u63A5\u53E3\u4E00\u6B21\u53EA\u80FD\u6539\u4E00\u9879");
1251
+ const field = fieldKeys[0];
1252
+ const maskOrder = { name: 0, history: 8, host: 4, display: 5, msgSetting: 6, mark: 7, gtid: 9 };
1253
+ let info = {};
1254
+ if (field === "host") {
1255
+ const { users, failed } = await resolveMembers({ users: args.host }, env);
1256
+ if (failed.length) {
1257
+ throw imValidationError(
1258
+ "members_resolve_failed",
1259
+ `\u7FA4\u4E3B\u4FE1\u606F\u83B7\u53D6\u5931\u8D25\uFF08cid/uid \u7F3A\u5931\u6216\u4E3A 0\uFF09\uFF1A${failed.map((f) => f.name ? `${f.name}(${f.uid})` : f.uid).join("\u3001")}`,
1260
+ { details: failed }
1261
+ );
1262
+ }
1263
+ if (!users.length) throw imValidationError("members_empty", "\u65B0\u7FA4\u4E3B\u89E3\u6790\u5931\u8D25");
1264
+ info = { host: users[0] };
1265
+ } else if (field === "history" || field === "display" || field === "msgSetting" || field === "mark") {
1266
+ info = { [field === "msgSetting" ? "msg_setting" : field]: toUint(args[field], field) };
1267
+ } else {
1268
+ info = { [field]: field === "gtid" ? String(args[field]) : String(args[field]) };
1269
+ }
1270
+ const data = {
1271
+ trans_id: 0,
1272
+ group_id: groupId,
1273
+ type: 0,
1274
+ dev: 4,
1275
+ mask: maskOrder[field],
1276
+ info
1277
+ };
1278
+ return {
1279
+ summary: { action: `\u4FEE\u6539\u7FA4\u4FE1\u606F\uFF08${field}\uFF09`, groupId, field, value: info[field === "msgSetting" ? "msg_setting" : field] },
1280
+ snapshot: { groupId, data }
1281
+ };
1282
+ },
1283
+ async execute(plan, env) {
1284
+ const res = await env.host.request({
1285
+ method: "POST",
1286
+ path: "/api/em/msg/executeIm/group/modifyGroupInfo",
1287
+ body: { data: plan.data },
1288
+ operation: "im.group.rename"
1289
+ });
1290
+ assertImOk(res, "\u4FEE\u6539\u7FA4\u4FE1\u606F");
1291
+ return { groupId: plan.groupId };
1292
+ }
1293
+ });
1294
+ var groupAnnounceModifyPair = makeWritePair({
1295
+ action: "im.group.announce.modify",
1296
+ async plan(args, env) {
1297
+ const groupId = str(args.groupId);
1298
+ if (!groupId || groupId === "0") throw imValidationError("id_invalid", "groupId \u5FC5\u987B\u975E 0");
1299
+ const isDel = args.del === true || String(args.del) === "1" || String(args.flag) === "1";
1300
+ const aid = args.aid !== void 0 && args.aid !== "" ? String(args.aid) : "0";
1301
+ if (isDel && (!aid || aid === "0")) throw imValidationError("aid_required", "\u5220\u9664\u516C\u544A\u5FC5\u987B\u6307\u5B9A aid");
1302
+ if (!isDel) {
1303
+ const annouce = args.annouce !== void 0 ? String(args.annouce) : "";
1304
+ if (!annouce) throw imValidationError("annouce_required", "\u65B0\u589E/\u4FEE\u6539\u516C\u544A\u5FC5\u987B\u63D0\u4F9B annouce");
1305
+ if (annouce.length > 5e3) throw imValidationError("annouce_too_long", "\u516C\u544A\u5185\u5BB9\u8FC7\u957F");
1306
+ }
1307
+ const summary = { action: isDel ? "\u5220\u9664\u7FA4\u516C\u544A" : aid && aid !== "0" ? "\u4FEE\u6539\u7FA4\u516C\u544A" : "\u65B0\u589E\u7FA4\u516C\u544A", groupId, aid };
1308
+ const snapshot = { groupId, flag: isDel ? 1 : 0, aid };
1309
+ if (!isDel) {
1310
+ const notice = args.notice !== void 0 ? toUint(args.notice, "notice") : 0;
1311
+ const fmark = args.fmark !== void 0 ? toUint(args.fmark, "fmark") : void 0;
1312
+ summary.notice = notice;
1313
+ summary.mustRead = fmark === 1;
1314
+ snapshot.annouce = String(args.annouce);
1315
+ snapshot.notice = notice;
1316
+ if (fmark !== void 0) snapshot.fmark = fmark;
1317
+ if (args.related !== void 0) snapshot.related = String(args.related);
1318
+ }
1319
+ return { summary, snapshot };
1320
+ },
1321
+ async execute(plan, env) {
1322
+ const body = compact({
1323
+ groupId: plan.groupId,
1324
+ flag: plan.flag,
1325
+ aid: plan.aid,
1326
+ annouce: plan.annouce,
1327
+ notice: plan.notice,
1328
+ fmark: plan.fmark,
1329
+ related: plan.related,
1330
+ sensitive_flag: plan.flag === 1 ? void 0 : 1
1331
+ });
1332
+ const res = await env.host.request({
1333
+ method: "POST",
1334
+ path: "/api/em/msg/executeIm/group/modifyAnnouce",
1335
+ body,
1336
+ operation: "im.group.announce.modify"
1337
+ });
1338
+ assertImOk(res, "\u4FEE\u6539\u7FA4\u516C\u544A");
1339
+ const responseAid = str(res?.data?.data?.aid ?? res?.data?.aid ?? "");
1340
+ const deleted = plan.flag === 1;
1341
+ return {
1342
+ groupId: plan.groupId,
1343
+ aid: responseAid && responseAid !== "0" ? responseAid : plan.aid,
1344
+ deleted,
1345
+ ...deleted ? {} : { created: plan.aid === "0" }
1346
+ };
1347
+ }
1348
+ });
1349
+ function buildWriteDefinition(name, method, summary, inputProps, pair) {
1350
+ const requiredInput = Object.keys(inputProps).filter((k) => {
1351
+ const prop = inputProps[k];
1352
+ return prop?.required === true;
1353
+ });
1354
+ const prepareSchema2 = schemaOf(
1355
+ { ...inputProps, removeFailed: { type: "boolean", description: "\u786E\u8BA4\u79FB\u9664\u89E3\u6790\u5931\u8D25\u6210\u5458" } },
1356
+ { required: requiredInput, description: summary }
1357
+ );
1358
+ return [
1359
+ {
1360
+ name: `${name}.prepare`,
1361
+ resource: "group",
1362
+ method: `${method}.prepare`,
1363
+ action: `${name}.prepare`,
1364
+ summary: `${summary}\uFF08prepare\uFF1A\u53EA\u8BFB\u6821\u9A8C + \u5DEE\u5F02\u6458\u8981 + \u7B7E\u53D1\u786E\u8BA4\uFF09`,
1365
+ capability: "group",
1366
+ risk: "read-before-write",
1367
+ requiresConfirmation: true,
1368
+ inputSchema: prepareSchema2,
1369
+ handler: pair.prepare
1370
+ },
1371
+ {
1372
+ name: `${name}.apply`,
1373
+ resource: "group",
1374
+ method: `${method}.apply`,
1375
+ action: `${name}.apply`,
1376
+ summary: `${summary}\uFF08apply\uFF1A\u9700 confirm:true + continuation\uFF09`,
1377
+ capability: "group",
1378
+ risk: WRITE,
1379
+ requiresConfirmation: true,
1380
+ inputSchema: schemaOf({
1381
+ confirm: { type: "boolean", description: "\u5FC5\u987B\u4E3A true" },
1382
+ continuation: { type: "string", minLength: 1 }
1383
+ }, { required: ["confirm", "continuation"], description: summary }),
1384
+ handler: pair.apply
1385
+ }
1386
+ ];
1387
+ }
1388
+ var groupWriteOps = [
1389
+ ...buildWriteDefinition("im.group.create", "group.create", "\u521B\u5EFA\u666E\u901A\u7FA4", {
1390
+ users: { type: "array", items: { type: "string" }, description: "\u7FA4\u6210\u5458 uid\uFF08\u9017\u53F7\u4E32\u6216\u6570\u7EC4\uFF09" },
1391
+ name: { type: "string", description: "\u7FA4\u540D\uFF08\u7F3A\u7701\u81EA\u52A8\u751F\u6210\uFF09" },
1392
+ names: { type: "array", items: { type: "string" }, description: "\u4E0E users \u987A\u5E8F\u5BF9\u5E94\u59D3\u540D\uFF08\u7528\u4E8E\u9ED8\u8BA4\u7FA4\u540D\uFF09" },
1393
+ admins: { type: "array", items: { type: "string" }, description: "\u7BA1\u7406\u5458 uid" }
1394
+ }, groupCreatePair),
1395
+ ...buildWriteDefinition("im.group.invite", "group.invite", "\u9080\u8BF7\u6210\u5458\u5165\u7FA4", {
1396
+ groupId: { type: "string", pattern: "^\\d+$", description: "\u7FA4 id" },
1397
+ users: { type: "array", items: { type: "string" }, description: "\u88AB\u9080\u8BF7 uid" }
1398
+ }, groupInvitePair),
1399
+ ...buildWriteDefinition("im.group.kick", "group.kick", "\u8E22\u51FA\u7FA4\u6210\u5458", {
1400
+ groupId: { type: "string", pattern: "^\\d+$", description: "\u7FA4 id" },
1401
+ users: { type: "array", items: { type: "string" }, description: "\u88AB\u8E22 uid" }
1402
+ }, groupKickPair),
1403
+ ...buildWriteDefinition("im.group.exit", "group.exit", "\u9000\u51FA\u7FA4\u804A", {
1404
+ groupId: { type: "string", pattern: "^\\d+$", description: "\u7FA4 id" },
1405
+ acknowledgeOrphanRisk: {
1406
+ type: "boolean",
1407
+ description: "\u7FA4\u4E3B\u6216\u6700\u540E\u4E00\u4E2A\u6210\u5458\u9000\u7FA4\u65F6\u5FC5\u987B\u663E\u5F0F\u4F20 true\uFF08\u9000\u7FA4\u540E\u8BE5\u7FA4\u4F1A\u53D8\u6210\u65E0\u4E3B\u7A7A\u7FA4\uFF0C\u65E0\u6CD5\u518D join/destroy\uFF09"
1408
+ }
1409
+ }, groupExitPair),
1410
+ ...buildWriteDefinition("im.group.destroy", "group.destroy", "\u89E3\u6563\u7FA4\u804A\uFF08\u4EC5\u7FA4\u4E3B\uFF0C\u4E0D\u53EF\u6062\u590D\uFF09", {
1411
+ groupId: { type: "string", pattern: "^\\d+$", description: "\u7FA4 id" }
1412
+ }, groupDestroyPair),
1413
+ ...buildWriteDefinition("im.group.join", "group.join", "\u7533\u8BF7\u52A0\u5165\u7FA4\u804A", {
1414
+ groupId: { type: "string", pattern: "^\\d+$", description: "\u7FA4 id\uFF08token \u4E8C\u9009\u4E00\uFF09" },
1415
+ token: { type: "string", description: "\u7FA4 token/\u4E8C\u7EF4\u7801\u52A0\u5165" },
1416
+ mark: { type: "string", maxLength: 100, description: "\u7533\u8BF7\u7406\u7531" }
1417
+ }, groupJoinPair),
1418
+ ...buildWriteDefinition("im.group.modify", "group.modify", "\u6279\u91CF\u4FEE\u6539\u7FA4\u5C5E\u6027\uFF08batModGroupInfo\uFF09", {
1419
+ groupId: { type: "string", pattern: "^\\d+$", description: "\u7FA4 id" },
1420
+ num: { type: "integer", description: "\u6700\u5927\u4EBA\u6570" },
1421
+ switchs: { type: "string", description: "\u7FA4\u5F00\u5173\uFF08flag:onoff \u9017\u53F7\u5206\u9694\uFF0C\u5982 1:1,8:0\uFF09" },
1422
+ rsonoff: { type: "integer", enum: [0, 1], description: "\u6D88\u606F\u9605\u8BFB\u72B6\u6001\u5F00\u5173" },
1423
+ history: { type: "integer", description: "\u65B0\u4EBA\u53EF\u770B\u5386\u53F2\u8303\u56F4" },
1424
+ admins: { type: "array", items: { type: "string" }, description: "\u65B0\u589E\u7BA1\u7406\u5458 uid" },
1425
+ delAdmins: { type: "array", items: { type: "string" }, description: "\u79FB\u9664\u7BA1\u7406\u5458 uid" },
1426
+ creator: { type: "string", description: "\u8F6C\u8BA9\u7FA4\u4E3B\uFF08\u5355 uid\uFF09" },
1427
+ copyGroupids: { type: "array", items: { type: "string" }, description: "\u62F7\u8D1D\u7FA4\u5217\u8868" },
1428
+ gtId: { type: "string", description: "\u5173\u8054\u7FA4\u7C7B\u578B id" }
1429
+ }, groupModifyPair),
1430
+ ...buildWriteDefinition("im.group.rename", "group.rename", "\u4FEE\u6539\u7FA4\u4FE1\u606F\uFF08\u4E00\u6B21\u4E00\u9879\uFF1A\u7FA4\u540D/\u5386\u53F2/\u7FA4\u4E3B/\u663E\u793A/\u6253\u6270/\u6807\u8BB0/gtid\uFF09", {
1431
+ groupId: { type: "string", pattern: "^\\d+$", description: "\u7FA4 id" },
1432
+ name: { type: "string", description: "\u6539\u7FA4\u540D" },
1433
+ history: { type: "integer", description: "\u65B0\u4EBA\u5386\u53F2\u6D88\u606F\u8303\u56F4" },
1434
+ host: { type: "string", description: "\u8F6C\u8BA9\u7FA4\u4E3B\uFF08\u5355 uid\uFF09" },
1435
+ display: { type: "integer", enum: [0, 1], description: "\u662F\u5426\u5728\u7FA4\u5217\u8868\u663E\u793A" },
1436
+ msgSetting: { type: "integer", description: "\u6D88\u606F\u6253\u6270\u8BBE\u7F6E" },
1437
+ mark: { type: "integer", description: "\u6807\u8BB0\u4F4D" },
1438
+ gtid: { type: "string", description: "GTID" }
1439
+ }, groupRenamePair),
1440
+ ...buildWriteDefinition("im.group.announce.modify", "group.announce.modify", "\u65B0\u589E/\u4FEE\u6539/\u5220\u9664\u7FA4\u516C\u544A", {
1441
+ groupId: { type: "string", pattern: "^\\d+$", description: "\u7FA4 id" },
1442
+ annouce: { type: "string", description: "\u516C\u544A\u5185\u5BB9\uFF08\u5220\u9664\u65F6\u4E0D\u9700\u8981\uFF09" },
1443
+ aid: { type: "string", description: "\u516C\u544A id\uFF080/\u4E0D\u4F20=\u65B0\u589E\uFF1B\u975E 0=\u4FEE\u6539\uFF1B\u5220\u9664\u5FC5\u586B\uFF09" },
1444
+ del: { type: "boolean", description: "\u5220\u9664\u5F00\u5173" },
1445
+ notice: { type: "integer", enum: [0, 1, 2], description: "0 \u53D1\u901A\u77E5(\u9ED8\u8BA4)/1 \u4E0D\u53D1/2 \u53D1\u5E76@\u5168\u4F53" },
1446
+ fmark: { type: "integer", enum: [0, 1], description: "\u65B0\u4EBA\u5FC5\u770B" },
1447
+ related: { type: "string", description: "\u5173\u8054\u9644\u4EF6 id" }
1448
+ }, groupAnnounceModifyPair)
1449
+ ];
1450
+ var groupWriteOperations = groupWriteOps;
1451
+
1452
+ // src/shortcuts/im/operations/msg-sync.ts
1453
+ var MAX_MSG_ID = String((1n << 63n) - 1n);
1454
+ function resolveRange(args, idKeys = { start: "start", end: "end" }) {
1455
+ const explicitStart = args[idKeys.start];
1456
+ const explicitEnd = args[idKeys.end];
1457
+ if (explicitStart !== void 0 && explicitStart !== null && explicitStart !== "") {
1458
+ return {
1459
+ start: String(explicitStart),
1460
+ end: explicitEnd !== void 0 && explicitEnd !== null && explicitEnd !== "" ? String(explicitEnd) : "0",
1461
+ scope: "explicit-id",
1462
+ shrink: null
1463
+ };
1464
+ }
1465
+ if (args.latest === true) {
1466
+ return { start: MAX_MSG_ID, end: "0", scope: "latest", shrink: null };
1467
+ }
1468
+ const hasFrom = args.from !== void 0 && args.from !== null && args.from !== "";
1469
+ const hasTo = args.to !== void 0 && args.to !== null && args.to !== "";
1470
+ if (hasFrom || hasTo) {
1471
+ const clamp = clampTimeRangeTo7Days(parseTimeToSec(args.from, false), parseTimeToSec(args.to, true));
1472
+ return {
1473
+ start: clamp.toSec > 0 ? makeMinMaxIdByTm(clamp.toSec).max : MAX_MSG_ID,
1474
+ end: clamp.fromSec > 0 ? makeMinMaxIdByTm(clamp.fromSec).min : "0",
1475
+ scope: "range",
1476
+ shrink: clamp.shrunk ? clamp : null
1477
+ };
1478
+ }
1479
+ const range = todayRange();
1480
+ return {
1481
+ start: makeMinMaxIdByTm(range.toSec).max,
1482
+ end: makeMinMaxIdByTm(range.fromSec).min,
1483
+ scope: "today",
1484
+ shrink: null
1485
+ };
1486
+ }
1487
+ function pageSizeOf(args) {
1488
+ const raw = args.num;
1489
+ if (raw === void 0 || raw === null || raw === "") return DEFAULT_PAGE_SIZE;
1490
+ const n = Number(raw);
1491
+ if (!Number.isInteger(n) || n <= 0) throw imValidationError("num_invalid", "num \u5FC5\u987B\u662F\u6B63\u6574\u6570");
1492
+ return Math.min(n, 50);
1493
+ }
1494
+ function emptyPageNote(args) {
1495
+ if (args.latest === true) return "\u8BE5\u4F1A\u8BDD\u6682\u65E0\u4EFB\u4F55\u6D88\u606F\u8BB0\u5F55";
1496
+ const hasRange = args.from !== void 0 && args.from !== "" || args.to !== void 0 && args.to !== "";
1497
+ if (hasRange) return "\u8BE5\u65F6\u95F4\u8303\u56F4\u5185\u65E0\u6D88\u606F\u8BB0\u5F55";
1498
+ return "\u5F53\u5929\u65E0\u6D88\u606F\uFF08\u5982\u9700\u6700\u65B0\u6D88\u606F\u8BF7\u4F20 latest:true\uFF0C\u6216\u6307\u5B9A from/to \u65F6\u95F4\u8303\u56F4\uFF09";
1499
+ }
1500
+ async function enrichMessages(rawRows, host, options = {}) {
1501
+ const rows = rawRows.filter(Boolean);
1502
+ if (rows.length === 0) return [];
1503
+ const i18nIds = collectI18nIds(rows);
1504
+ const personIds = collectPersonIds(rows);
1505
+ const fromUids = rows.map((r) => r.from_uid).filter((x) => Boolean(x));
1506
+ for (const uid of fromUids) personIds.push(uid);
1507
+ const [i18nMap, personMap] = await Promise.all([
1508
+ host.fetchI18nLabels(i18nIds),
1509
+ host.resolveUsersByIds([...new Set(personIds)])
1510
+ ]);
1511
+ const nameMap = {};
1512
+ for (const [uid, p] of Object.entries(personMap)) nameMap[uid] = p.name;
1513
+ const enriched = [];
1514
+ for (const row of rows) {
1515
+ const msgObj = parseMsg(row.msg);
1516
+ const parsed = parseContent(msgObj, { i18nMap, nameMap });
1517
+ const imgs = msgObj ? extractImgs(msgObj) : [];
1518
+ const videos = msgObj ? extractVideos(msgObj) : [];
1519
+ const files = msgObj ? extractFiles(msgObj) : [];
1520
+ const imgFormat = options.imgFormat || "small";
1521
+ const media = [];
1522
+ for (const img of imgs) {
1523
+ media.push({
1524
+ kind: "img",
1525
+ fileId: img.fileId,
1526
+ name: img.name,
1527
+ w: img.w,
1528
+ h: img.h,
1529
+ previewUrl: await host.buildPreviewUrl({
1530
+ fileId: img.fileId,
1531
+ msgid: String(row.ser_msgid ?? ""),
1532
+ kind: "img",
1533
+ imgFormat,
1534
+ ...options.groupId ? { groupId: options.groupId } : {},
1535
+ ...options.user ? { user: options.user } : {}
1536
+ }),
1537
+ downloadUrl: await host.buildDownloadUrl({
1538
+ fileId: img.fileId,
1539
+ msgid: String(row.ser_msgid ?? ""),
1540
+ kind: "img",
1541
+ imgFormat,
1542
+ ...options.groupId ? { groupId: options.groupId } : {},
1543
+ ...options.user ? { user: options.user } : {}
1544
+ })
1545
+ });
1546
+ }
1547
+ for (const v of videos) {
1548
+ media.push({
1549
+ kind: "video",
1550
+ fileId: v.fileId,
1551
+ name: v.name,
1552
+ ext: v.ext,
1553
+ previewUrl: await host.buildPreviewUrl({
1554
+ fileId: v.fileId,
1555
+ msgid: String(row.ser_msgid ?? ""),
1556
+ kind: "video",
1557
+ ...options.groupId ? { groupId: options.groupId } : {},
1558
+ ...options.user ? { user: options.user } : {}
1559
+ }),
1560
+ downloadUrl: await host.buildDownloadUrl({
1561
+ fileId: v.fileId,
1562
+ msgid: String(row.ser_msgid ?? ""),
1563
+ kind: "video",
1564
+ ...options.groupId ? { groupId: options.groupId } : {},
1565
+ ...options.user ? { user: options.user } : {}
1566
+ })
1567
+ });
1568
+ }
1569
+ for (const f of files) {
1570
+ media.push({
1571
+ kind: "file",
1572
+ fileId: f.fileId,
1573
+ name: f.name,
1574
+ size: f.size,
1575
+ downloadUrl: await host.buildDownloadUrl({
1576
+ fileId: f.fileId,
1577
+ msgid: String(row.ser_msgid ?? ""),
1578
+ kind: "img",
1579
+ imgFormat,
1580
+ ...options.groupId ? { groupId: options.groupId } : {},
1581
+ ...options.user ? { user: options.user } : {}
1582
+ })
1583
+ });
1584
+ }
1585
+ const sender = senderName(msgObj || {}, row.from_uid, options.authUid, nameMap);
1586
+ enriched.push({
1587
+ msgid: str(row.ser_msgid),
1588
+ sender,
1589
+ from_uid: str(row.from_uid),
1590
+ time: formatFullTime(row.msgtime),
1591
+ msgtime: row.msgtime,
1592
+ type: parsed.type,
1593
+ typeName: parsed.typeName,
1594
+ title: options.titleFirst ? parsed.title : void 0,
1595
+ content: collapseNewlines(parsed.content),
1596
+ must: parsed.must,
1597
+ fileName: parsed.fileName,
1598
+ media,
1599
+ ...msgObj ? { msg: msgObj } : {}
1600
+ });
1601
+ }
1602
+ return enriched;
1603
+ }
1604
+ var msgSyncSingle = {
1605
+ name: "im.msg.sync.single",
1606
+ resource: "msg",
1607
+ method: "msg.sync.single",
1608
+ action: "im.msg.sync.single",
1609
+ summary: "\u62C9\u53D6\u4E0E\u67D0\u4EBA\u7684\u5355\u804A\u6D88\u606F\uFF08\u5012\u5E8F\uFF0C\u9ED8\u8BA4\u5F53\u5929\uFF1B\u65F6\u95F4\u8303\u56F4\u8F6C\u6D88\u606F id \u533A\u95F4\u5E76\u81EA\u52A8\u7FFB\u9875\u62C9\u5B8C\uFF09",
1610
+ capability: "msg",
1611
+ risk: READ,
1612
+ inputSchema: schemaOf({
1613
+ fromUid: { type: "string", pattern: "^\\d+$", description: "\u5BF9\u65B9 uid\uFF08\u5FC5\u586B\uFF09" },
1614
+ fromCid: { type: "string", pattern: "^\\d+$", description: "\u5BF9\u65B9 cid\uFF08\u5FC5\u586B\uFF09" },
1615
+ num: { type: "integer", minimum: 1, maximum: 50, description: "\u6BCF\u9875\u6570\u91CF\uFF08\u9ED8\u8BA4 50\uFF0C\u6700\u591A 50\uFF09" },
1616
+ latest: { type: "boolean", description: "\u62C9\u6700\u65B0\u4E0D\u9650\u65E5\u671F\uFF08\u65E0\u754C\u533A\u95F4\uFF0C\u53EA\u62C9\u4E00\u9875\uFF09" },
1617
+ from: { type: "string", description: "\u8D77\u59CB\u65F6\u95F4\uFF08YYYY-MM-DD \u6216 YYYY-MM-DD HH:mm:ss \u6216 unix \u79D2\uFF09\uFF1B\u8DE8\u5EA6 > 7 \u5929\u81EA\u52A8\u6536\u655B\u4E3A\u8BE5\u8303\u56F4\u6700\u540E 7 \u5929" },
1618
+ to: { type: "string", description: "\u7ED3\u675F\u65F6\u95F4\uFF08\u540C\u4E0A\uFF09" },
1619
+ start: { type: "string", description: "\u663E\u5F0F\u8D77\u59CB\u6D88\u606F id\uFF08\u6700\u9AD8\u4F18\u5148\uFF09" },
1620
+ end: { type: "string", description: "\u663E\u5F0F\u7ED3\u675F\u6D88\u606F id" },
1621
+ imgFormat: { type: "string", enum: ["small", "large", "original"], description: "\u9884\u89C8\u89C4\u683C\uFF08\u9ED8\u8BA4 small\uFF09" }
1622
+ }, { required: ["fromUid", "fromCid"], description: "\u62C9\u53D6\u5355\u804A\u6D88\u606F" }),
1623
+ handler: async (args, { host }) => {
1624
+ const fromUid = String(args.fromUid);
1625
+ const fromCid = String(args.fromCid);
1626
+ if (!fromUid || !fromCid || fromUid === "0" || fromCid === "0") {
1627
+ throw imValidationError("id_invalid", "fromUid/fromCid \u5FC5\u987B\u975E 0");
1628
+ }
1629
+ const { start, end, scope, shrink } = resolveRange(args);
1630
+ const num = pageSizeOf(args);
1631
+ const autoLoop = end !== "0";
1632
+ let actCode = 0;
1633
+ const pulled = await pullPaged({
1634
+ num,
1635
+ start,
1636
+ end,
1637
+ autoLoop,
1638
+ requestOnePage: async (pageStart, pageEnd, maxNum) => {
1639
+ const body = {
1640
+ trans_id: 0,
1641
+ dev: 4,
1642
+ enc_type: 0,
1643
+ datas: [{ from_cid: fromCid, from_uid: fromUid, start: pageStart, end: pageEnd, max_num: maxNum }]
1644
+ };
1645
+ const res = await host.request({
1646
+ method: "POST",
1647
+ path: "/api/em/msg/executeIm/msg/syncSingleMsg",
1648
+ body,
1649
+ operation: "im.msg.sync.single"
1650
+ });
1651
+ actCode = Number(res?.data?.actionMsg?.code ?? -1);
1652
+ if (actCode === 1303) return [];
1653
+ assertImOk(res, "\u62C9\u53D6\u5355\u804A\u6D88\u606F");
1654
+ const inner = unwrapInner(res);
1655
+ const outerDatas = inner?.datas || [];
1656
+ const rows = [];
1657
+ for (const group of outerDatas) {
1658
+ const list = group?.datas || group?.data || [];
1659
+ if (Array.isArray(list)) rows.push(...list);
1660
+ }
1661
+ return rows;
1662
+ }
1663
+ });
1664
+ const authUid = await resolveAuthUid(host);
1665
+ const messages = await enrichMessages(pulled.rows, host, {
1666
+ authUid,
1667
+ user: { cid: fromCid, uid: fromUid },
1668
+ imgFormat: args.imgFormat
1669
+ });
1670
+ sortMessagesNewestFirst(messages);
1671
+ return imSuccess("im.msg.sync.single", {
1672
+ total: messages.length,
1673
+ messages,
1674
+ range: { from: args.from, to: args.to, start, end, scope, autoPaged: autoLoop },
1675
+ ...paginationMeta(pulled, num),
1676
+ ...shrink ? { rangeShrink: rangeShrinkMeta(shrink) } : {},
1677
+ ...actCode === 1303 ? { empty: true, emptyReason: emptyPageNote(args) } : {}
1678
+ });
1679
+ }
1680
+ };
1681
+ var msgSyncGroup = {
1682
+ name: "im.msg.sync.group",
1683
+ resource: "msg",
1684
+ method: "msg.sync.group",
1685
+ action: "im.msg.sync.group",
1686
+ summary: "\u62C9\u53D6\u67D0\u7FA4\u804A\u5929\u6D88\u606F\uFF08\u5012\u5E8F\uFF0C\u9ED8\u8BA4\u5F53\u5929\uFF1B\u6709\u754C\u533A\u95F4\u81EA\u52A8\u7FFB\u9875\u62C9\u5B8C\uFF1Btype=0 \u5FC5\u4F20\uFF09",
1687
+ capability: "msg",
1688
+ risk: READ,
1689
+ inputSchema: schemaOf({
1690
+ groupId: { type: "string", pattern: "^\\d+$", description: "\u7FA4 id\uFF08\u5FC5\u586B\uFF09" },
1691
+ num: { type: "integer", minimum: 1, maximum: 50, description: "\u6BCF\u9875\u6570\u91CF\uFF08\u9ED8\u8BA4 50\uFF0C\u6700\u591A 50\uFF09" },
1692
+ latest: { type: "boolean", description: "\u62C9\u6700\u65B0\u4E0D\u9650\u65E5\u671F\uFF08\u65E0\u754C\u533A\u95F4\uFF0C\u53EA\u62C9\u4E00\u9875\uFF09" },
1693
+ from: { type: "string", description: "\u8D77\u59CB\u65F6\u95F4\uFF1B\u8DE8\u5EA6 > 7 \u5929\u81EA\u52A8\u6536\u655B\u4E3A\u8BE5\u8303\u56F4\u6700\u540E 7 \u5929" },
1694
+ to: { type: "string", description: "\u7ED3\u675F\u65F6\u95F4\uFF08\u540C\u4E0A\uFF09" },
1695
+ startId: { type: "string", description: "\u663E\u5F0F\u8D77\u59CB\u6D88\u606F id\uFF08\u6700\u9AD8\u4F18\u5148\uFF09" },
1696
+ endId: { type: "string", description: "\u663E\u5F0F\u7ED3\u675F\u6D88\u606F id" },
1697
+ imgFormat: { type: "string", enum: ["small", "large", "original"], description: "\u9884\u89C8\u89C4\u683C\uFF08\u9ED8\u8BA4 small\uFF09" }
1698
+ }, { required: ["groupId"], description: "\u62C9\u53D6\u7FA4\u804A\u6D88\u606F" }),
1699
+ handler: async (args, { host }) => {
1700
+ const groupId = String(args.groupId);
1701
+ if (!groupId || groupId === "0") throw imValidationError("id_invalid", "groupId \u5FC5\u987B\u975E 0");
1702
+ const { start, end, scope, shrink } = resolveRange(args, { start: "startId", end: "endId" });
1703
+ const num = pageSizeOf(args);
1704
+ const autoLoop = end !== "0";
1705
+ let actCode = 0;
1706
+ const pulled = await pullPaged({
1707
+ num,
1708
+ start,
1709
+ end,
1710
+ autoLoop,
1711
+ requestOnePage: async (pageStart, pageEnd, maxNum) => {
1712
+ const body = {
1713
+ trans_id: 0,
1714
+ dev: 4,
1715
+ type: 0,
1716
+ enc_type: 0,
1717
+ datas: [{ group_id: groupId, start: pageStart, end: pageEnd, max_num: maxNum }]
1718
+ };
1719
+ const res = await host.request({
1720
+ method: "POST",
1721
+ path: "/api/em/msg/executeIm/chat/syncGroupMsg",
1722
+ body,
1723
+ operation: "im.msg.sync.group"
1724
+ });
1725
+ actCode = Number(res?.data?.actionMsg?.code ?? -1);
1726
+ if (actCode === 1303) return [];
1727
+ assertImOk(res, "\u62C9\u53D6\u7FA4\u804A\u6D88\u606F");
1728
+ const inner = unwrapInner(res);
1729
+ const outerDatas = inner?.datas || [];
1730
+ const rows = [];
1731
+ for (const group of outerDatas) {
1732
+ const list = group?.datas || group?.data || [];
1733
+ if (Array.isArray(list)) rows.push(...list);
1734
+ }
1735
+ return rows;
1736
+ }
1737
+ });
1738
+ const authUid = await resolveAuthUid(host);
1739
+ const messages = await enrichMessages(pulled.rows, host, {
1740
+ authUid,
1741
+ groupId,
1742
+ imgFormat: args.imgFormat
1743
+ });
1744
+ sortMessagesNewestFirst(messages);
1745
+ return imSuccess("im.msg.sync.group", {
1746
+ groupId,
1747
+ total: messages.length,
1748
+ messages,
1749
+ range: { from: args.from, to: args.to, start, end, scope, autoPaged: autoLoop },
1750
+ ...paginationMeta(pulled, num),
1751
+ ...shrink ? { rangeShrink: rangeShrinkMeta(shrink) } : {},
1752
+ ...actCode === 1303 ? { empty: true, emptyReason: emptyPageNote(args) } : {}
1753
+ });
1754
+ }
1755
+ };
1756
+ var msgTopSync = {
1757
+ name: "im.msg.top.sync",
1758
+ resource: "msg",
1759
+ method: "msg.top.sync",
1760
+ action: "im.msg.top.sync",
1761
+ summary: "\u540C\u6B65\u7FA4\u7F6E\u9876\u6D88\u606F\uFF08\u6458\u8981 + \u6D88\u606F\u5185\u5BB9\uFF09",
1762
+ capability: "msg",
1763
+ risk: READ,
1764
+ inputSchema: schemaOf({
1765
+ groupId: { type: "string", pattern: "^\\d+$", description: "\u7FA4 id\uFF08\u5FC5\u586B\uFF09" },
1766
+ msgids: { type: "array", items: { type: "string" }, description: "\u4EC5\u540C\u6B65\u6307\u5B9A\u6D88\u606F id\uFF08\u7F3A\u7701=\u5168\u90E8\u7F6E\u9876\uFF09" },
1767
+ encType: { type: "integer", enum: [0, 1, 2, 3], description: "\u52A0\u5BC6\u7C7B\u578B\uFF08\u9ED8\u8BA4 0\uFF0C\u4E0D\u89E3\u5BC6\uFF09" },
1768
+ imgFormat: { type: "string", enum: ["small", "large", "original"], description: "\u7F6E\u9876\u6D88\u606F\u5185\u56FE\u7247\u7684\u9884\u89C8\u89C4\u683C\uFF08\u9ED8\u8BA4 small\uFF09" }
1769
+ }, { required: ["groupId"], description: "\u540C\u6B65\u7FA4\u7F6E\u9876\u6D88\u606F" }),
1770
+ handler: async (args, { host }) => {
1771
+ const groupId = String(args.groupId);
1772
+ if (!groupId || groupId === "0") throw imValidationError("id_invalid", "groupId \u5FC5\u987B\u975E 0");
1773
+ const body = compact({
1774
+ group_id: groupId,
1775
+ enc_type: Number(args.encType ?? 0),
1776
+ msgids: Array.isArray(args.msgids) && args.msgids.length ? args.msgids.map((x) => String(x)) : void 0
1777
+ });
1778
+ const res = await host.request({
1779
+ method: "POST",
1780
+ path: "/api/em/msg/executeIm/msg/syncGroupTopMsg",
1781
+ body,
1782
+ operation: "im.msg.top.sync"
1783
+ });
1784
+ assertImOk(res, "\u540C\u6B65\u7F6E\u9876\u6D88\u606F");
1785
+ const inner = unwrapInner(res);
1786
+ const infos = inner?.infos || [];
1787
+ const personIds = infos.map((it) => String(it?.user?.uid ?? "")).filter((x) => x && x !== "0");
1788
+ const personMap = await host.resolveUsersByIds([...new Set(personIds)]);
1789
+ const summary = infos.map((it) => ({
1790
+ msgid: str(it.msgid ?? it.ser_msgid),
1791
+ operator: personMap[str(it.user?.uid)]?.name || str(it.user?.uid),
1792
+ updateTime: formatFullTime(it.update_tm ?? it.time),
1793
+ status: Number(it.status ?? 0),
1794
+ statusNote: Number(it.status) === 1 ? "\u65E0\u6743\u9650/\u5DF2\u5220\u9664" : "\u6B63\u5E38"
1795
+ }));
1796
+ const topRaw = Array.isArray(inner?.datas) ? inner.datas : [];
1797
+ const messages = await enrichMessages(topRaw, host, {
1798
+ groupId,
1799
+ imgFormat: args.imgFormat,
1800
+ authUid: await resolveAuthUid(host)
1801
+ });
1802
+ return imSuccess("im.msg.top.sync", {
1803
+ groupId,
1804
+ total: summary.length,
1805
+ infos: summary,
1806
+ messages
1807
+ });
1808
+ }
1809
+ };
1810
+ var msgReadSingle = {
1811
+ name: "im.msg.read.single",
1812
+ resource: "msg",
1813
+ method: "msg.read.single",
1814
+ action: "im.msg.read.single",
1815
+ summary: "\u67E5\u8BE2\u5355\u804A\u6D88\u606F\u9605\u8BFB\u72B6\u6001\uFF08msgids=\u81EA\u5DF1\u53D1\u51FA / recvMsgids=\u81EA\u5DF1\u63A5\u6536\uFF09",
1816
+ capability: "msg",
1817
+ risk: READ,
1818
+ inputSchema: schemaOf({
1819
+ toUid: { type: "string", pattern: "^\\d+$", description: "\u5BF9\u65B9 uid" },
1820
+ toCid: { type: "string", pattern: "^\\d+$", description: "\u5BF9\u65B9 cid" },
1821
+ msgids: { type: "array", items: { type: "string" }, description: "\u81EA\u5DF1\u53D1\u51FA\u7684\u6D88\u606F id\uFF08\u6700\u591A 50\uFF09" },
1822
+ recvMsgids: { type: "array", items: { type: "string" }, description: "\u81EA\u5DF1\u63A5\u6536\u7684\u6D88\u606F id\uFF08\u6700\u591A 50\uFF09" }
1823
+ }, { required: ["toUid", "toCid"], description: "\u67E5\u8BE2\u5355\u804A\u9605\u8BFB\u72B6\u6001\uFF08msgids/recvMsgids \u81F3\u5C11\u5176\u4E00\uFF09" }),
1824
+ handler: async (args, { host }) => {
1825
+ const hasSent = Array.isArray(args.msgids) && args.msgids.length > 0;
1826
+ const hasRecv = Array.isArray(args.recvMsgids) && args.recvMsgids.length > 0;
1827
+ if (!hasSent && !hasRecv) throw imValidationError("msgids_required", "msgids / recvMsgids \u81F3\u5C11\u5176\u4E00");
1828
+ const body = compact({
1829
+ data: {
1830
+ trans_id: 0,
1831
+ user: { cid: String(args.toCid), uid: String(args.toUid) },
1832
+ msgids: hasSent ? args.msgids.map((x) => String(x)) : void 0,
1833
+ recv_msgids: hasRecv ? args.recvMsgids.map((x) => String(x)) : void 0
1834
+ }
1835
+ });
1836
+ const res = await host.request({
1837
+ method: "POST",
1838
+ path: "/api/em/msg/executeIm/msg/getSingleMsgReadStatus",
1839
+ body,
1840
+ operation: "im.msg.read.single"
1841
+ });
1842
+ assertImOk(res, "\u67E5\u8BE2\u5355\u804A\u9605\u8BFB\u72B6\u6001");
1843
+ const inner = unwrapInner(res);
1844
+ const datas = inner?.datas || [];
1845
+ const rows = Array.isArray(datas) ? datas.map((d) => ({
1846
+ msgid: str(d.msgid),
1847
+ status: Number(d.status),
1848
+ statusName: Number(d.status) === 1 ? "\u5DF2\u8BFB" : "\u672A\u8BFB",
1849
+ time: formatFullTime(d.time),
1850
+ dev: d.dev
1851
+ })) : [];
1852
+ return imSuccess("im.msg.read.single", { total: rows.length, items: rows });
1853
+ }
1854
+ };
1855
+ var msgReadGroup = {
1856
+ name: "im.msg.read.group",
1857
+ resource: "msg",
1858
+ method: "msg.read.group",
1859
+ action: "im.msg.read.group",
1860
+ summary: "\u67E5\u8BE2\u7FA4\u6D88\u606F\u9605\u8BFB\u72B6\u6001\u6C47\u603B\uFF08\u6BCF\u6761\u6D88\u606F\u5DF2\u8BFB/\u672A\u8BFB\u60C5\u51B5\uFF0C\u539F\u6837\u8F93\u51FA\uFF09",
1861
+ capability: "msg",
1862
+ risk: READ,
1863
+ inputSchema: schemaOf({
1864
+ groupId: { type: "string", pattern: "^\\d+$", description: "\u7FA4 id" },
1865
+ msgids: { type: "array", items: { type: "string" }, description: "\u81EA\u5DF1\u53D1\u51FA\u7684\u6D88\u606F id\uFF08\u6700\u591A 50\uFF09" },
1866
+ recvMsgids: { type: "array", items: { type: "string" }, description: "\u522B\u4EBA\u53D1\u51FA\u7684\u6D88\u606F id\uFF08\u6700\u591A 50\uFF09" }
1867
+ }, { required: ["groupId"], description: "\u67E5\u8BE2\u7FA4\u6D88\u606F\u9605\u8BFB\u72B6\u6001" }),
1868
+ handler: async (args, { host }) => {
1869
+ const hasSent = Array.isArray(args.msgids) && args.msgids.length > 0;
1870
+ const hasRecv = Array.isArray(args.recvMsgids) && args.recvMsgids.length > 0;
1871
+ if (!hasSent && !hasRecv) throw imValidationError("msgids_required", "msgids / recvMsgids \u81F3\u5C11\u5176\u4E00");
1872
+ const body = compact({
1873
+ trans_id: 0,
1874
+ group_id: String(args.groupId),
1875
+ msgids: hasSent ? args.msgids.map((x) => String(x)) : void 0,
1876
+ recv_msgids: hasRecv ? args.recvMsgids.map((x) => String(x)) : void 0
1877
+ });
1878
+ const res = await host.request({
1879
+ method: "POST",
1880
+ path: "/api/em/msg/executeIm/msg/getGroupMsgReadStatus",
1881
+ body,
1882
+ operation: "im.msg.read.group"
1883
+ });
1884
+ assertImOk(res, "\u67E5\u8BE2\u7FA4\u9605\u8BFB\u72B6\u6001");
1885
+ const inner = unwrapInner(res);
1886
+ return imSuccess("im.msg.read.group", {
1887
+ groupId: String(args.groupId),
1888
+ raw: Array.isArray(inner) ? inner : inner
1889
+ });
1890
+ }
1891
+ };
1892
+ var msgReadGroupDetail = {
1893
+ name: "im.msg.read.group.detail",
1894
+ resource: "msg",
1895
+ method: "msg.read.group.detail",
1896
+ action: "im.msg.read.group.detail",
1897
+ summary: "\u7FA4\u6D88\u606F\u9605\u8BFB\u8BE6\u60C5\uFF08unread/read count + \u6BCF\u4EBA\u72B6\u6001\uFF09\uFF0C\u652F\u6301\u5206\u9875",
1898
+ capability: "msg",
1899
+ risk: READ,
1900
+ inputSchema: schemaOf({
1901
+ groupId: { type: "string", pattern: "^\\d+$", description: "\u7FA4 id" },
1902
+ msgid: { type: "string", pattern: "^\\d+$", description: "\u6D88\u606F id" },
1903
+ pageSize: { type: "integer", minimum: 1, maximum: 100, description: "\u5206\u9875\u5927\u5C0F\uFF08\u9ED8\u8BA4 10\uFF09" },
1904
+ pageNum: { type: "integer", minimum: 1, description: "\u9875\u7801\uFF08\u9ED8\u8BA4 1\uFF09" },
1905
+ ptype: { type: "integer", description: "MsgPageType\uFF08\u5206\u9875\u542F\u7528\u65F6\u6709\u6548\uFF09" }
1906
+ }, { required: ["groupId", "msgid"], description: "\u7FA4\u6D88\u606F\u9605\u8BFB\u8BE6\u60C5" }),
1907
+ handler: async (args, { host }) => {
1908
+ const paging = args.pageSize !== void 0 || args.pageNum !== void 0;
1909
+ const body = compact({
1910
+ trans_id: 0,
1911
+ group_id: String(args.groupId),
1912
+ msgid: String(args.msgid),
1913
+ page: paging ? { size: Number(args.pageSize ?? 10), num: Number(args.pageNum ?? 1) } : void 0,
1914
+ ptype: paging && args.ptype !== void 0 ? Number(args.ptype) : void 0
1915
+ });
1916
+ const res = await host.request({
1917
+ method: "POST",
1918
+ path: "/api/em/msg/executeIm/group/syncGroupReadStatus",
1919
+ body,
1920
+ operation: "im.msg.read.group.detail"
1921
+ });
1922
+ assertImOk(res, "\u540C\u6B65\u7FA4\u9605\u8BFB\u8BE6\u60C5");
1923
+ const inner = unwrapInner(res);
1924
+ const personIds = (inner?.datas || []).map((d) => String(d?.user?.uid ?? "")).filter((x) => x && x !== "0");
1925
+ const personMap = await host.resolveUsersByIds([...new Set(personIds)]);
1926
+ const rows = (inner?.datas || []).map((d) => ({
1927
+ name: personMap[str(d.user?.uid)]?.name || str(d.user?.uid),
1928
+ uid: str(d.user?.uid),
1929
+ cid: str(d.user?.cid),
1930
+ status: Number(d.status),
1931
+ statusName: Number(d.status) === 1 ? "\u5DF2\u8BFB" : "\u672A\u8BFB",
1932
+ dev: d.dev,
1933
+ time: formatFullTime(d.time)
1934
+ }));
1935
+ return imSuccess("im.msg.read.group.detail", {
1936
+ groupId: String(args.groupId),
1937
+ msgid: String(args.msgid),
1938
+ unreadCount: inner?.unread_count,
1939
+ readCount: inner?.read_count,
1940
+ endFlag: inner?.end_flag,
1941
+ hasMore: Number(inner?.end_flag) === 1,
1942
+ total: rows.length,
1943
+ items: rows
1944
+ });
1945
+ }
1946
+ };
1947
+ var msgReadOperations = [
1948
+ msgSyncSingle,
1949
+ msgSyncGroup,
1950
+ msgTopSync,
1951
+ msgReadSingle,
1952
+ msgReadGroup,
1953
+ msgReadGroupDetail
1954
+ ];
1955
+
1956
+ // src/shortcuts/im/operations/msg-write.ts
1957
+ import { existsSync } from "node:fs";
1958
+ import { resolve } from "node:path";
1959
+ function assertLocalFile(pathValue, field) {
1960
+ const abs = resolve(String(pathValue ?? ""));
1961
+ if (!existsSync(abs)) throw imValidationError("file_not_found", `${field} \u6587\u4EF6\u4E0D\u5B58\u5728: ${abs}`);
1962
+ return abs;
1963
+ }
1964
+ function normalizeContent(args) {
1965
+ const txtRaw = args.txt !== void 0 && args.txt !== null ? String(args.txt) : "";
1966
+ const txt = txtRaw.trim() !== "" ? txtRaw : void 0;
1967
+ const imgPath = args.img || args.imgPath ? String(args.img || args.imgPath) : void 0;
1968
+ const filePath = args.file || args.filePath ? String(args.file || args.filePath) : void 0;
1969
+ if (!txt && !imgPath && !filePath) {
1970
+ throw imValidationError("content_required", "txt / img / file \u81F3\u5C11\u63D0\u4F9B\u4E00\u79CD\uFF08\u7A7A\u767D\u6587\u672C\u4E0D\u7B97\u5185\u5BB9\uFF0C\u7981\u6B62\u53D1\u9001\u7A7A\u767D\u6D88\u606F\uFF09");
1971
+ }
1972
+ if (imgPath && filePath) {
1973
+ throw imValidationError("content_conflict", "img \u4E0E file \u4E0D\u80FD\u540C\u65F6\u63D0\u4F9B\uFF08\u4E00\u6B21\u53D1\u4E00\u79CD\u5A92\u4F53\uFF09");
1974
+ }
1975
+ return { txt, imgPath, filePath };
1976
+ }
1977
+ var sendSinglePair = makeWritePair({
1978
+ action: "im.msg.send.single",
1979
+ async plan(args, env) {
1980
+ const toUid = str(args.toUid);
1981
+ const toCid = str(args.toCid);
1982
+ if (!toUid || !toCid || toUid === "0" || toCid === "0") {
1983
+ throw imValidationError("id_invalid", "toUid/toCid \u5FC5\u987B\u975E 0");
1984
+ }
1985
+ const content = normalizeContent(args);
1986
+ const summary = {
1987
+ action: "\u53D1\u9001\u5355\u804A\u6D88\u606F",
1988
+ toUid,
1989
+ toCid,
1990
+ hasTxt: Boolean(content.txt),
1991
+ hasImg: Boolean(content.imgPath),
1992
+ hasFile: Boolean(content.filePath)
1993
+ };
1994
+ const snapshot = { toUid, toCid };
1995
+ if (content.txt) {
1996
+ snapshot.txt = content.txt;
1997
+ summary.textPreview = content.txt.length > 60 ? `${content.txt.slice(0, 60)}\u2026` : content.txt;
1998
+ }
1999
+ if (content.imgPath) {
2000
+ const abs = assertLocalFile(content.imgPath, "img");
2001
+ snapshot.imgPath = abs;
2002
+ summary.fileName = abs.split(/[\\/]/).pop();
2003
+ }
2004
+ if (content.filePath) {
2005
+ const abs = assertLocalFile(content.filePath, "file");
2006
+ snapshot.filePath = abs;
2007
+ summary.fileName = abs.split(/[\\/]/).pop();
2008
+ }
2009
+ return { summary, snapshot };
2010
+ },
2011
+ async execute(plan, env) {
2012
+ const body = { reciver: { cid: plan.toCid, uid: plan.toUid } };
2013
+ if (plan.txt !== void 0) body.txt = plan.txt;
2014
+ if (plan.imgPath) {
2015
+ const fileObj = await env.host.uploadFile(plan.imgPath, { shareUsers: plan.toUid });
2016
+ body.img = fileObjToImg(fileObj);
2017
+ }
2018
+ if (plan.filePath) {
2019
+ const fileObj = await env.host.uploadFile(plan.filePath, { shareUsers: plan.toUid });
2020
+ body.file = fileObjToFile(fileObj);
2021
+ }
2022
+ const res = await env.host.request({
2023
+ method: "POST",
2024
+ path: "/api/em/msg/executeIm/send/sendSingleMsg",
2025
+ body,
2026
+ operation: "im.msg.send.single"
2027
+ });
2028
+ assertImOk(res, "\u53D1\u9001\u5355\u804A\u6D88\u606F");
2029
+ return { toUid: plan.toUid, toCid: plan.toCid, sent: true };
2030
+ }
2031
+ });
2032
+ var sendGroupPair = makeWritePair({
2033
+ action: "im.msg.send.group",
2034
+ async plan(args, env) {
2035
+ const groupId = str(args.groupId);
2036
+ if (!groupId || groupId === "0") throw imValidationError("id_invalid", "groupId \u5FC5\u987B\u975E 0");
2037
+ const content = normalizeContent(args);
2038
+ const summary = { action: "\u53D1\u9001\u7FA4\u804A\u6D88\u606F", groupId, hasTxt: Boolean(content.txt), hasImg: Boolean(content.imgPath), hasFile: Boolean(content.filePath) };
2039
+ const snapshot = { groupId };
2040
+ if (content.txt) {
2041
+ snapshot.txt = content.txt;
2042
+ summary.textPreview = content.txt.length > 60 ? `${content.txt.slice(0, 60)}\u2026` : content.txt;
2043
+ }
2044
+ if (content.imgPath) {
2045
+ const abs = assertLocalFile(content.imgPath, "img");
2046
+ snapshot.imgPath = abs;
2047
+ summary.fileName = abs.split(/[\\/]/).pop();
2048
+ }
2049
+ if (content.filePath) {
2050
+ const abs = assertLocalFile(content.filePath, "file");
2051
+ snapshot.filePath = abs;
2052
+ summary.fileName = abs.split(/[\\/]/).pop();
2053
+ }
2054
+ return { summary, snapshot };
2055
+ },
2056
+ async execute(plan, env) {
2057
+ const body = { groupId: plan.groupId };
2058
+ if (plan.txt !== void 0) body.txt = plan.txt;
2059
+ if (plan.imgPath) {
2060
+ const fileObj = await env.host.uploadFile(plan.imgPath, { shareGroups: plan.groupId });
2061
+ body.img = fileObjToImg(fileObj);
2062
+ }
2063
+ if (plan.filePath) {
2064
+ const fileObj = await env.host.uploadFile(plan.filePath, { shareGroups: plan.groupId });
2065
+ body.file = fileObjToFile(fileObj);
2066
+ }
2067
+ const res = await env.host.request({
2068
+ method: "POST",
2069
+ path: "/api/em/msg/executeIm/send/sendGroupMsg",
2070
+ body,
2071
+ operation: "im.msg.send.group"
2072
+ });
2073
+ assertImOk(res, "\u53D1\u9001\u7FA4\u804A\u6D88\u606F");
2074
+ return { groupId: plan.groupId, sent: true };
2075
+ }
2076
+ });
2077
+ function findWithdrawTimeOut(value) {
2078
+ if (!value || typeof value !== "object") return null;
2079
+ if (value.time_out !== void 0 && value.time_out !== null && String(value.time_out) !== "") {
2080
+ return String(value.time_out);
2081
+ }
2082
+ for (const key of Object.keys(value)) {
2083
+ const found = findWithdrawTimeOut(value[key]);
2084
+ if (found !== null) return found;
2085
+ }
2086
+ return null;
2087
+ }
2088
+ function formatWithdrawInterval(seconds) {
2089
+ const total = parseInt(seconds, 10);
2090
+ if (!Number.isFinite(total) || total <= 0) return `${seconds} \u79D2`;
2091
+ if (total < 60) return `${total} \u79D2`;
2092
+ const minutes = Math.floor(total / 60);
2093
+ const rest = total % 60;
2094
+ return rest > 0 ? `${minutes} \u5206\u949F ${rest} \u79D2` : `${minutes} \u5206\u949F`;
2095
+ }
2096
+ var withdrawPair = makeWritePair({
2097
+ action: "im.msg.withdraw",
2098
+ async plan(args, env) {
2099
+ const type = String(args.type || "single");
2100
+ if (type !== "single" && type !== "group") throw imValidationError("type_invalid", "type \u5FC5\u987B\u662F single \u6216 group");
2101
+ const msgid = str(args.msgid);
2102
+ if (!msgid || msgid === "0") throw imValidationError("id_invalid", "msgid \u5FC5\u987B\u975E 0");
2103
+ const snapshot = { type, msgid };
2104
+ let source;
2105
+ if (type === "single") {
2106
+ const toUid = str(args.toUid);
2107
+ const toCid = str(args.toCid);
2108
+ if (!toUid || !toCid || toUid === "0" || toCid === "0") throw imValidationError("id_invalid", "toUid/toCid \u5FC5\u987B\u975E 0\uFF08\u64A4\u56DE\u5355\u804A\u6D88\u606F\uFF09");
2109
+ snapshot.toUid = toUid;
2110
+ snapshot.toCid = toCid;
2111
+ source = { flag: 0, user: { cid: toCid, uid: toUid } };
2112
+ } else {
2113
+ const groupId = str(args.groupId);
2114
+ if (!groupId || groupId === "0") throw imValidationError("id_invalid", "groupId \u5FC5\u987B\u975E 0");
2115
+ snapshot.groupId = groupId;
2116
+ source = { flag: 1, group_id: groupId };
2117
+ }
2118
+ return {
2119
+ summary: { action: type === "single" ? "\u64A4\u56DE\u5355\u804A\u6D88\u606F" : "\u64A4\u56DE\u7FA4\u804A\u6D88\u606F", msgid, source },
2120
+ snapshot: { ...snapshot, source }
2121
+ };
2122
+ },
2123
+ async execute(plan, env) {
2124
+ const self = await env.host.getSelfIdentity();
2125
+ const name = self.name || self.uid || "\u6211";
2126
+ const withdrawMsg = JSON.stringify({
2127
+ display: "0",
2128
+ dt: [{ txt: { id18n: "103838", kvs: { "%NAME%": name, "%UNAME%": "" }, ot: "1", ou: { c: self.cid, u: self.uid }, v: `${name}\u64A4\u56DE\u4E86\u4E00\u6761\u6D88\u606F` } }],
2129
+ scid: self.cid,
2130
+ suid: self.uid,
2131
+ sname: name,
2132
+ type: "10",
2133
+ ver: "1.0"
2134
+ });
2135
+ const body = {
2136
+ source: plan.source,
2137
+ msgid: plan.msgid,
2138
+ dev: 5,
2139
+ msg: withdrawMsg,
2140
+ title: withdrawMsg,
2141
+ trans_id: String(Math.floor(Date.now() / 1e3)),
2142
+ sensitive_confirm: "0"
2143
+ };
2144
+ const res = await env.host.request({
2145
+ method: "POST",
2146
+ path: "/api/em/msg/executeIm/msg/makeMsgWithdraw",
2147
+ body,
2148
+ operation: "im.msg.withdraw"
2149
+ });
2150
+ const actCode = Number(res?.data?.actionMsg?.code ?? res?.code ?? -1);
2151
+ const timeOut = findWithdrawTimeOut(res);
2152
+ const interval = timeOut !== null ? formatWithdrawInterval(timeOut) : "";
2153
+ if (actCode === 1505) {
2154
+ throw imValidationError(
2155
+ "withdraw_timeout",
2156
+ `\u64A4\u9500\u8D85\u65F6${interval ? `\uFF08\u64A4\u56DE\u65F6\u9650 ${interval}\uFF09` : "\uFF08\u53D1\u51FA\u8D85\u8FC7\u7EA6 2 \u5206\u949F\uFF09"}\uFF1A\u6D88\u606F\u53D1\u9001\u5DF2\u8D85\u8FC7\u53EF\u64A4\u56DE\u65F6\u9650\uFF0C\u65E0\u6CD5\u64A4\u56DE`,
2157
+ { code: 1505, details: interval ? { withdrawInterval: interval } : void 0 }
2158
+ );
2159
+ }
2160
+ if (actCode === 1506) throw imValidationError("withdraw_not_owner", "\u6D88\u606F\u4E0D\u662F\u81EA\u5DF1\u53D1\u9001\u7684\uFF0C\u65E0\u6CD5\u64A4\u56DE", { code: 1506 });
2161
+ if (actCode === 1507) throw imValidationError("withdraw_edit_timeout", "\u7F16\u8F91\u64A4\u56DE\u8D85\u65F6", { code: 1507 });
2162
+ if (actCode !== 0) throw imValidationError("withdraw_failed", `\u64A4\u56DE\u5931\u8D25\uFF08code=${actCode}\uFF09`, { code: actCode });
2163
+ return {
2164
+ msgid: plan.msgid,
2165
+ withdrawn: true,
2166
+ ...interval ? { withdrawInterval: interval, withdrawIntervalSeconds: Number(timeOut) } : {}
2167
+ };
2168
+ }
2169
+ });
2170
+ var topSetPair = makeWritePair({
2171
+ action: "im.msg.top.set",
2172
+ async plan(args, env) {
2173
+ const groupId = str(args.groupId);
2174
+ if (!groupId || groupId === "0") throw imValidationError("id_invalid", "groupId \u5FC5\u987B\u975E 0");
2175
+ const msgid = str(args.msgid);
2176
+ if (!msgid || msgid === "0") throw imValidationError("id_invalid", "msgid \u5FC5\u987B\u975E 0");
2177
+ let type;
2178
+ if (args.cancel === true) type = 2;
2179
+ else if (args.type !== void 0) {
2180
+ type = Number(args.type);
2181
+ if (type !== 1 && type !== 2) throw imValidationError("type_invalid", "type \u5FC5\u987B\u662F 1\uFF08\u7F6E\u9876\uFF09\u6216 2\uFF08\u53D6\u6D88\u7F6E\u9876\uFF09");
2182
+ } else type = 1;
2183
+ return {
2184
+ summary: { action: type === 1 ? "\u7FA4\u6D88\u606F\u7F6E\u9876" : "\u53D6\u6D88\u7FA4\u6D88\u606F\u7F6E\u9876", groupId, msgid },
2185
+ snapshot: { groupId, msgid, type }
2186
+ };
2187
+ },
2188
+ async execute(plan, env) {
2189
+ const body = { group_id: plan.groupId, type: plan.type, msgid: plan.msgid };
2190
+ const res = await env.host.request({
2191
+ method: "POST",
2192
+ path: "/api/em/msg/executeIm/msg/setGroupTopMsg",
2193
+ body,
2194
+ operation: "im.msg.top.set"
2195
+ });
2196
+ assertImOk(res, plan.type === 1 ? "\u7F6E\u9876\u6D88\u606F" : "\u53D6\u6D88\u7F6E\u9876");
2197
+ return { groupId: plan.groupId, msgid: plan.msgid, type: plan.type };
2198
+ }
2199
+ });
2200
+ var dingSendPair = makeWritePair({
2201
+ action: "im.ding.send",
2202
+ async plan(args, env) {
2203
+ const groupId = args.groupId !== void 0 && args.groupId !== "" ? str(args.groupId) : "";
2204
+ const toUid = args.toUid !== void 0 && args.toUid !== "" ? str(args.toUid) : "";
2205
+ const convertMsgid = args.convertMsgid !== void 0 && args.convertMsgid !== "" ? str(args.convertMsgid) : "";
2206
+ if (!groupId && !toUid) throw imValidationError("target_required", "groupId\uFF08\u7FA4\u5FC5\u8FBE\uFF09\u4E0E toUid\uFF08\u5355\u804A\u5FC5\u8FBE\uFF09\u81F3\u5C11\u5176\u4E00");
2207
+ if (groupId && groupId === "0") throw imValidationError("id_invalid", "groupId \u5FC5\u987B\u975E 0");
2208
+ const txtRaw = args.txt !== void 0 && args.txt !== null ? String(args.txt) : "";
2209
+ const txt = txtRaw.trim() !== "" ? txtRaw : "";
2210
+ if (!convertMsgid && !txt) throw imValidationError("content_required", "\u666E\u901A\u5FC5\u8FBE\u9700 txt\uFF1B\u8F6C\u5FC5\u8FBE\u9700 convertMsgid");
2211
+ if (args.unreadOnly === true && !groupId) {
2212
+ throw imValidationError("unread_only_group_only", "unreadOnly \u4EC5\u652F\u6301\u7FA4\u804A\u8F6C\u5FC5\u8FBE\uFF08\u9700\u63D0\u4F9B groupId\uFF09");
2213
+ }
2214
+ if (!groupId && convertMsgid && !str(args.toCid)) {
2215
+ throw imValidationError("to_cid_required", "\u5355\u804A\u8F6C\u5FC5\u8FBE\u9700\u63D0\u4F9B toCid\uFF08\u7528\u4E8E\u6309\u6D88\u606F id \u62C9\u53D6\u6E90\u6D88\u606F\uFF09");
2216
+ }
2217
+ const summary = {
2218
+ action: convertMsgid ? "\u5DF2\u6709\u6D88\u606F\u8F6C\u5FC5\u8FBE" : "\u53D1\u9001\u5FC5\u8FBE\u6D88\u606F",
2219
+ targetType: groupId ? "\u7FA4\u804A" : "\u5355\u804A",
2220
+ ...groupId ? { groupId } : { toUid },
2221
+ ...convertMsgid ? { convertMsgid } : { textPreview: txt.length > 60 ? `${txt.slice(0, 60)}\u2026` : txt },
2222
+ sendMsg: args.sendMsg !== void 0 ? Number(args.sendMsg) : 1,
2223
+ showType: args.showType !== void 0 ? Number(args.showType) : 0
2224
+ };
2225
+ const snapshot = {
2226
+ groupId: groupId || void 0,
2227
+ toUid: toUid || void 0,
2228
+ toCid: args.toCid !== void 0 ? str(args.toCid) : void 0,
2229
+ txt: txt || void 0,
2230
+ convertMsgid: convertMsgid || void 0,
2231
+ unreadOnly: args.unreadOnly === true,
2232
+ toUids: args.toUids !== void 0 ? Array.isArray(args.toUids) ? args.toUids.map((x) => String(x)) : String(args.toUids).split(",").map((s) => s.trim()).filter(Boolean) : void 0,
2233
+ sendMsg: args.sendMsg !== void 0 ? Number(args.sendMsg) : 1,
2234
+ showType: args.showType !== void 0 ? Number(args.showType) : 0,
2235
+ removeFailed: args.removeFailed === true
2236
+ };
2237
+ if (groupId) {
2238
+ const self = await env.host.getSelfIdentity();
2239
+ const myUid = self.uid || (await env.host.getSession()).userId;
2240
+ const requested = Array.isArray(snapshot.toUids) ? [...new Set(snapshot.toUids.map((x) => String(x)))] : [];
2241
+ const groupUsers2 = [];
2242
+ let receiverSource = "\u5168\u4F53\u6210\u5458";
2243
+ if (requested.length) {
2244
+ receiverSource = "\u6307\u5B9A\u4EBA\u5458";
2245
+ const map = await env.host.resolveUsersByIds(requested);
2246
+ const failed = requested.filter((uid) => !map[uid]?.cid || map[uid].cid === "0");
2247
+ if (failed.length && snapshot.removeFailed !== true) {
2248
+ throw imValidationError(
2249
+ "members_resolve_failed",
2250
+ `\u6307\u5B9A\u63A5\u6536\u4EBA\u4FE1\u606F\u83B7\u53D6\u5931\u8D25\uFF08cid \u7F3A\u5931\u6216\u4E3A 0\uFF09\uFF1A${failed.map((uid) => map[uid]?.name || uid).join("\u3001")}\uFF1B\u786E\u8BA4\u8DF3\u8FC7\u8BF7\u4F20 removeFailed:true`,
2251
+ { details: failed }
2252
+ );
2253
+ }
2254
+ for (const uid of requested) {
2255
+ const cid = map[uid]?.cid;
2256
+ if (!cid || cid === "0" || uid === myUid) continue;
2257
+ groupUsers2.push({ cid, uid });
2258
+ }
2259
+ } else if (snapshot.unreadOnly === true) {
2260
+ receiverSource = "\u4EC5\u672A\u8BFB\u4EBA\u5458";
2261
+ const readRes = await env.host.request({
2262
+ method: "POST",
2263
+ path: "/api/em/msg/executeIm/group/syncGroupReadStatus",
2264
+ body: { trans_id: 0, group_id: groupId, msgid: convertMsgid || "0" },
2265
+ operation: "im.ding.send.unread"
2266
+ });
2267
+ const readDatas = readRes?.data?.data?.datas || [];
2268
+ const unread = readDatas.filter((d) => Number(d.status) === 0);
2269
+ const uidArr = [
2270
+ ...new Set(unread.map((d) => String(d?.user?.uid)).filter((uid) => Boolean(uid) && uid !== myUid))
2271
+ ];
2272
+ if (uidArr.length === 0) {
2273
+ throw imValidationError(
2274
+ "unread_empty",
2275
+ "\u7FA4\u5185\u6CA1\u6709\u672A\u8BFB\u4EBA\u5458\uFF08unreadOnly=true \u4E0D\u81EA\u52A8\u56DE\u9000\u5168\u5458\uFF09\uFF1A\u8BF7\u786E\u8BA4\u6539\u53D1\u5168\u4F53\u6210\u5458\u3001\u6307\u5B9A\u4EBA\u5458\uFF0C\u6216\u653E\u5F03\u53D1\u9001"
2276
+ );
2277
+ }
2278
+ const map = await env.host.resolveUsersByIds(uidArr);
2279
+ for (const uid of uidArr) {
2280
+ const cid = map[uid]?.cid;
2281
+ if (cid && cid !== "0") groupUsers2.push({ cid, uid });
2282
+ }
2283
+ } else {
2284
+ const memRes = await env.host.request({
2285
+ method: "POST",
2286
+ path: "/api/em/msg/executeIm/group/getGroupUsers",
2287
+ body: { group_id: groupId, type: 0, sync_type: 0, member_mask: 6, client_uc: "0" },
2288
+ operation: "im.ding.send.members"
2289
+ });
2290
+ const uidArr = [...new Set(extractGroupMembers(memRes?.data?.data).map((m) => String(m?.uid)).filter((uid) => uid && uid !== myUid))];
2291
+ const map = await env.host.resolveUsersByIds(uidArr);
2292
+ for (const uid of uidArr) {
2293
+ const cid = map[uid]?.cid;
2294
+ if (cid && cid !== "0") groupUsers2.push({ cid, uid });
2295
+ }
2296
+ }
2297
+ if (groupUsers2.length === 0) {
2298
+ throw imValidationError("members_empty", "\u7FA4\u5185\u6CA1\u6709\u53EF\u63A5\u6536\u5FC5\u8FBE\u6D88\u606F\u7684\u6210\u5458\uFF08\u5DF2\u6392\u9664\u672C\u4EBA\uFF1B\u6307\u5B9A/\u672A\u8BFB\u4EBA\u5458\u53EF\u80FD\u4E3A\u7A7A\uFF09");
2299
+ }
2300
+ snapshot.groupUsers = groupUsers2;
2301
+ snapshot.receiveUserIds = groupUsers2.map((u) => u.uid).join(",");
2302
+ summary.receiverSource = receiverSource;
2303
+ summary.receiverCount = groupUsers2.length;
2304
+ } else {
2305
+ summary.receiverSource = "\u5355\u804A\u5BF9\u65B9";
2306
+ summary.receiverCount = 1;
2307
+ }
2308
+ return { summary, snapshot };
2309
+ },
2310
+ async execute(plan, env) {
2311
+ const self = await env.host.getSelfIdentity();
2312
+ const session = await env.host.getSession();
2313
+ const myUid = self.uid || session.userId;
2314
+ const myCid = self.cid;
2315
+ const myName = self.name || myUid;
2316
+ let receiveUserIds = "";
2317
+ let targetType;
2318
+ let targetId = "";
2319
+ let mkind;
2320
+ let msgEntity;
2321
+ let msgTitle;
2322
+ let groupUsers2;
2323
+ let fileIds = "";
2324
+ let extraInfo = "";
2325
+ let content = "";
2326
+ if (plan.convertMsgid) {
2327
+ const sourceReq = plan.groupId ? { trans_id: 0, dev: 4, type: 0, enc_type: 0, datas: [{ group_id: plan.groupId, start: plan.convertMsgid, end: "0", max_num: 1 }] } : { trans_id: 0, dev: 4, enc_type: 0, datas: [{ from_cid: plan.toCid, from_uid: plan.toUid, start: plan.convertMsgid, end: "0", max_num: 1 }] };
2328
+ const sourcePath = plan.groupId ? "/api/em/msg/executeIm/chat/syncGroupMsg" : "/api/em/msg/executeIm/msg/syncSingleMsg";
2329
+ const srcRes = await env.host.request({ method: "POST", path: sourcePath, body: sourceReq, operation: "im.ding.send.source" });
2330
+ const srcMsg = srcRes?.data?.data?.datas?.[0]?.datas?.[0] ?? srcRes?.data?.data?.datas?.[0];
2331
+ if (!srcMsg?.msg) throw imValidationError("source_not_found", `\u672A\u627E\u5230\u6E90\u6D88\u606F ${plan.convertMsgid}`);
2332
+ let msgObj;
2333
+ try {
2334
+ msgObj = typeof srcMsg.msg === "string" ? JSON.parse(srcMsg.msg) : srcMsg.msg;
2335
+ } catch {
2336
+ throw imValidationError("source_invalid", "\u6E90\u6D88\u606F\u5185\u5BB9\u65E0\u6CD5\u89E3\u6790");
2337
+ }
2338
+ const mtype = Number(msgObj.type ?? 0);
2339
+ let tag;
2340
+ let titleDt;
2341
+ const nm = msgObj.dt?.[0]?.file?.nm || msgObj.dt?.[0]?.img?.nm || msgObj.dt?.[0]?.media?.nm || "";
2342
+ if (mtype === 4) {
2343
+ tag = "2";
2344
+ content = `[\u6587\u4EF6]${nm}`;
2345
+ mkind = 512;
2346
+ titleDt = [{ txt: { v: nm } }];
2347
+ fileIds = String(msgObj.dt?.[0]?.file?.id || "");
2348
+ } else if (mtype === 2) {
2349
+ tag = "0";
2350
+ content = "[\u56FE\u7247]";
2351
+ mkind = 64;
2352
+ titleDt = [];
2353
+ fileIds = String(msgObj.dt?.[0]?.img?.src || msgObj.dt?.[0]?.img?.id || "");
2354
+ } else if (mtype === 7) {
2355
+ tag = "1";
2356
+ content = "[\u89C6\u9891]";
2357
+ mkind = 2048;
2358
+ titleDt = [];
2359
+ fileIds = String(msgObj.dt?.[0]?.media?.src || msgObj.dt?.[0]?.media?.id || "");
2360
+ } else {
2361
+ tag = "3";
2362
+ content = msgObj.dt?.[0]?.txt?.v || "";
2363
+ mkind = 1;
2364
+ titleDt = [{ txt: { v: content } }];
2365
+ }
2366
+ msgEntity = JSON.stringify({ ...msgObj, tf: "1" });
2367
+ msgTitle = JSON.stringify({ sname: myName, suid: myUid, scid: myCid, display: "0", type: String(mtype), dt: titleDt, vv: "", des: "", tf: "1" });
2368
+ extraInfo = JSON.stringify({ msgSource: { source: { tag, msgid: String(plan.convertMsgid), flag: plan.groupId ? 1 : 0, ...plan.groupId ? { group_id: plan.groupId } : { user: { cid: plan.toCid, uid: plan.toUid } } } } });
2369
+ } else {
2370
+ content = plan.txt;
2371
+ mkind = 1;
2372
+ msgEntity = JSON.stringify({
2373
+ ver: "1.0",
2374
+ dev: 5,
2375
+ guid: "0",
2376
+ cnt: "0",
2377
+ idx: "0",
2378
+ sname: myName,
2379
+ suid: myUid,
2380
+ scid: myCid,
2381
+ display: "",
2382
+ sysId: "",
2383
+ weaOaId: "",
2384
+ bgc: "",
2385
+ type: "1",
2386
+ dt: [{ txt: { v: plan.txt, next: "0", ft: "china" } }],
2387
+ tf: "1"
2388
+ });
2389
+ msgTitle = JSON.stringify({ sname: myName, suid: myUid, scid: myCid, display: "0", type: "1", dt: [{ txt: { v: plan.txt, next: "0", ft: "china" } }], vv: "", des: "", tf: "1" });
2390
+ }
2391
+ if (plan.groupId) {
2392
+ targetType = 2;
2393
+ targetId = plan.groupId;
2394
+ groupUsers2 = Array.isArray(plan.groupUsers) ? plan.groupUsers : [];
2395
+ receiveUserIds = str(plan.receiveUserIds) || groupUsers2.map((u) => u.uid).join(",");
2396
+ if (!receiveUserIds) throw imValidationError("members_empty", "\u7FA4\u5185\u6CA1\u6709\u53EF\u63A5\u6536\u5FC5\u8FBE\u6D88\u606F\u7684\u6210\u5458");
2397
+ } else {
2398
+ targetType = 1;
2399
+ const toUid = plan.toUid;
2400
+ targetId = `${myUid}|${toUid}`;
2401
+ receiveUserIds = toUid;
2402
+ }
2403
+ const body = compact({
2404
+ content,
2405
+ receiveUserIds,
2406
+ fileIds,
2407
+ sendMsg: plan.sendMsg,
2408
+ showType: plan.showType,
2409
+ mkind,
2410
+ msgEntity,
2411
+ msgTitle,
2412
+ targetType,
2413
+ targetId,
2414
+ groupUsers: groupUsers2,
2415
+ extraInfo: extraInfo || void 0
2416
+ });
2417
+ const res = await env.host.request({
2418
+ method: "POST",
2419
+ path: "/api/em/msg/createDing",
2420
+ body,
2421
+ operation: "im.ding.send"
2422
+ });
2423
+ const code = Number(res?.code ?? -1);
2424
+ if (code !== 200 || !res?.status) {
2425
+ throw imValidationError("ding_failed", `\u5FC5\u8FBE\u53D1\u9001\u5931\u8D25\uFF1Acode=${code} msg=${res?.msg ?? ""}`, { code });
2426
+ }
2427
+ return { id: str(res?.data?.id ?? ""), msg: res?.data?.msg ?? "" };
2428
+ }
2429
+ });
2430
+ function buildMsgWriteDefinition(name, method, summary, inputProps, pair) {
2431
+ const requiredInput = Object.keys(inputProps).filter((k) => {
2432
+ const prop = inputProps[k];
2433
+ return prop?.required === true;
2434
+ });
2435
+ return [
2436
+ {
2437
+ name: `${name}.prepare`,
2438
+ resource: "msg",
2439
+ method: `${method}.prepare`,
2440
+ action: `${name}.prepare`,
2441
+ summary: `${summary}\uFF08prepare\uFF1A\u53EA\u8BFB\u6821\u9A8C + \u5DEE\u5F02\u6458\u8981 + \u7B7E\u53D1\u786E\u8BA4\uFF09`,
2442
+ capability: "msg",
2443
+ risk: "read-before-write",
2444
+ requiresConfirmation: true,
2445
+ inputSchema: schemaOf(inputProps, { required: requiredInput, description: summary }),
2446
+ handler: pair.prepare
2447
+ },
2448
+ {
2449
+ name: `${name}.apply`,
2450
+ resource: "msg",
2451
+ method: `${method}.apply`,
2452
+ action: `${name}.apply`,
2453
+ summary: `${summary}\uFF08apply\uFF1A\u9700 confirm:true + continuation\uFF09`,
2454
+ capability: "msg",
2455
+ risk: "high-risk-write",
2456
+ requiresConfirmation: true,
2457
+ inputSchema: schemaOf({
2458
+ confirm: { type: "boolean", description: "\u5FC5\u987B\u4E3A true" },
2459
+ continuation: { type: "string", minLength: 1 }
2460
+ }, { required: ["confirm", "continuation"], description: summary }),
2461
+ handler: pair.apply
2462
+ }
2463
+ ];
2464
+ }
2465
+ var msgWriteOps = [
2466
+ ...buildMsgWriteDefinition("im.msg.send.single", "msg.send.single", "\u53D1\u9001\u5355\u804A\u6D88\u606F\uFF08\u6587\u672C/\u56FE\u7247/\u6587\u4EF6\uFF09", {
2467
+ toUid: { type: "string", pattern: "^\\d+$", description: "\u63A5\u6536\u4EBA uid" },
2468
+ toCid: { type: "string", pattern: "^\\d+$", description: "\u63A5\u6536\u4EBA cid" },
2469
+ txt: { type: "string", description: "\u6587\u672C\u5185\u5BB9" },
2470
+ img: { type: "string", description: "\u672C\u5730\u56FE\u7247\u8DEF\u5F84\uFF08\u53D1\u9001\u524D\u4F1A\u4E0A\u4F20\u5230 E10 \u6587\u4EF6\u670D\u52A1\uFF09" },
2471
+ file: { type: "string", description: "\u672C\u5730\u6587\u4EF6\u8DEF\u5F84" }
2472
+ }, sendSinglePair),
2473
+ ...buildMsgWriteDefinition("im.msg.send.group", "msg.send.group", "\u53D1\u9001\u7FA4\u804A\u6D88\u606F\uFF08\u6587\u672C/\u56FE\u7247/\u6587\u4EF6\uFF09", {
2474
+ groupId: { type: "string", pattern: "^\\d+$", description: "\u7FA4 id" },
2475
+ txt: { type: "string", description: "\u6587\u672C\u5185\u5BB9" },
2476
+ img: { type: "string", description: "\u672C\u5730\u56FE\u7247\u8DEF\u5F84" },
2477
+ file: { type: "string", description: "\u672C\u5730\u6587\u4EF6\u8DEF\u5F84" }
2478
+ }, sendGroupPair),
2479
+ ...buildMsgWriteDefinition("im.msg.withdraw", "msg.withdraw", "\u64A4\u56DE\u6D88\u606F\uFF08\u5355\u804A/\u7FA4\u804A\uFF0C\u9650\u672C\u4EBA 2 \u5206\u949F\u5185\uFF09", {
2480
+ type: { type: "string", enum: ["single", "group"], description: "single \u6216 group" },
2481
+ msgid: { type: "string", pattern: "^\\d+$", description: "\u6D88\u606F id\uFF08ser_msgid\uFF09" },
2482
+ toUid: { type: "string", pattern: "^\\d+$", description: "\u5355\u804A\uFF1A\u5BF9\u65B9 uid" },
2483
+ toCid: { type: "string", pattern: "^\\d+$", description: "\u5355\u804A\uFF1A\u5BF9\u65B9 cid" },
2484
+ groupId: { type: "string", pattern: "^\\d+$", description: "\u7FA4\u804A\uFF1A\u7FA4 id" }
2485
+ }, withdrawPair),
2486
+ ...buildMsgWriteDefinition("im.msg.top.set", "msg.top.set", "\u7FA4\u6D88\u606F\u7F6E\u9876 / \u53D6\u6D88\u7F6E\u9876", {
2487
+ groupId: { type: "string", pattern: "^\\d+$", description: "\u7FA4 id" },
2488
+ msgid: { type: "string", pattern: "^\\d+$", description: "\u76EE\u6807\u6D88\u606F id" },
2489
+ type: { type: "integer", enum: [1, 2], description: "1 \u7F6E\u9876 / 2 \u53D6\u6D88" },
2490
+ cancel: { type: "boolean", description: "\u7B49\u4EF7 type=2" }
2491
+ }, topSetPair),
2492
+ ...buildMsgWriteDefinition("im.ding.send", "ding.send", "\u53D1\u9001\u5FC5\u8FBE\u6D88\u606F / \u5DF2\u6709\u6D88\u606F\u8F6C\u5FC5\u8FBE\uFF08createDing\uFF09", {
2493
+ groupId: { type: "string", pattern: "^\\d+$", description: "\u7FA4\u573A\u666F\u7FA4 id" },
2494
+ toUid: { type: "string", pattern: "^\\d+$", description: "\u5355\u804A\u573A\u666F\u5BF9\u65B9 uid" },
2495
+ toCid: { type: "string", pattern: "^\\d+$", description: "\u5355\u804A\u8F6C\u5FC5\u8FBE\u5BF9\u65B9 cid" },
2496
+ txt: { type: "string", description: "\u666E\u901A\u5FC5\u8FBE\u6587\u672C" },
2497
+ convertMsgid: { type: "string", pattern: "^\\d+$", description: "\u8F6C\u5FC5\u8FBE\u6E90\u6D88\u606F id" },
2498
+ unreadOnly: { type: "boolean", description: "\u7FA4\u8F6C\u5FC5\u8FBE\u4EC5\u53D1\u7ED9\u672A\u8BFB\u4EBA\u5458" },
2499
+ toUids: { type: "array", items: { type: "string" }, description: "\u6307\u5B9A\u63A5\u6536\u4EBA uid" },
2500
+ sendMsg: { type: "integer", enum: [0, 1], description: "\u53D1\u77ED\u4FE1\uFF08\u9ED8\u8BA4 1 \u53D1\uFF09" },
2501
+ showType: { type: "integer", enum: [0, 1], description: "0 \u5168\u4F53\u53EF\u89C1\uFF08\u9ED8\u8BA4\uFF09/1 \u4EC5\u53D1\u9001\u4EBA\u53EF\u89C1" }
2502
+ }, dingSendPair)
2503
+ ];
2504
+ var msgWriteOperations = msgWriteOps;
2505
+
2506
+ // src/shortcuts/im/operations/session.ts
2507
+ var MAX_MSG_ID2 = String((1n << 63n) - 1n);
2508
+ var SESSION_DEFAULT_PAGE_SIZE = 20;
2509
+ function sessionTypeName(type) {
2510
+ if ([1, 6, 9].includes(type)) return "\u5355\u804A";
2511
+ if ([2, 3, 7, 11].includes(type)) return "\u7FA4\u804A";
2512
+ if ([4, 10].includes(type)) return "\u7CFB\u7EDF";
2513
+ return "\u5176\u5B83";
2514
+ }
2515
+ var sessionList = {
2516
+ name: "im.session.list",
2517
+ resource: "session",
2518
+ method: "session.list",
2519
+ action: "im.session.list",
2520
+ summary: "\u62C9\u53D6\u5F53\u524D\u7528\u6237\u4F1A\u8BDD\u5217\u8868\uFF08\u5355\u804A/\u7FA4\u804A/\u7CFB\u7EDF\u6D88\u606F\uFF0C\u89E3\u6790\u540D\u79F0\u4E0E\u526F\u6807\u9898\uFF09",
2521
+ capability: "session",
2522
+ risk: READ,
2523
+ inputSchema: schemaOf({
2524
+ num: { type: "integer", minimum: 1, maximum: 50, description: "\u5355\u9875\u6761\u6570\uFF08\u9ED8\u8BA4 20\uFF09" },
2525
+ msgid: { type: "string", description: "\u951A\u70B9\u6D88\u606F id\uFF08\u9ED8\u8BA4 int64 max \u4ECE\u6700\u65B0\uFF09" },
2526
+ flag: { type: "integer", enum: [0, 1, 2], description: "0 up+down / 1 up / 2 down\uFF08\u9ED8\u8BA4 2\uFF09" },
2527
+ type: { type: "integer", description: "\u4EC5\u5C55\u793A\u8BE5 session_type" },
2528
+ around: { type: "boolean", description: "\u9644\u8FD1\u8BED\u4E49\uFF08flag=0 \u4E14 up/down \u5404\u534A\uFF09" }
2529
+ }, { description: "\u62C9\u53D6\u4F1A\u8BDD\u5217\u8868" }),
2530
+ handler: async (args, { host }) => {
2531
+ const num = Math.min(toUint(args.num, "num") ?? SESSION_DEFAULT_PAGE_SIZE, MAX_PAGE_SIZE);
2532
+ const flag = args.flag !== void 0 ? Number(args.flag) : 2;
2533
+ const around = args.around === true;
2534
+ const curAnchor = args.msgid !== void 0 && args.msgid !== "" ? String(args.msgid) : MAX_MSG_ID2;
2535
+ const isNewestAnchor = curAnchor === MAX_MSG_ID2;
2536
+ const splitUpDown = around || flag === 0 && !isNewestAnchor;
2537
+ const half = Math.floor(num / 2);
2538
+ const downSize = splitUpDown ? Math.max(half, 1) : num;
2539
+ const upSize = splitUpDown ? Math.max(num - half, 1) : num;
2540
+ const body = {
2541
+ msgid: curAnchor,
2542
+ flag,
2543
+ view: 0,
2544
+ sview: 0,
2545
+ reminder: 0,
2546
+ top: 1
2547
+ };
2548
+ if (flag !== 2) body.up = { page_size: upSize, msgid: "0" };
2549
+ if (flag !== 1) body.down = { page_size: downSize, msgid: "0" };
2550
+ const res = await host.request({
2551
+ method: "POST",
2552
+ path: "/api/em/msg/executeIm/data/getSessionContext",
2553
+ body,
2554
+ operation: "im.session.list"
2555
+ });
2556
+ assertImOk(res, "\u62C9\u53D6\u4F1A\u8BDD\u5217\u8868");
2557
+ const inner = unwrapInner(res);
2558
+ const sessions = [...inner?.down_datas || [], ...inner?.up_datas || []];
2559
+ const singleTargets = /* @__PURE__ */ new Map();
2560
+ const groupIds = /* @__PURE__ */ new Set();
2561
+ const sysGroupIds = /* @__PURE__ */ new Set();
2562
+ for (const s of sessions) {
2563
+ const type = Number(s?.session_type ?? -1);
2564
+ if ([1, 6, 9].includes(type) && s?.fuser?.uid) {
2565
+ singleTargets.set(String(s.fuser.uid), { cid: str(s.fuser.cid), uid: str(s.fuser.uid) });
2566
+ } else if ([2, 3, 7, 11].includes(type) && s?.group_id) {
2567
+ groupIds.add(String(s.group_id));
2568
+ } else if ([4, 10].includes(type) && s?.group) {
2569
+ sysGroupIds.add(Number(s.group));
2570
+ }
2571
+ }
2572
+ const [personMap, groupRes] = await Promise.all([
2573
+ host.resolveUsersByIds([...singleTargets.keys()]),
2574
+ groupIds.size ? host.request({ method: "POST", path: "/api/em/msg/executeIm/group/queryGroupInfo", body: { trans_id: 0, type: 0, mask: 0, group_id: [...groupIds], flag: 0 }, operation: "im.session.list.groups" }) : Promise.resolve(null)
2575
+ ]);
2576
+ const groupInfoMap = /* @__PURE__ */ new Map();
2577
+ if (groupRes) {
2578
+ const gi = unwrapInner(groupRes)?.datas || [];
2579
+ for (const g of gi) if (g?.name) groupInfoMap.set(str(g.group_id ?? g.id), g.name);
2580
+ }
2581
+ const sysNameMap = /* @__PURE__ */ new Map();
2582
+ if (sysGroupIds.size) {
2583
+ const sysRes = await host.request({
2584
+ method: "POST",
2585
+ path: "/api/em/msg/executeIm/system-msg/syncGroupType",
2586
+ body: { gids: [...sysGroupIds], tids: [], lang: "zh_CN", showdel: 1 },
2587
+ operation: "im.session.list.sysgroups"
2588
+ });
2589
+ const sg = unwrapInner(sysRes)?.groups || [];
2590
+ for (const g of sg) if (g?.groupName) sysNameMap.set(Number(g.groupId), g.groupName);
2591
+ }
2592
+ const rows = [];
2593
+ for (const s of sessions) {
2594
+ const type = Number(s?.session_type ?? -1);
2595
+ const typeName = sessionTypeName(type);
2596
+ let name = "";
2597
+ if ([1, 6, 9].includes(type)) {
2598
+ const target = singleTargets.get(str(s?.fuser?.uid));
2599
+ name = target ? personMap[target.uid]?.name || target.uid : str(s?.name || s?.title || "");
2600
+ } else if ([2, 3, 7, 11].includes(type)) {
2601
+ name = groupInfoMap.get(str(s?.group_id)) || str(s?.group_id);
2602
+ } else if ([4, 10].includes(type)) {
2603
+ name = sysNameMap.get(Number(s?.group)) || str(s?.group);
2604
+ } else {
2605
+ name = str(s?.name || s?.title || "");
2606
+ }
2607
+ const unread = s?.unread_count ?? s?.unread ?? 0;
2608
+ const dontDisturb = Number(s?.reminder ?? s?.reminder_type ?? 0) === 1;
2609
+ const titleRaw = s?.title;
2610
+ const titleObj = typeof titleRaw === "string" ? parseMsg(titleRaw) : titleRaw && typeof titleRaw === "object" ? titleRaw : null;
2611
+ let subtitleSender = "";
2612
+ let subtitleContent = "";
2613
+ let subtitleMedia = "";
2614
+ if (titleObj) {
2615
+ const parsed = parseContent(titleObj, { i18nMap: {}, nameMap: {} });
2616
+ const sname = str(titleObj.sname);
2617
+ if (sname) subtitleSender = sname;
2618
+ else if (titleObj.scid || titleObj.suid) {
2619
+ const hit = await host.resolveUsersByIds([str(titleObj.suid)]);
2620
+ subtitleSender = hit[str(titleObj.suid)]?.name || str(titleObj.suid);
2621
+ }
2622
+ const imgs = extractImgs(titleObj);
2623
+ const videos = extractVideos(titleObj);
2624
+ const files = extractFiles(titleObj);
2625
+ if (imgs.length) subtitleMedia = `[\u56FE\u7247]${imgs[0].name}`;
2626
+ else if (videos.length) subtitleMedia = `[\u89C6\u9891]${videos[0].name}`;
2627
+ else if (files.length) subtitleMedia = `[\u6587\u4EF6]${files[0].name}`;
2628
+ const mustFlag = Number(titleObj.tf ?? 0) & 1;
2629
+ const prefix = mustFlag ? "[\u5FC5\u8FBE]" : "";
2630
+ subtitleContent = subtitleMedia ? `${prefix}${subtitleMedia}` : `${prefix}${collapseNewlines(parsed.content)}`;
2631
+ } else {
2632
+ subtitleContent = collapseNewlines(String(titleRaw ?? ""));
2633
+ }
2634
+ const subtitle = subtitleSender ? `${subtitleSender}\uFF1A${subtitleContent}` : subtitleContent;
2635
+ rows.push({
2636
+ sessionId: str(s?.session_id ?? s?.id ?? ""),
2637
+ sessionType: type,
2638
+ sessionTypeName: typeName,
2639
+ name,
2640
+ unread: Number(unread),
2641
+ dontDisturb,
2642
+ unreadLabel: Number(unread) > 0 ? dontDisturb ? `${unread}\uFF08\u514D\u6253\u6270\uFF09` : String(unread) : "",
2643
+ time: formatFullTime(s?.update_tm ?? s?.update_time ?? s?.last_time ?? s?.create),
2644
+ subtitle,
2645
+ lastMsgid: str(s?.last_msgid ?? "")
2646
+ });
2647
+ }
2648
+ rows.sort((a, b) => BigInt(a.lastMsgid || "0") < BigInt(b.lastMsgid || "0") ? 1 : -1);
2649
+ const filterType = args.type !== void 0 ? Number(args.type) : void 0;
2650
+ const filtered = filterType !== void 0 ? rows.filter((r) => r.sessionType === filterType) : rows;
2651
+ const minLast = filtered.length ? filtered[filtered.length - 1].lastMsgid : "";
2652
+ return imSuccess("im.session.list", {
2653
+ total: filtered.length,
2654
+ sessions: filtered,
2655
+ nextMsgid: minLast && BigInt(minLast) > 0n ? minLast : void 0,
2656
+ hasMore: filtered.length > 0,
2657
+ pageSize: num
2658
+ });
2659
+ }
2660
+ };
2661
+ var sysmsgGroupSearch = {
2662
+ name: "im.sysmsg.groupSearch",
2663
+ resource: "sysmsg",
2664
+ method: "sysmsg.groupSearch",
2665
+ action: "im.sysmsg.groupSearch",
2666
+ summary: "\u6309\u540D\u79F0\u641C\u7D22\u7CFB\u7EDF\u6D88\u606F\u5206\u7EC4/\u7C7B\u578B\u914D\u7F6E\uFF08\u4F9B querySysMsgInfo \u4F7F\u7528\uFF09",
2667
+ capability: "sysmsg",
2668
+ risk: READ,
2669
+ inputSchema: schemaOf({
2670
+ name: { type: "string", minLength: 1, description: "\u5206\u7EC4/\u7C7B\u578B\u540D\u79F0\uFF08\u6A21\u7CCA\uFF09" },
2671
+ type: { type: "integer", enum: [0, 1], description: "0 \u641C group\uFF08\u9ED8\u8BA4\uFF09/1 \u641C type" }
2672
+ }, { required: ["name"], description: "\u641C\u7D22\u7CFB\u7EDF\u6D88\u606F\u5206\u7EC4\u914D\u7F6E" }),
2673
+ handler: async (args, { host }) => {
2674
+ const body = {
2675
+ data: {
2676
+ cond: { mask: 1, groupName: String(args.name) },
2677
+ lang: "zh_CN",
2678
+ page: { current: 1, pageSize: 30 },
2679
+ type: Number(args.type ?? 0),
2680
+ order: 0
2681
+ }
2682
+ };
2683
+ const res = await host.request({
2684
+ method: "POST",
2685
+ path: "/api/em/msg/executeIm/system-msg/searchSysMsgGroup",
2686
+ body,
2687
+ operation: "im.sysmsg.groupSearch"
2688
+ });
2689
+ assertImOk(res, "\u641C\u7D22\u7CFB\u7EDF\u6D88\u606F\u5206\u7EC4");
2690
+ const inner = unwrapInner(res);
2691
+ const groups = (inner?.groups || []).map((g) => ({
2692
+ groupId: g.groupId,
2693
+ groupName: g.groupName,
2694
+ typesIds: g.typesIds || [],
2695
+ i18nName: g.i18nName,
2696
+ enable: g.enable,
2697
+ state: g.state
2698
+ }));
2699
+ const types = (inner?.types || []).map((t) => ({
2700
+ typeId: t.typeId,
2701
+ typeName: t.typeName,
2702
+ i18nName: t.i18nName,
2703
+ state: t.state
2704
+ }));
2705
+ return imSuccess("im.sysmsg.groupSearch", { groups, types, total: Math.max(groups.length, types.length) });
2706
+ }
2707
+ };
2708
+ var sysmsgTypeSync = {
2709
+ name: "im.sysmsg.typeSync",
2710
+ resource: "sysmsg",
2711
+ method: "sysmsg.typeSync",
2712
+ action: "im.sysmsg.typeSync",
2713
+ summary: "\u6309 gids/tids \u62C9\u53D6\u7CFB\u7EDF\u6D88\u606F\u5206\u7EC4/\u7C7B\u578B\u914D\u7F6E",
2714
+ capability: "sysmsg",
2715
+ risk: READ,
2716
+ inputSchema: schemaOf({
2717
+ gids: { type: "array", items: { type: "integer" }, description: "\u7CFB\u7EDF\u5206\u7EC4 id\uFF08\u4E0E tids \u81F3\u5C11\u5176\u4E00\uFF09" },
2718
+ tids: { type: "array", items: { type: "integer" }, description: "\u6D88\u606F\u7C7B\u578B id" }
2719
+ }, { description: "gids / tids \u81F3\u5C11\u5176\u4E00" }),
2720
+ handler: async (args, { host }) => {
2721
+ const gids = Array.isArray(args.gids) ? args.gids.map((x) => Number(x)).filter((n) => Number.isInteger(n)) : [];
2722
+ const tids = Array.isArray(args.tids) ? args.tids.map((x) => Number(x)).filter((n) => Number.isInteger(n)) : [];
2723
+ if (!gids.length && !tids.length) throw imValidationError("target_required", "gids \u4E0E tids \u81F3\u5C11\u5176\u4E00");
2724
+ const body = { gids, tids, lang: "zh_CN", showdel: 1 };
2725
+ const res = await host.request({
2726
+ method: "POST",
2727
+ path: "/api/em/msg/executeIm/system-msg/syncGroupType",
2728
+ body,
2729
+ operation: "im.sysmsg.typeSync"
2730
+ });
2731
+ assertImOk(res, "\u540C\u6B65\u7CFB\u7EDF\u6D88\u606F\u914D\u7F6E");
2732
+ const inner = unwrapInner(res);
2733
+ const groups = (inner?.groups || []).map((g) => ({
2734
+ groupId: g.groupId,
2735
+ groupName: g.groupName,
2736
+ typesIds: g.typesIds || [],
2737
+ i18nName: g.i18nName,
2738
+ enable: g.enable,
2739
+ state: g.state,
2740
+ sunread: g.sunread
2741
+ }));
2742
+ const types = (inner?.types || []).map((t) => ({
2743
+ typeId: t.typeId,
2744
+ typeName: t.typeName,
2745
+ i18nName: t.i18nName,
2746
+ state: t.state
2747
+ }));
2748
+ return imSuccess("im.sysmsg.typeSync", { groups, types });
2749
+ }
2750
+ };
2751
+ var sysmsgQuery = {
2752
+ name: "im.sysmsg.query",
2753
+ resource: "sysmsg",
2754
+ method: "sysmsg.query",
2755
+ action: "im.sysmsg.query",
2756
+ summary: "\u62C9\u53D6\u7CFB\u7EDF\u6D88\u606F\uFF08\u6D41\u7A0B/\u4EFB\u52A1/\u516C\u6587\u7B49\uFF09\uFF0C\u652F\u6301\u9605\u8BFB\u7EF4\u5EA6/\u5904\u7406\u72B6\u6001/\u65F6\u95F4\u8303\u56F4\uFF0C\u9ED8\u8BA4\u5F53\u5929\u4E14\u6709\u754C\u533A\u95F4\u81EA\u52A8\u7FFB\u9875\u62C9\u5B8C",
2757
+ capability: "sysmsg",
2758
+ risk: READ,
2759
+ inputSchema: schemaOf({
2760
+ group: { type: "integer", minimum: 1, description: "\u7CFB\u7EDF\u5206\u7EC4 id" },
2761
+ type: { type: "integer", description: "\u6D88\u606F\u7C7B\u578B id" },
2762
+ num: { type: "integer", minimum: 1, maximum: 50, description: "\u6BCF\u9875\u6761\u6570\uFF08\u9ED8\u8BA4 50\uFF0C\u6700\u591A 50\uFF09" },
2763
+ flag: { type: "integer", enum: [0, 1, 2], description: "0 \u4E0D\u5206(\u9ED8\u8BA4)/1 \u5DF2\u8BFB/2 \u672A\u8BFB" },
2764
+ deal: { type: "integer", enum: [0, 1, 2], description: "0 \u5168\u90E8(\u9ED8\u8BA4)/1 \u672A\u5904\u7406/2 \u5DF2\u5904\u7406" },
2765
+ from: { type: "string", description: "\u8D77\u59CB\u65F6\u95F4\uFF1B\u8DE8\u5EA6 > 7 \u5929\u81EA\u52A8\u6536\u655B\u4E3A\u8BE5\u8303\u56F4\u6700\u540E 7 \u5929" },
2766
+ to: { type: "string", description: "\u7ED3\u675F\u65F6\u95F4\uFF08\u540C\u4E0A\uFF09" },
2767
+ latest: { type: "boolean", description: "\u62C9\u6700\u65B0\u4E0D\u9650\u65E5\u671F\uFF08\u65E0\u754C\u533A\u95F4\uFF0C\u53EA\u62C9\u4E00\u9875\uFF09" },
2768
+ start: { type: "string", description: "\u624B\u52A8\u8D77\u59CB\u6D88\u606F id\uFF08\u6700\u9AD8\u4F18\u5148\uFF09" },
2769
+ end: { type: "string", description: "\u624B\u52A8\u7ED3\u675F\u6D88\u606F id" }
2770
+ }, { required: ["group"], description: "\u62C9\u53D6\u7CFB\u7EDF\u6D88\u606F" }),
2771
+ handler: async (args, { host }) => {
2772
+ const group = toUint(args.group, "group");
2773
+ if (group === void 0 || group <= 0) {
2774
+ throw imValidationError("group_required", "group\uFF08\u7CFB\u7EDF\u6D88\u606F\u5206\u7EC4 id\uFF0C\u6765\u81EA sysmsg.groupSearch \u6216\u4F1A\u8BDD\u5217\u8868\uFF09\u5FC5\u586B\u4E14\u4E3A\u6B63\u6574\u6570");
2775
+ }
2776
+ const hasType = args.type !== void 0 && args.type !== null && args.type !== "";
2777
+ const msgType = { group };
2778
+ if (hasType) msgType.type = toUint(args.type, "type");
2779
+ let start = MAX_MSG_ID2;
2780
+ let end = "0";
2781
+ let scope = "today";
2782
+ let shrink = null;
2783
+ if (args.start !== void 0 && args.start !== null && args.start !== "") {
2784
+ start = String(args.start);
2785
+ end = args.end !== void 0 && args.end !== "" ? String(args.end) : "0";
2786
+ scope = "explicit-id";
2787
+ } else if (args.latest === true) {
2788
+ scope = "latest";
2789
+ } else if (args.from || args.to) {
2790
+ const clamp = clampTimeRangeTo7Days(parseTimeToSec(args.from, false), parseTimeToSec(args.to, true));
2791
+ if (clamp.toSec > 0) start = makeMinMaxIdByTm(clamp.toSec).max;
2792
+ if (clamp.fromSec > 0) end = makeMinMaxIdByTm(clamp.fromSec).min;
2793
+ shrink = clamp.shrunk ? clamp : null;
2794
+ scope = "range";
2795
+ } else {
2796
+ const range = todayRange();
2797
+ start = makeMinMaxIdByTm(range.toSec).max;
2798
+ end = makeMinMaxIdByTm(range.fromSec).min;
2799
+ }
2800
+ const num = Math.min(toUint(args.num, "num") ?? DEFAULT_PAGE_SIZE, MAX_PAGE_SIZE);
2801
+ const autoLoop = end !== "0";
2802
+ const pulled = await pullPaged({
2803
+ num,
2804
+ start,
2805
+ end,
2806
+ autoLoop,
2807
+ requestOnePage: async (pageStart, pageEnd, maxNum) => {
2808
+ const body = {
2809
+ trans_id: 0,
2810
+ dev: 4,
2811
+ enc_type: 0,
2812
+ flag: Number(args.flag ?? 0),
2813
+ deal_status: Number(args.deal ?? 0),
2814
+ datas: [{ msg_type: msgType, max_num: maxNum, start: pageStart, end: pageEnd }]
2815
+ };
2816
+ const res = await host.request({
2817
+ method: "POST",
2818
+ path: "/api/em/msg/executeIm/system-msg/querySysMsgInfo",
2819
+ body,
2820
+ operation: "im.sysmsg.query"
2821
+ });
2822
+ assertImOk(res, "\u62C9\u53D6\u7CFB\u7EDF\u6D88\u606F");
2823
+ const inner = unwrapInner(res);
2824
+ return Array.isArray(inner?.datas) ? inner.datas : [];
2825
+ }
2826
+ });
2827
+ const rawRows = pulled.rows;
2828
+ let dealMode = false;
2829
+ try {
2830
+ const cfgRes = await host.request({
2831
+ method: "POST",
2832
+ path: "/api/em/msg/executeIm/system-msg/syncGroupType",
2833
+ body: { gids: [group], tids: [], lang: "zh_CN", showdel: 1 },
2834
+ operation: "im.sysmsg.query.cfg"
2835
+ });
2836
+ const cfg = unwrapInner(cfgRes)?.groups?.[0];
2837
+ dealMode = Number(cfg?.sunread) === 1;
2838
+ } catch {
2839
+ }
2840
+ const msgRows = rawRows.map((r) => ({
2841
+ msg: r?.msg,
2842
+ ser_msgid: r?.ser_msgid,
2843
+ from_uid: r?.from_uid,
2844
+ msgtime: r?.msgtime,
2845
+ read_status: r?.read_status,
2846
+ deal_status: r?.deal_status
2847
+ }));
2848
+ const { collectI18nIds: collectI18nIds2, collectPersonIds: collectPersonIds2 } = await import("./msg-parse-4GSQ2WTO.js");
2849
+ const i18nIds = collectI18nIds2(msgRows);
2850
+ const personIds = collectPersonIds2(msgRows);
2851
+ for (const r of msgRows) if (r.from_uid) personIds.push(String(r.from_uid));
2852
+ const [i18nMap, personMap] = await Promise.all([
2853
+ host.fetchI18nLabels(i18nIds),
2854
+ host.resolveUsersByIds([...new Set(personIds)])
2855
+ ]);
2856
+ const nameMap = {};
2857
+ for (const [uid, p] of Object.entries(personMap)) nameMap[uid] = p.name;
2858
+ const authUid = await resolveAuthUid(host);
2859
+ const messages = msgRows.map((row) => {
2860
+ const msgObj = parseMsg(row.msg);
2861
+ const parsed = parseContent(msgObj, { i18nMap, nameMap });
2862
+ const sender = senderName(msgObj || {}, row.from_uid, authUid, nameMap);
2863
+ const statusLabel = dealMode ? Number(row.deal_status) === 1 ? "\u5DF2\u5904\u7406" : "\u672A\u5904\u7406" : row.read_status === true || row.read_status === 1 ? "\u5DF2\u8BFB" : "\u672A\u8BFB";
2864
+ return {
2865
+ msgid: str(row.ser_msgid),
2866
+ sender,
2867
+ time: formatFullTime(row.msgtime),
2868
+ title: parsed.title,
2869
+ content: escapePipe(collapseNewlines(parsed.content)),
2870
+ typeName: parsed.typeName,
2871
+ must: parsed.must,
2872
+ statusLabel
2873
+ };
2874
+ });
2875
+ sortMessagesNewestFirst(messages);
2876
+ return imSuccess("im.sysmsg.query", {
2877
+ group,
2878
+ type: hasType ? Number(args.type) : void 0,
2879
+ dealMode,
2880
+ total: messages.length,
2881
+ messages,
2882
+ range: { start, end, scope, autoPaged: autoLoop },
2883
+ ...paginationMeta(pulled, num),
2884
+ ...shrink ? { rangeShrink: rangeShrinkMeta(shrink) } : {}
2885
+ });
2886
+ }
2887
+ };
2888
+ var sessionOperations = [
2889
+ sessionList,
2890
+ sysmsgGroupSearch,
2891
+ sysmsgTypeSync,
2892
+ sysmsgQuery
2893
+ ];
2894
+
2895
+ // src/shortcuts/im/operations/person.ts
2896
+ var personResolve = {
2897
+ name: "im.person.resolve",
2898
+ resource: "person",
2899
+ method: "person.resolve",
2900
+ action: "im.person.resolve",
2901
+ summary: "\u6309\u59D3\u540D/\u5DE5\u53F7/\u624B\u673A/\u90AE\u7BB1\u6A21\u7CCA\u67E5\u8BE2\u5728\u804C\u5458\u5DE5\uFF0C\u8FD4\u56DE uid/cid/\u90E8\u95E8\u7B49\uFF08\u4F9B\u53D1\u6D88\u606F\u4E0E\u6210\u5458\u89E3\u6790\uFF09",
2902
+ capability: "person",
2903
+ risk: READ,
2904
+ inputSchema: schemaOf({
2905
+ name: { type: "string", minLength: 1, description: "\u59D3\u540D\uFF08\u6A21\u7CCA\uFF09/\u5DE5\u53F7/\u624B\u673A/\u90AE\u7BB1" }
2906
+ }, { required: ["name"], description: "\u4EBA\u5458\u89E3\u6790\uFF1A\u8F93\u5165\u4E00\u4E2A\u67E5\u8BE2\u5173\u952E\u5B57" }),
2907
+ handler: async (args, { host }) => {
2908
+ const name = String(args.name ?? "").trim();
2909
+ if (!name) throw imValidationError("name_required", "name \u5FC5\u586B");
2910
+ const employees = await host.searchEmployeeByName(name);
2911
+ const rows = employees.map((e) => ({
2912
+ uid: e.uid,
2913
+ name: e.name,
2914
+ department: e.department,
2915
+ departmentId: e.departmentId,
2916
+ subCompany: e.subCompany,
2917
+ position: e.position,
2918
+ jobNum: e.jobNum,
2919
+ mobile: e.mobile,
2920
+ cid: e.cid,
2921
+ ok: Boolean(e.uid && e.cid && e.uid !== "0" && e.cid !== "0")
2922
+ }));
2923
+ return imSuccess("im.person.resolve", {
2924
+ total: rows.length,
2925
+ keyword: name,
2926
+ employees: rows
2927
+ });
2928
+ }
2929
+ };
2930
+ var personResolveByIds = {
2931
+ name: "im.person.resolveByIds",
2932
+ resource: "person",
2933
+ method: "person.resolveByIds",
2934
+ action: "im.person.resolveByIds",
2935
+ summary: "\u6309 uid \u5217\u8868\u6279\u91CF\u89E3\u6790\u4EBA\u5458\u59D3\u540D/\u90E8\u95E8/\u5C97\u4F4D/cid\uFF08\u4E00\u6B21\u6700\u591A 100\uFF0C\u8D85\u51FA\u81EA\u52A8\u5206\u6279\uFF09",
2936
+ capability: "person",
2937
+ risk: READ,
2938
+ inputSchema: schemaOf({
2939
+ ids: { type: "array", items: { type: "string" }, description: "\u4EBA\u5458 uid \u5217\u8868" }
2940
+ }, { required: ["ids"], description: "\u6309 id \u6279\u91CF\u89E3\u6790\u4EBA\u5458" }),
2941
+ handler: async (args, { host }) => {
2942
+ const ids = Array.isArray(args.ids) ? args.ids.map((x) => String(x)).filter(Boolean) : [];
2943
+ if (ids.length === 0) throw imValidationError("ids_required", "ids \u4E0D\u80FD\u4E3A\u7A7A");
2944
+ const map = await host.resolveUsersByIds(ids);
2945
+ return imSuccess("im.person.resolveByIds", {
2946
+ requested: ids.length,
2947
+ resolved: Object.keys(map).length,
2948
+ employees: ids.map((uid) => map[uid]).filter(Boolean).map((u) => ({
2949
+ uid: u.uid,
2950
+ name: u.name,
2951
+ department: u.department,
2952
+ departmentId: u.departmentId,
2953
+ subCompany: u.subCompany,
2954
+ position: u.position,
2955
+ jobNum: u.jobNum,
2956
+ mobile: u.mobile,
2957
+ cid: u.cid,
2958
+ ok: Boolean(u.uid && u.cid && u.uid !== "0" && u.cid !== "0")
2959
+ }))
2960
+ });
2961
+ }
2962
+ };
2963
+ var personOperations = [
2964
+ personResolve,
2965
+ personResolveByIds
2966
+ ];
2967
+
2968
+ // src/shortcuts/im/operations/file-user.ts
2969
+ import { existsSync as existsSync2 } from "node:fs";
2970
+ import { rename, stat, writeFile } from "node:fs/promises";
2971
+ import { dirname, extname, resolve as resolve2 } from "node:path";
2972
+ var FILE_UPLOAD_ALIASES = {
2973
+ file: ["filePath"],
2974
+ shareGroup: ["shareGroups"]
2975
+ };
2976
+ var fileUpload = {
2977
+ name: "im.file.upload",
2978
+ resource: "file",
2979
+ method: "file.upload",
2980
+ action: "im.file.upload",
2981
+ summary: "\u4E0A\u4F20\u672C\u5730\u6587\u4EF6\u5230 E10 \u6587\u4EF6\u670D\u52A1\uFF08module=im\uFF09\uFF0C\u8FD4\u56DE\u6587\u4EF6 id\uFF08\u4F9B\u6D88\u606F img/file \u5F15\u7528\uFF09",
2982
+ capability: "file",
2983
+ risk: "external-artifact",
2984
+ deprecatedInputAliases: FILE_UPLOAD_ALIASES,
2985
+ inputSchema: {
2986
+ ...schemaOf({
2987
+ file: { type: "string", description: "\u672C\u5730\u6587\u4EF6\u8DEF\u5F84\uFF08\u5FC5\u586B\uFF09" },
2988
+ filePath: { type: "string", description: "\u65E7\u540D\u5B57\u6BB5\uFF0C\u7B49\u4EF7 file\uFF08\u5DF2\u5E9F\u5F03\uFF0C\u4E0E\u65B0\u540D\u540C\u65F6\u51FA\u73B0\u4E14\u4E0D\u4E00\u81F4\u4F1A\u62A5 alias_conflict\uFF09" },
2989
+ name: { type: "string", description: "\u6587\u4EF6\u540D\uFF08\u9ED8\u8BA4\u53D6 basename\uFF09" },
2990
+ shareGroup: { type: "string", description: "\u5206\u4EAB\u7FA4 id\uFF08\u53D1\u7FA4\u6D88\u606F\u7528\uFF09" },
2991
+ shareGroups: { type: "string", description: "\u65E7\u540D\u5B57\u6BB5\uFF0C\u7B49\u4EF7 shareGroup\uFF08\u5DF2\u5E9F\u5F03\uFF09" },
2992
+ shareUsers: { type: "array", items: { type: "string" }, description: "\u5206\u4EAB\u7528\u6237 uid\uFF08\u53D1\u5355\u804A\u7528\uFF09" },
2993
+ permission: { type: "string", description: "\u6587\u4EF6\u6743\u9650\uFF08\u9ED8\u8BA4 3\uFF09" }
2994
+ }, { description: "\u6587\u4EF6\u4E0A\u4F20\uFF1Afile\uFF08\u6216\u65E7\u540D filePath\uFF09\u5FC5\u586B" }),
2995
+ anyOf: [{ required: ["file"] }, { required: ["filePath"] }]
2996
+ },
2997
+ handler: async (args, { host }) => {
2998
+ const input = normalizeAliases(args, FILE_UPLOAD_ALIASES);
2999
+ const filePath = String(input.file ?? "");
3000
+ if (!filePath) throw imValidationError("file_required", "file \u5FC5\u586B");
3001
+ const abs = resolve2(filePath);
3002
+ if (!existsSync2(abs)) throw imValidationError("file_not_found", `\u6587\u4EF6\u4E0D\u5B58\u5728: ${abs}`);
3003
+ const shareUsers = Array.isArray(input.shareUsers) ? input.shareUsers.join(",") : String(input.shareUsers ?? "");
3004
+ const shareGroups = input.shareGroup;
3005
+ const fileObj = await host.uploadFile(abs, {
3006
+ name: input.name !== void 0 ? String(input.name) : void 0,
3007
+ shareGroups: shareGroups !== void 0 && shareGroups !== "" ? String(shareGroups) : void 0,
3008
+ shareUsers: shareUsers || void 0,
3009
+ permission: input.permission !== void 0 ? String(input.permission) : void 0
3010
+ });
3011
+ return imSuccess("im.file.upload", {
3012
+ fileObj,
3013
+ img: fileObjToImg(fileObj),
3014
+ file: fileObjToFile(fileObj)
3015
+ });
3016
+ }
3017
+ };
3018
+ var filePreview = {
3019
+ name: "im.file.preview",
3020
+ resource: "file",
3021
+ method: "file.preview",
3022
+ action: "im.file.preview",
3023
+ summary: "\u751F\u6210\u56FE\u7247/\u89C6\u9891\u9884\u89C8\u4E0E\u4E0B\u8F7D URL\uFF08\u9700\u767B\u5F55\u6001\u8BBF\u95EE\uFF1B\u56FE\u7247\u652F\u6301 small/large/original\uFF09",
3024
+ capability: "file",
3025
+ risk: READ,
3026
+ inputSchema: schemaOf({
3027
+ kind: { type: "string", enum: ["img", "video"], description: "img\uFF08\u9ED8\u8BA4\uFF09/ video" },
3028
+ fileId: { type: "string", minLength: 1, description: "\u6587\u4EF6 id" },
3029
+ msgid: { type: "string", pattern: "^\\d+$", description: "\u6D88\u606F id" },
3030
+ groupId: { type: "string", description: "\u7FA4\u804A\u573A\u666F\u7FA4 id" },
3031
+ toUid: { type: "string", description: "\u5355\u804A\u573A\u666F\u5BF9\u65B9 uid" },
3032
+ toCid: { type: "string", description: "\u5355\u804A\u573A\u666F\u5BF9\u65B9 cid" },
3033
+ imgFormat: { type: "string", enum: ["small", "large", "original"], description: "\u56FE\u7247\u89C4\u683C\uFF08\u9ED8\u8BA4 small\uFF09" }
3034
+ }, { required: ["fileId", "msgid"], description: "\u5A92\u4F53\u9884\u89C8 URL" }),
3035
+ handler: async (args, { host }) => {
3036
+ const kind = String(args.kind ?? "img") === "video" ? "video" : "img";
3037
+ const fileId = String(args.fileId);
3038
+ const msgid = String(args.msgid);
3039
+ const groupId = args.groupId !== void 0 && args.groupId !== "" ? String(args.groupId) : void 0;
3040
+ const user = args.toUid || args.toCid ? { cid: str(args.toCid), uid: str(args.toUid) } : void 0;
3041
+ if (!groupId && !user) {
3042
+ throw imValidationError("context_required", "groupId\uFF08\u7FA4\u804A\uFF09\u6216 toUid+toCid\uFF08\u5355\u804A\uFF09\u5FC5\u987B\u63D0\u4F9B\u5176\u4E00");
3043
+ }
3044
+ const opts = {
3045
+ fileId,
3046
+ msgid,
3047
+ kind,
3048
+ imgFormat: args.imgFormat || "small",
3049
+ ...groupId ? { groupId } : {},
3050
+ ...user ? { user } : {}
3051
+ };
3052
+ return imSuccess("im.file.preview", {
3053
+ kind,
3054
+ fileId,
3055
+ previewUrl: await host.buildPreviewUrl(opts),
3056
+ downloadUrl: await host.buildDownloadUrl(opts),
3057
+ note: "\u9884\u89C8/\u4E0B\u8F7D URL \u9700\u8981\u767B\u5F55\u6001\uFF08Cookie+eteamsid\uFF09\uFF0C\u76F4\u63A5\u5D4C\u5165 Markdown \u4F1A 401\uFF1B\u9700\u8981\u771F\u6B63\u53EF\u89C1\u8BF7\u7528 im.file.download \u843D\u5730\u5230\u672C\u5730\u3002"
3058
+ });
3059
+ }
3060
+ };
3061
+ var IMAGE_SIGNATURES = [
3062
+ { ext: ".png", test: (b) => b.length >= 4 && b.subarray(0, 4).toString("hex") === "89504e47" },
3063
+ { ext: ".jpg", test: (b) => b.length >= 3 && b.subarray(0, 3).toString("hex") === "ffd8ff" },
3064
+ { ext: ".gif", test: (b) => b.length >= 4 && b.subarray(0, 4).toString("hex") === "47494638" },
3065
+ {
3066
+ ext: ".webp",
3067
+ test: (b) => b.length >= 12 && b.subarray(0, 4).toString("ascii") === "RIFF" && b.subarray(8, 12).toString("ascii") === "WEBP"
3068
+ }
3069
+ ];
3070
+ function detectImageExt(buffer) {
3071
+ for (const signature of IMAGE_SIGNATURES) {
3072
+ if (signature.test(buffer)) return signature.ext;
3073
+ }
3074
+ return null;
3075
+ }
3076
+ var fileDownload = {
3077
+ name: "im.file.download",
3078
+ resource: "file",
3079
+ method: "file.download",
3080
+ action: "im.file.download",
3081
+ summary: "\u4E0B\u8F7D\u6D88\u606F\u91CC\u7684\u56FE\u7247/\u89C6\u9891/\u6587\u4EF6\u5230\u672C\u5730\uFF08\u9700\u767B\u5F55\u6001\uFF1B\u7236\u76EE\u5F55\u5FC5\u987B\u5B58\u5728\uFF0C\u7981\u6B62\u8986\u76D6\uFF09",
3082
+ capability: "file",
3083
+ risk: "local-file-write",
3084
+ inputSchema: schemaOf({
3085
+ fileId: { type: "string", minLength: 1, description: "\u6587\u4EF6 id\uFF08\u53D6\u6D88\u606F media[].fileId\uFF09" },
3086
+ msgid: { type: "string", pattern: "^\\d+$", description: "\u6D88\u606F id\uFF08\u53D6\u6D88\u606F media[].msgid / msgid\uFF09" },
3087
+ kind: { type: "string", enum: ["img", "video", "file"], description: "\u5A92\u4F53\u7C7B\u578B\uFF08\u9ED8\u8BA4 img\uFF1B\u6587\u4EF6\u6D88\u606F\u4F20 file\uFF09" },
3088
+ groupId: { type: "string", description: "\u7FA4\u804A\u573A\u666F\u7FA4 id\uFF08\u4E0E\u5355\u804A\u8EAB\u4EFD\u4E8C\u9009\u4E00\uFF09" },
3089
+ toUid: { type: "string", description: "\u5355\u804A\u573A\u666F\u5BF9\u65B9 uid\uFF08\u4E0E groupId \u4E8C\u9009\u4E00\uFF09" },
3090
+ toCid: { type: "string", description: "\u5355\u804A\u573A\u666F\u5BF9\u65B9 cid\uFF08\u4E0E groupId \u4E8C\u9009\u4E00\uFF09" },
3091
+ imgFormat: { type: "string", enum: ["small", "large", "original"], description: "\u56FE\u7247\u89C4\u683C\uFF08\u9ED8\u8BA4 small\uFF1B\u8981\u539F\u56FE\u4F20 original\uFF09" },
3092
+ output: { type: "string", minLength: 1, description: "\u672C\u5730\u8F93\u51FA\u6587\u4EF6\u8DEF\u5F84\uFF08\u7236\u76EE\u5F55\u5FC5\u987B\u5B58\u5728\uFF0C\u5DF2\u5B58\u5728\u5219\u62D2\u7EDD\uFF09" }
3093
+ }, { required: ["fileId", "msgid", "output"], description: "\u5A92\u4F53/\u6587\u4EF6\u843D\u5730\u5230\u672C\u5730" }),
3094
+ handler: async (args, { host }) => {
3095
+ const fileId = String(args.fileId ?? "");
3096
+ const msgid = String(args.msgid ?? "");
3097
+ const kindRaw = String(args.kind ?? "img");
3098
+ const kind = kindRaw === "video" ? "video" : "img";
3099
+ const output = String(args.output ?? "").trim();
3100
+ if (!output) throw imValidationError("output_required", "output \u5FC5\u987B\u662F\u660E\u786E\u7684\u672C\u5730\u6587\u4EF6\u8DEF\u5F84");
3101
+ const groupId = args.groupId !== void 0 && args.groupId !== "" ? String(args.groupId) : void 0;
3102
+ const user = args.toUid || args.toCid ? { cid: str(args.toCid), uid: str(args.toUid) } : void 0;
3103
+ if (!groupId && !user) {
3104
+ throw imValidationError("context_required", "groupId\uFF08\u7FA4\u804A\uFF09\u6216 toUid+toCid\uFF08\u5355\u804A\uFF09\u5FC5\u987B\u63D0\u4F9B\u5176\u4E00");
3105
+ }
3106
+ const resolved = resolve2(output);
3107
+ const parent = await stat(dirname(resolved)).catch(() => null);
3108
+ if (!parent) throw imValidationError("output_parent_missing", `\u8F93\u51FA\u76EE\u5F55\u4E0D\u5B58\u5728\uFF1A${dirname(resolved)}`);
3109
+ if (!parent.isDirectory()) throw imValidationError("output_parent_invalid", "\u8F93\u51FA\u6587\u4EF6\u7684\u7236\u8DEF\u5F84\u4E0D\u662F\u76EE\u5F55");
3110
+ if (existsSync2(resolved)) throw imValidationError("output_exists", `\u8F93\u51FA\u6587\u4EF6\u5DF2\u5B58\u5728\uFF0C\u62D2\u7EDD\u8986\u76D6\uFF1A${resolved}`);
3111
+ const url = await host.buildDownloadUrl({
3112
+ fileId,
3113
+ msgid,
3114
+ kind,
3115
+ imgFormat: args.imgFormat || "small",
3116
+ ...groupId ? { groupId } : {},
3117
+ ...user ? { user } : {}
3118
+ });
3119
+ const content = await host.requestBinary(url);
3120
+ await writeFile(resolved, content, { flag: "wx", mode: 384 });
3121
+ let finalPath = resolved;
3122
+ let renamedFrom;
3123
+ if (kind === "img" || kindRaw === "file") {
3124
+ const detected = detectImageExt(content);
3125
+ const currentExt = extname(resolved).toLowerCase();
3126
+ if (detected && detected !== currentExt) {
3127
+ const candidate = currentExt ? `${resolved.slice(0, resolved.length - currentExt.length)}${detected}` : `${resolved}${detected}`;
3128
+ if (!existsSync2(candidate)) {
3129
+ await rename(resolved, candidate);
3130
+ renamedFrom = resolved;
3131
+ finalPath = candidate;
3132
+ }
3133
+ }
3134
+ }
3135
+ return imSuccess("im.file.download", {
3136
+ fileId,
3137
+ msgid,
3138
+ kind: kindRaw,
3139
+ output: finalPath,
3140
+ size: content.length,
3141
+ ...renamedFrom ? { renamedFrom, renameNote: "\u6269\u5C55\u540D\u5DF2\u6309\u6587\u4EF6\u5934\u7EA0\u6B63\uFF08small/large \u9884\u89C8\u4E3A\u670D\u52A1\u7AEF\u8F6C\u6362\u540E\u7684\u683C\u5F0F\uFF09" } : {}
3142
+ });
3143
+ }
3144
+ };
3145
+ var userState = {
3146
+ name: "im.user.state",
3147
+ resource: "user",
3148
+ method: "user.state",
3149
+ action: "im.user.state",
3150
+ summary: "\u67E5\u8BE2\u6307\u5B9A\u4EBA\u5458\u5404\u5728\u7EBF\u8BBE\u5907\u72B6\u6001\uFF08sub_state \u5F3A\u5236 0 \u4E0D\u8BA2\u9605\uFF09",
3151
+ capability: "user",
3152
+ risk: READ,
3153
+ inputSchema: schemaOf({
3154
+ users: { type: "array", items: { type: "string" }, description: "\u4EBA\u5458 uid \u5217\u8868" },
3155
+ devType: { type: "integer", description: "\u8BBE\u5907\u7C7B\u578B\uFF08\u7F3A\u7701\u67E5\u5168\u90E8\u5728\u7EBF\u8BBE\u5907\uFF09" },
3156
+ mask: { type: "integer", description: "\u4FE1\u606F\u63A9\u7801\uFF08\u9ED8\u8BA4 7\uFF09" },
3157
+ removeFailed: { type: "boolean", description: "\u89E3\u6790\u5931\u8D25\u7684\u4EBA\u5458\u8DF3\u8FC7\uFF08\u9ED8\u8BA4 false\uFF1A\u89E3\u6790\u5931\u8D25\u4F1A\u62A5 members_resolve_failed\uFF09" }
3158
+ }, { required: ["users"], description: "\u67E5\u8BE2\u4EBA\u5458\u5728\u7EBF\u72B6\u6001" }),
3159
+ handler: async (args, { host }) => {
3160
+ const rawUids = Array.isArray(args.users) ? args.users.map((x) => String(x)) : splitIds(args.users, "users");
3161
+ const map = await host.resolveUsersByIds(rawUids);
3162
+ const members = [];
3163
+ const failed = [];
3164
+ for (const uid of rawUids) {
3165
+ const p = map[uid];
3166
+ if (!p?.cid || p.cid === "0") {
3167
+ failed.push({ uid, name: p?.name || "" });
3168
+ continue;
3169
+ }
3170
+ members.push({ cid: p.cid, uid });
3171
+ }
3172
+ if (failed.length && args.removeFailed !== true) {
3173
+ throw imValidationError("members_resolve_failed", `\u4EE5\u4E0B\u4EBA\u5458\u89E3\u6790\u5931\u8D25\uFF1A${failed.map((f) => f.name || f.uid).join("\u3001")}\uFF1B\u786E\u8BA4\u8DF3\u8FC7\u8BF7\u4F20 removeFailed:true`);
3174
+ }
3175
+ const body = compact({
3176
+ users: members,
3177
+ sub_state: 0,
3178
+ dev_type: args.devType !== void 0 ? toUint(args.devType, "devType") : void 0,
3179
+ mask: Number(args.mask ?? 7)
3180
+ });
3181
+ const res = await host.request({
3182
+ method: "POST",
3183
+ path: "/api/em/msg/executeIm/state/syncUserState",
3184
+ body,
3185
+ operation: "im.user.state"
3186
+ });
3187
+ assertImOk(res, "\u67E5\u8BE2\u4EBA\u5458\u72B6\u6001");
3188
+ const inner = unwrapInner(res);
3189
+ const devTypeNames = {
3190
+ 1: "Android",
3191
+ 2: "iPhone",
3192
+ 3: "iPad",
3193
+ 4: "API",
3194
+ 5: "PC Web",
3195
+ 6: "\u624B\u673AWeb",
3196
+ 7: "Mac",
3197
+ 8: "Linux",
3198
+ 9: "Windows",
3199
+ 10: "\u7B2C\u4E09\u65B9",
3200
+ 11: "\u5B89\u5353Pad",
3201
+ 12: "\u9E3F\u8499",
3202
+ 13: "\u9E3F\u8499Pad",
3203
+ 0: "\u65E0\u6548"
3204
+ };
3205
+ const infos = (inner?.infos || []).map((it) => {
3206
+ const uid = str(it?.user?.uid);
3207
+ const devices = (it?.dev_infos || []).map((d) => ({
3208
+ dev: Number(d.dev ?? -1),
3209
+ devName: devTypeNames[Number(d.dev)] ?? String(d.dev),
3210
+ status: Number(d.status),
3211
+ online: Number(d.status) === 1,
3212
+ loginTime: formatTime(d.logintime),
3213
+ activeTime: formatTime(d.active_time),
3214
+ imei: str(d.imei)
3215
+ }));
3216
+ return { uid, name: map[uid]?.name || uid, devices };
3217
+ });
3218
+ return imSuccess("im.user.state", { total: infos.length, infos });
3219
+ }
3220
+ };
3221
+ function formatTime(ts) {
3222
+ if (ts === void 0 || ts === null || ts === "") return "-";
3223
+ const d = new Date(Number(ts) * 1e3);
3224
+ if (Number.isNaN(d.getTime())) return "-";
3225
+ const p = (n) => String(n).padStart(2, "0");
3226
+ return `${d.getFullYear()}/${d.getMonth() + 1}/${d.getDate()} ${p(d.getHours())}:${p(d.getMinutes())}:${p(d.getSeconds())}`;
3227
+ }
3228
+ var i18nLabels = {
3229
+ name: "im.i18n.labels",
3230
+ resource: "i18n",
3231
+ method: "i18n.labels",
3232
+ action: "im.i18n.labels",
3233
+ summary: "\u6279\u91CF\u7FFB\u8BD1\u56FD\u9645\u5316\u6807\u7B7E id \u2192 \u5F53\u524D\u8BED\u8A00\u6587\u6848",
3234
+ capability: "i18n",
3235
+ risk: READ,
3236
+ inputSchema: schemaOf({
3237
+ ids: { type: "array", items: { type: "string" }, description: "\u6807\u7B7E id\uFF08\u6570\u5B57\uFF09\u5217\u8868" }
3238
+ }, { required: ["ids"], description: "i18n \u6807\u7B7E\u7FFB\u8BD1" }),
3239
+ handler: async (args, { host }) => {
3240
+ const ids = Array.isArray(args.ids) ? args.ids.map((x) => String(x)) : splitIds(args.ids, "ids");
3241
+ const labels = await host.fetchI18nLabels(ids);
3242
+ return imSuccess("im.i18n.labels", {
3243
+ total: Object.keys(labels).length,
3244
+ labels: ids.map((id) => ({ id, text: labels[id] ?? "(\u672A\u53D6\u5230\u6587\u6848)" }))
3245
+ });
3246
+ }
3247
+ };
3248
+ var fileUserOperations = [
3249
+ fileUpload,
3250
+ filePreview,
3251
+ fileDownload,
3252
+ userState,
3253
+ i18nLabels
3254
+ ];
3255
+
3256
+ // src/shortcuts/im/operations/user-remind.ts
3257
+ var SESSION_TYPE_NAME = {
3258
+ 1: "\u5355\u804A\u4F1A\u8BDD",
3259
+ 2: "\u7FA4\u804A\u4F1A\u8BDD",
3260
+ 4: "\u7CFB\u7EDF\u4F1A\u8BDD"
3261
+ };
3262
+ var REMINDER_NAME = {
3263
+ 0: "\u6D88\u606F\u63A5\u6536\u63D0\u9192",
3264
+ 1: "\u6D88\u606F\u63A5\u6536\u4F46\u4E0D\u63D0\u9192\uFF08\u514D\u6253\u6270\uFF09"
3265
+ };
3266
+ var USER_SESSION_TYPES = /* @__PURE__ */ new Set([1]);
3267
+ var GROUP_ID_SESSION_TYPES = /* @__PURE__ */ new Set([2]);
3268
+ async function resolveTargetLabel(plan, env) {
3269
+ try {
3270
+ if (GROUP_ID_SESSION_TYPES.has(plan.sessionType) && plan.groupId) {
3271
+ const res = await env.host.request({
3272
+ method: "POST",
3273
+ path: "/api/em/msg/executeIm/group/queryGroupInfo",
3274
+ body: { trans_id: 0, type: 0, mask: 0, group_id: [plan.groupId], flag: 0 },
3275
+ operation: "im.user.setRemind.plan.group"
3276
+ });
3277
+ const info = (unwrapInner(res)?.datas || [])[0];
3278
+ const name = str(info?.name);
3279
+ return name ? `\u7FA4\u300C${name}\u300D(${plan.groupId})` : `\u7FA4 ${plan.groupId}`;
3280
+ }
3281
+ if (USER_SESSION_TYPES.has(plan.sessionType) && plan.user) {
3282
+ const map = await env.host.resolveUsersByIds([plan.user.uid]);
3283
+ const name = map[plan.user.uid]?.name;
3284
+ return name ? `\u4E0E\u300C${name}\u300D\u7684\u4F1A\u8BDD(${plan.user.uid})` : `\u4E0E ${plan.user.uid} \u7684\u4F1A\u8BDD`;
3285
+ }
3286
+ if (plan.sessionType === 4 && plan.group !== void 0) {
3287
+ const res = await env.host.request({
3288
+ method: "POST",
3289
+ path: "/api/em/msg/executeIm/system-msg/syncGroupType",
3290
+ body: { gids: [plan.group], tids: [], lang: "zh_CN", showdel: 1 },
3291
+ operation: "im.user.setRemind.plan.sysgroup"
3292
+ });
3293
+ const groupName = str((unwrapInner(res)?.groups || [])[0]?.groupName);
3294
+ const base = groupName ? `\u7CFB\u7EDF\u6D88\u606F\u5206\u7EC4\u300C${groupName}\u300D(${plan.group})` : `\u7CFB\u7EDF\u6D88\u606F\u5206\u7EC4 ${plan.group}`;
3295
+ return base;
3296
+ }
3297
+ } catch {
3298
+ }
3299
+ if (plan.groupId) return `\u7FA4 ${plan.groupId}`;
3300
+ if (plan.user) return `\u4E0E ${plan.user.uid} \u7684\u4F1A\u8BDD`;
3301
+ if (plan.group !== void 0) return `\u7CFB\u7EDF\u6D88\u606F\u5206\u7EC4 ${plan.group}`;
3302
+ return "\u4F1A\u8BDD\u514D\u6253\u6270\u8BBE\u7F6E";
3303
+ }
3304
+ var userSetRemindPair = makeWritePair({
3305
+ action: "im.user.setRemind",
3306
+ async plan(args, env) {
3307
+ const sessionType = toUint(args.sessionType, "sessionType");
3308
+ if (sessionType === void 0 || SESSION_TYPE_NAME[sessionType] === void 0) {
3309
+ throw imValidationError(
3310
+ "session_type_invalid",
3311
+ "sessionType \u5FC5\u586B\u4E14\u4EC5\u652F\u6301\u4F1A\u8BDD\u7EF4\u5EA6\uFF1A1 \u5355\u804A\u4F1A\u8BDD\u30012 \u7FA4\u804A\u4F1A\u8BDD\u30014 \u7CFB\u7EDF\u4F1A\u8BDD"
3312
+ );
3313
+ }
3314
+ const reminder = toUint(args.reminder, "reminder");
3315
+ if (reminder === void 0 || REMINDER_NAME[reminder] === void 0) {
3316
+ throw imValidationError("reminder_invalid", "reminder \u5FC5\u586B\u4E14\u4EC5\u652F\u6301 0 \u6D88\u606F\u63A5\u6536\u63D0\u9192 / 1 \u6D88\u606F\u63A5\u6536\u4F46\u4E0D\u63D0\u9192\uFF08\u514D\u6253\u6270\uFF09");
3317
+ }
3318
+ const plan = { sessionType, reminder };
3319
+ if (USER_SESSION_TYPES.has(sessionType)) {
3320
+ const uid = str(args.toUid);
3321
+ const cid = str(args.toCid);
3322
+ if (!uid || !cid || uid === "0" || cid === "0") {
3323
+ throw imValidationError("target_required", `sessionType=${sessionType}\uFF08${SESSION_TYPE_NAME[sessionType]}\uFF09\u9700\u8981 toUid + toCid`);
3324
+ }
3325
+ plan.user = { cid, uid };
3326
+ } else if (GROUP_ID_SESSION_TYPES.has(sessionType)) {
3327
+ const groupId = str(args.groupId);
3328
+ if (!groupId || groupId === "0") {
3329
+ throw imValidationError("target_required", `sessionType=${sessionType}\uFF08${SESSION_TYPE_NAME[sessionType]}\uFF09\u9700\u8981 groupId`);
3330
+ }
3331
+ plan.groupId = groupId;
3332
+ } else {
3333
+ const group = toUint(args.group, "group");
3334
+ if (group === void 0 || group <= 0) {
3335
+ throw imValidationError("target_required", "sessionType=4\uFF08\u7CFB\u7EDF\u4F1A\u8BDD\uFF09\u9700\u8981 group\uFF08\u7CFB\u7EDF\u6D88\u606F\u5206\u7EC4 id\uFF09");
3336
+ }
3337
+ plan.group = group;
3338
+ }
3339
+ const target = await resolveTargetLabel(plan, env);
3340
+ return {
3341
+ summary: {
3342
+ action: "\u8BBE\u7F6E\u6D88\u606F\u514D\u6253\u6270",
3343
+ target,
3344
+ sessionType: plan.sessionType,
3345
+ sessionTypeName: SESSION_TYPE_NAME[plan.sessionType],
3346
+ reminder: plan.reminder,
3347
+ reminderName: REMINDER_NAME[plan.reminder],
3348
+ ...plan.groupId ? { groupId: plan.groupId } : {},
3349
+ ...plan.user ? { toUid: plan.user.uid, toCid: plan.user.cid } : {},
3350
+ ...plan.group !== void 0 ? { group: plan.group } : {},
3351
+ note: "\u4EC5\u4FEE\u6539\u5F53\u524D\u767B\u5F55\u4EBA\u81EA\u5DF1\u7684\u4F1A\u8BDD\u63D0\u9192\u8BBE\u7F6E\uFF1Breminder=0 \u63A5\u6536\u5E76\u63D0\u9192\uFF0C1 \u63A5\u6536\u4F46\u4E0D\u63D0\u9192\uFF08\u514D\u6253\u6270\uFF09\u3002"
3352
+ },
3353
+ snapshot: plan
3354
+ };
3355
+ },
3356
+ async execute(plan, env) {
3357
+ const self = await env.host.getSelfIdentity();
3358
+ const remind = {
3359
+ session_type: plan.sessionType,
3360
+ reminder: plan.reminder
3361
+ };
3362
+ if (plan.user) remind.user = { cid: plan.user.cid, uid: plan.user.uid };
3363
+ if (plan.groupId) remind.group_id = plan.groupId;
3364
+ if (plan.group !== void 0) remind.group = plan.group;
3365
+ const res = await env.host.request({
3366
+ method: "POST",
3367
+ path: "/api/em/msg/executeIm/user/setMsgRemind",
3368
+ body: {
3369
+ user: { cid: self.cid, uid: self.uid },
3370
+ data: { trans_id: 0, dev: 4, remind }
3371
+ },
3372
+ operation: "im.user.setRemind"
3373
+ });
3374
+ assertImOk(res, "\u8BBE\u7F6E\u6D88\u606F\u514D\u6253\u6270");
3375
+ return {
3376
+ sessionType: plan.sessionType,
3377
+ sessionTypeName: SESSION_TYPE_NAME[plan.sessionType],
3378
+ reminder: plan.reminder,
3379
+ reminderName: REMINDER_NAME[plan.reminder],
3380
+ ...plan.groupId ? { groupId: plan.groupId } : {},
3381
+ ...plan.user ? { toUid: plan.user.uid } : {},
3382
+ ...plan.group !== void 0 ? { group: plan.group } : {}
3383
+ };
3384
+ }
3385
+ });
3386
+ var prepareSchema = {
3387
+ ...schemaOf({
3388
+ sessionType: {
3389
+ type: "integer",
3390
+ enum: [1, 2, 4],
3391
+ description: "\u4F1A\u8BDD\u7C7B\u578B\uFF08\u5FC5\u586B\uFF0C\u4EC5\u4F1A\u8BDD\u7EF4\u5EA6\uFF09\uFF1A1 \u5355\u804A\u4F1A\u8BDD\uFF0C2 \u7FA4\u804A\u4F1A\u8BDD\uFF0C4 \u7CFB\u7EDF\u4F1A\u8BDD"
3392
+ },
3393
+ reminder: {
3394
+ type: "integer",
3395
+ enum: [0, 1],
3396
+ description: "\u63D0\u9192\u503C\uFF08\u5FC5\u586B\uFF09\uFF1A0 \u6D88\u606F\u63A5\u6536\u63D0\u9192\uFF0C1 \u6D88\u606F\u63A5\u6536\u4F46\u4E0D\u63D0\u9192\uFF08\u514D\u6253\u6270\uFF09"
3397
+ },
3398
+ toUid: { type: "string", pattern: "^\\d+$", description: "sessionType=1\uFF08\u5355\u804A\u4F1A\u8BDD\uFF09\u65F6\u7684\u5BF9\u65B9 uid" },
3399
+ toCid: { type: "string", pattern: "^\\d+$", description: "sessionType=1\uFF08\u5355\u804A\u4F1A\u8BDD\uFF09\u65F6\u7684\u5BF9\u65B9 cid" },
3400
+ groupId: { type: "string", pattern: "^\\d+$", description: "sessionType=2\uFF08\u7FA4\u804A\u4F1A\u8BDD\uFF09\u65F6\u7684\u7FA4 id" },
3401
+ group: { type: "integer", minimum: 1, description: "sessionType=4\uFF08\u7CFB\u7EDF\u4F1A\u8BDD\uFF09\u65F6\u7684\u7CFB\u7EDF\u6D88\u606F\u5206\u7EC4 id" }
3402
+ }, { required: ["sessionType", "reminder"], description: "\u4F1A\u8BDD\u514D\u6253\u6270\u8BBE\u7F6E\uFF08\u5355\u804A\u4F1A\u8BDD / \u7FA4\u804A\u4F1A\u8BDD / \u7CFB\u7EDF\u4F1A\u8BDD\uFF09" })
3403
+ };
3404
+ var userRemindOperations = [
3405
+ {
3406
+ name: "im.user.setRemind.prepare",
3407
+ resource: "user",
3408
+ method: "user.setRemind.prepare",
3409
+ action: "im.user.setRemind.prepare",
3410
+ summary: "\u8BBE\u7F6E\u6D88\u606F\u514D\u6253\u6270\uFF08prepare\uFF1A\u6821\u9A8C\u76EE\u6807 + \u53EA\u8BFB\u56DE\u67E5\u76EE\u6807\u540D\u79F0 + \u7B7E\u53D1\u786E\u8BA4\uFF09",
3411
+ capability: "user",
3412
+ risk: "read-before-write",
3413
+ requiresConfirmation: true,
3414
+ inputSchema: prepareSchema,
3415
+ handler: userSetRemindPair.prepare
3416
+ },
3417
+ {
3418
+ name: "im.user.setRemind.apply",
3419
+ resource: "user",
3420
+ method: "user.setRemind.apply",
3421
+ action: "im.user.setRemind.apply",
3422
+ summary: "\u8BBE\u7F6E\u6D88\u606F\u514D\u6253\u6270\uFF08apply\uFF1A\u9700 confirm:true + continuation\uFF09",
3423
+ capability: "user",
3424
+ risk: WRITE,
3425
+ requiresConfirmation: true,
3426
+ inputSchema: schemaOf({
3427
+ confirm: { type: "boolean", description: "\u5FC5\u987B\u4E3A true" },
3428
+ continuation: { type: "string", minLength: 1 }
3429
+ }, { required: ["confirm", "continuation"], description: "\u8BBE\u7F6E\u6D88\u606F\u514D\u6253\u6270\uFF08apply\uFF09" }),
3430
+ handler: userSetRemindPair.apply
3431
+ }
3432
+ ];
3433
+
3434
+ // src/shortcuts/im/operations/registry.ts
3435
+ function buildRegistry() {
3436
+ const registry = /* @__PURE__ */ new Map();
3437
+ const definitions = [
3438
+ ...personOperations,
3439
+ ...msgReadOperations,
3440
+ ...msgWriteOperations,
3441
+ ...groupReadOperations,
3442
+ ...groupWriteOperations,
3443
+ ...sessionOperations,
3444
+ ...fileUserOperations,
3445
+ ...userRemindOperations
3446
+ ];
3447
+ for (const definition of definitions) {
3448
+ if (registry.has(definition.name)) {
3449
+ throw new Error(`duplicate im operation: ${definition.name}`);
3450
+ }
3451
+ registry.set(definition.name, definition);
3452
+ }
3453
+ return registry;
3454
+ }
3455
+ var imOperationRegistry = buildRegistry();
3456
+ function imOperationDefinitions() {
3457
+ return [...imOperationRegistry.values()];
3458
+ }
3459
+ function getImOperation(operation) {
3460
+ const definition = imOperationRegistry.get(operation);
3461
+ if (!definition) {
3462
+ throw imValidationError("operation_unknown", `\u6613\u79D2\u529E\u4E0D\u652F\u6301\u64CD\u4F5C\uFF1A${operation}`);
3463
+ }
3464
+ return definition;
3465
+ }
3466
+
3467
+ export {
3468
+ asObject,
3469
+ assertNoForbiddenKeys,
3470
+ imOperationDefinitions,
3471
+ getImOperation
3472
+ };