@openclaw/qqbot 2026.7.1-beta.6 → 2026.7.2-beta.1

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 (41) hide show
  1. package/dist/api.js +8 -7
  2. package/dist/{channel-D1UztsnG.js → channel-BbwpkiY3.js} +99 -54
  3. package/dist/{channel-entry-C5YdhX3Y.js → channel-entry-Cj1lWXpt.js} +4 -4
  4. package/dist/channel-entry-api.js +1 -1
  5. package/dist/channel-plugin-api.js +1 -1
  6. package/dist/{channel.setup-2ItDYKhz.js → channel.setup-DfhritPL.js} +1 -1
  7. package/dist/{config-C1qZbh0K.js → config-CpOXnoEc.js} +2 -2
  8. package/dist/{config-schema-JZEf1dvB.js → config-schema-B5Mle_87.js} +38 -47
  9. package/dist/doctor-contract-api.js +1 -1
  10. package/dist/{gateway-pJQppxe4.js → gateway-be5-Ckdc.js} +284 -174
  11. package/dist/{group-o0GmovSf.js → group-Dbpnjalm.js} +19 -17
  12. package/dist/{handler-runtime-zQvT6SrI.js → handler-runtime-BvR-ayNW.js} +8 -12
  13. package/dist/{log-DEtcoDWe.js → log-Da4jz75I.js} +4 -8
  14. package/dist/{outbound-BIrfvvFJ.js → outbound-BLl8Tsu7.js} +8 -142
  15. package/dist/{runtime-DodcT_fQ.js → runtime-Du28LbOJ.js} +2 -2
  16. package/dist/runtime-api.js +1 -1
  17. package/dist/secret-contract-api.js +6 -22
  18. package/dist/{sender-CjDuU-uz.js → sender-0vqsivoI.js} +220 -66
  19. package/dist/setup-plugin-api.js +1 -1
  20. package/dist/state-keys-jLJ2SmJA.js +225 -0
  21. package/dist/{tools-UJJ-tLHP.js → tools-DYb23LBU.js} +48 -6
  22. package/dist/tools-api.js +1 -1
  23. package/node_modules/p-map/index.d.ts +155 -0
  24. package/node_modules/p-map/index.js +284 -0
  25. package/node_modules/p-map/license +9 -0
  26. package/node_modules/p-map/package.json +57 -0
  27. package/node_modules/p-map/readme.md +190 -0
  28. package/node_modules/parse-ms/index.d.ts +30 -0
  29. package/node_modules/parse-ms/index.js +45 -0
  30. package/node_modules/parse-ms/license +9 -0
  31. package/node_modules/parse-ms/package.json +47 -0
  32. package/node_modules/parse-ms/readme.md +46 -0
  33. package/node_modules/pretty-ms/index.d.ts +157 -0
  34. package/node_modules/pretty-ms/index.js +149 -0
  35. package/node_modules/pretty-ms/license +9 -0
  36. package/node_modules/pretty-ms/package.json +55 -0
  37. package/node_modules/pretty-ms/readme.md +179 -0
  38. package/npm-shrinkwrap.json +44 -3
  39. package/openclaw.plugin.json +61 -89
  40. package/package.json +8 -4
  41. package/dist/state-keys-CQKlAFyo.js +0 -141
@@ -0,0 +1,55 @@
1
+ {
2
+ "name": "pretty-ms",
3
+ "version": "9.3.0",
4
+ "description": "Convert milliseconds to a human readable string: `1337000000` → `15d 11h 23m 20s`",
5
+ "license": "MIT",
6
+ "repository": "sindresorhus/pretty-ms",
7
+ "funding": "https://github.com/sponsors/sindresorhus",
8
+ "author": {
9
+ "name": "Sindre Sorhus",
10
+ "email": "sindresorhus@gmail.com",
11
+ "url": "https://sindresorhus.com"
12
+ },
13
+ "type": "module",
14
+ "exports": {
15
+ "types": "./index.d.ts",
16
+ "default": "./index.js"
17
+ },
18
+ "sideEffects": false,
19
+ "engines": {
20
+ "node": ">=18"
21
+ },
22
+ "scripts": {
23
+ "test": "xo && ava && tsd"
24
+ },
25
+ "files": [
26
+ "index.js",
27
+ "index.d.ts"
28
+ ],
29
+ "keywords": [
30
+ "pretty",
31
+ "prettify",
32
+ "human",
33
+ "humanize",
34
+ "humanized",
35
+ "readable",
36
+ "time",
37
+ "ms",
38
+ "milliseconds",
39
+ "duration",
40
+ "period",
41
+ "range",
42
+ "text",
43
+ "string",
44
+ "number",
45
+ "hrtime"
46
+ ],
47
+ "dependencies": {
48
+ "parse-ms": "^4.0.0"
49
+ },
50
+ "devDependencies": {
51
+ "ava": "^6.2.0",
52
+ "tsd": "^0.31.2",
53
+ "xo": "^0.59.3"
54
+ }
55
+ }
@@ -0,0 +1,179 @@
1
+ # pretty-ms
2
+
3
+ > Convert milliseconds to a human readable string: `1337000000` → `15d 11h 23m 20s`
4
+
5
+ ## Install
6
+
7
+ ```sh
8
+ npm install pretty-ms
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```js
14
+ import prettyMilliseconds from 'pretty-ms';
15
+
16
+ prettyMilliseconds(1337000000);
17
+ //=> '15d 11h 23m 20s'
18
+
19
+ prettyMilliseconds(1337000000n);
20
+ //=> '15d 11h 23m 20s'
21
+
22
+ prettyMilliseconds(1337);
23
+ //=> '1.3s'
24
+
25
+ prettyMilliseconds(133);
26
+ //=> '133ms'
27
+
28
+ // `compact` option
29
+ prettyMilliseconds(1337, {compact: true});
30
+ //=> '1s'
31
+
32
+ // `verbose` option
33
+ prettyMilliseconds(1335669000, {verbose: true});
34
+ //=> '15 days 11 hours 1 minute 9 seconds'
35
+
36
+ // `colonNotation` option
37
+ prettyMilliseconds(95500, {colonNotation: true});
38
+ //=> '1:35.5'
39
+
40
+ // `formatSubMilliseconds` option
41
+ prettyMilliseconds(100.400080, {formatSubMilliseconds: true})
42
+ //=> '100ms 400µs 80ns'
43
+
44
+ // `subSecondsAsDecimals` option
45
+ prettyMilliseconds(900, {subSecondsAsDecimals: true});
46
+ //=> '0.9s'
47
+
48
+ // Can be useful for time durations
49
+ prettyMilliseconds(new Date(2014, 0, 1, 10, 40) - new Date(2014, 0, 1, 10, 5))
50
+ //=> '35m'
51
+ ```
52
+
53
+ ## API
54
+
55
+ ### prettyMilliseconds(milliseconds, options?)
56
+
57
+ #### milliseconds
58
+
59
+ Type: `number | bigint`
60
+
61
+ Milliseconds to humanize.
62
+
63
+ #### options
64
+
65
+ Type: `object`
66
+
67
+ ##### secondsDecimalDigits
68
+
69
+ Type: `number`\
70
+ Default: `1`
71
+
72
+ Number of digits to appear after the seconds decimal point.
73
+
74
+ ##### millisecondsDecimalDigits
75
+
76
+ Type: `number`\
77
+ Default: `0`
78
+
79
+ Number of digits to appear after the milliseconds decimal point.
80
+
81
+ Useful in combination with [`process.hrtime()`](https://nodejs.org/api/process.html#process_process_hrtime_time).
82
+
83
+ ##### keepDecimalsOnWholeSeconds
84
+
85
+ Type: `boolean`\
86
+ Default: `false`
87
+
88
+ Keep milliseconds on whole seconds: `13s` → `13.0s`.
89
+
90
+ Useful when you are showing a number of seconds spent on an operation and don't want the width of the output to change when hitting a whole number.
91
+
92
+ ##### compact
93
+
94
+ Type: `boolean`\
95
+ Default: `false`
96
+
97
+ Only show the first unit: `1h 10m` → `1h`.
98
+
99
+ Also ensures that `millisecondsDecimalDigits` and `secondsDecimalDigits` are both set to `0`.
100
+
101
+ ##### unitCount
102
+
103
+ Type: `number`\
104
+ Default: `Infinity`
105
+
106
+ Number of units to show. Setting `compact` to `true` overrides this option.
107
+
108
+ ##### verbose
109
+
110
+ Type: `boolean`\
111
+ Default: `false`
112
+
113
+ Use full-length units: `5h 1m 45s` → `5 hours 1 minute 45 seconds`
114
+
115
+ ##### separateMilliseconds
116
+
117
+ Type: `boolean`\
118
+ Default: `false`
119
+
120
+ Show milliseconds separately. This means they won't be included in the decimal part of the seconds.
121
+
122
+ ##### formatSubMilliseconds
123
+
124
+ Type: `boolean`\
125
+ Default: `false`
126
+
127
+ Show microseconds and nanoseconds.
128
+
129
+ ##### colonNotation
130
+
131
+ Type: `boolean`\
132
+ Default: `false`
133
+
134
+ Display time using colon notation: `5h 1m 45s` → `5:01:45`. Always shows time in at least minutes: `1s` → `0:01`
135
+
136
+ Useful when you want to display time without the time units, similar to a digital watch.
137
+
138
+ Setting `colonNotation` to `true` overrides the following options to `false`:
139
+ - `compact`
140
+ - `formatSubMilliseconds`
141
+ - `separateMilliseconds`
142
+ - `verbose`
143
+
144
+ ##### hideYear
145
+
146
+ Type: `boolean`\
147
+ Default: `false`
148
+
149
+ Hides the year and shows the hidden year additionally as days (365 per year): `1y 3d 5h 1m 45s` → `368d 5h 1m 45s`.
150
+
151
+ ##### hideYearAndDays
152
+
153
+ Type: `boolean`\
154
+ Default: `false`
155
+
156
+ Hides the year and days and shows the hidden values additionally as hours: `1y 3d 5h 1m 45s` → `8837h 1m 45s`.
157
+
158
+ ##### hideSeconds
159
+
160
+ Type: `boolean`\
161
+ Default: `false`
162
+
163
+ Hides the seconds: `1y 3d 5h 1m 45s` → `1y 3d 5h 1m`.
164
+
165
+ ##### subSecondsAsDecimals
166
+
167
+ Type: `boolean`\
168
+ Default: `false`
169
+
170
+ Show sub-second values as decimal seconds: `900ms` → `0.9s`.
171
+
172
+ Useful for progress indicators where you want consistent unit format to prevent flickering.
173
+
174
+ ## Related
175
+
176
+ - [pretty-ms-cli](https://github.com/sindresorhus/pretty-ms-cli) - CLI for this module
177
+ - [parse-ms](https://github.com/sindresorhus/parse-ms) - Parse milliseconds into an object
178
+ - [to-milliseconds](https://github.com/sindresorhus/to-milliseconds) - Convert an object of time properties to milliseconds
179
+ - [pretty-bytes](https://github.com/sindresorhus/pretty-bytes) - Convert bytes to a human readable string
@@ -1,21 +1,23 @@
1
1
  {
2
2
  "name": "@openclaw/qqbot",
3
- "version": "2026.7.1-beta.6",
3
+ "version": "2026.7.2-beta.1",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@openclaw/qqbot",
9
- "version": "2026.7.1-beta.6",
9
+ "version": "2026.7.2-beta.1",
10
10
  "dependencies": {
11
11
  "@tencent-connect/qqbot-connector": "1.1.0",
12
12
  "mpg123-decoder": "1.0.3",
13
+ "p-map": "7.0.5",
14
+ "pretty-ms": "9.3.0",
13
15
  "silk-wasm": "3.7.1",
14
16
  "ws": "8.21.0",
15
17
  "zod": "4.4.3"
16
18
  },
17
19
  "peerDependencies": {
18
- "openclaw": ">=2026.7.1-beta.6"
20
+ "openclaw": ">=2026.7.2-beta.1"
19
21
  },
20
22
  "peerDependenciesMeta": {
21
23
  "openclaw": {
@@ -64,6 +66,45 @@
64
66
  "url": "https://github.com/sponsors/eshaz"
65
67
  }
66
68
  },
69
+ "node_modules/p-map": {
70
+ "version": "7.0.5",
71
+ "resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.5.tgz",
72
+ "integrity": "sha512-e8vJF4XdVkzqqSHguEMz41mQO1wKwxKm5ENrUJQUu9kLDCtn83cxbyHZcszr4QC5zEA7WffRRC4gsTecC7J9oA==",
73
+ "license": "MIT",
74
+ "engines": {
75
+ "node": ">=18"
76
+ },
77
+ "funding": {
78
+ "url": "https://github.com/sponsors/sindresorhus"
79
+ }
80
+ },
81
+ "node_modules/parse-ms": {
82
+ "version": "4.0.0",
83
+ "resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-4.0.0.tgz",
84
+ "integrity": "sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==",
85
+ "license": "MIT",
86
+ "engines": {
87
+ "node": ">=18"
88
+ },
89
+ "funding": {
90
+ "url": "https://github.com/sponsors/sindresorhus"
91
+ }
92
+ },
93
+ "node_modules/pretty-ms": {
94
+ "version": "9.3.0",
95
+ "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-9.3.0.tgz",
96
+ "integrity": "sha512-gjVS5hOP+M3wMm5nmNOucbIrqudzs9v/57bWRHQWLYklXqoXKrVfYW2W9+glfGsqtPgpiz5WwyEEB+ksXIx3gQ==",
97
+ "license": "MIT",
98
+ "dependencies": {
99
+ "parse-ms": "^4.0.0"
100
+ },
101
+ "engines": {
102
+ "node": ">=18"
103
+ },
104
+ "funding": {
105
+ "url": "https://github.com/sponsors/sindresorhus"
106
+ }
107
+ },
67
108
  "node_modules/qrcode-terminal": {
68
109
  "version": "0.12.0",
69
110
  "resolved": "https://registry.npmjs.org/qrcode-terminal/-/qrcode-terminal-0.12.0.tgz",
@@ -196,29 +196,22 @@
196
196
  ]
197
197
  },
198
198
  "streaming": {
199
- "anyOf": [
200
- {
201
- "type": "boolean"
199
+ "type": "object",
200
+ "additionalProperties": false,
201
+ "properties": {
202
+ "mode": {
203
+ "type": "string",
204
+ "enum": [
205
+ "off",
206
+ "partial"
207
+ ],
208
+ "default": "partial"
202
209
  },
203
- {
204
- "type": "object",
205
- "additionalProperties": true,
206
- "properties": {
207
- "mode": {
208
- "type": "string",
209
- "enum": [
210
- "off",
211
- "partial"
212
- ],
213
- "default": "partial"
214
- },
215
- "c2cStreamApi": {
216
- "type": "boolean",
217
- "description": "Use QQ C2C official stream_messages API (single-message typing-style updates)."
218
- }
219
- }
210
+ "nativeTransport": {
211
+ "type": "boolean",
212
+ "description": "Use QQ's official C2C stream_messages API for DM replies (single-message typing-style updates)."
220
213
  }
221
- ]
214
+ }
222
215
  },
223
216
  "groups": {
224
217
  "$ref": "#/$defs/groups"
@@ -280,29 +273,22 @@
280
273
  ]
281
274
  },
282
275
  "streaming": {
283
- "anyOf": [
284
- {
285
- "type": "boolean"
286
- },
287
- {
288
- "type": "object",
289
- "additionalProperties": false,
290
- "properties": {
291
- "mode": {
292
- "type": "string",
293
- "enum": [
294
- "off",
295
- "partial"
296
- ],
297
- "default": "partial"
298
- },
299
- "c2cStreamApi": {
300
- "type": "boolean",
301
- "description": "Use QQ C2C official stream_messages API (single-message typing-style updates)."
302
- }
303
- }
276
+ "type": "object",
277
+ "additionalProperties": false,
278
+ "properties": {
279
+ "mode": {
280
+ "type": "string",
281
+ "enum": [
282
+ "off",
283
+ "partial"
284
+ ],
285
+ "default": "partial"
286
+ },
287
+ "nativeTransport": {
288
+ "type": "boolean",
289
+ "description": "Use QQ's official C2C stream_messages API for DM replies (single-message typing-style updates)."
304
290
  }
305
- ]
291
+ }
306
292
  },
307
293
  "accounts": {
308
294
  "type": "object",
@@ -503,31 +489,24 @@
503
489
  ]
504
490
  },
505
491
  "streaming": {
506
- "anyOf": [
507
- {
508
- "type": "boolean"
492
+ "type": "object",
493
+ "properties": {
494
+ "mode": {
495
+ "default": "partial",
496
+ "type": "string",
497
+ "enum": [
498
+ "off",
499
+ "partial"
500
+ ]
509
501
  },
510
- {
511
- "type": "object",
512
- "properties": {
513
- "mode": {
514
- "default": "partial",
515
- "type": "string",
516
- "enum": [
517
- "off",
518
- "partial"
519
- ]
520
- },
521
- "c2cStreamApi": {
522
- "type": "boolean"
523
- }
524
- },
525
- "required": [
526
- "mode"
527
- ],
528
- "additionalProperties": {}
502
+ "nativeTransport": {
503
+ "type": "boolean"
529
504
  }
530
- ]
505
+ },
506
+ "required": [
507
+ "mode"
508
+ ],
509
+ "additionalProperties": false
531
510
  },
532
511
  "execApprovals": {
533
512
  "type": "object",
@@ -867,31 +846,24 @@
867
846
  ]
868
847
  },
869
848
  "streaming": {
870
- "anyOf": [
871
- {
872
- "type": "boolean"
849
+ "type": "object",
850
+ "properties": {
851
+ "mode": {
852
+ "default": "partial",
853
+ "type": "string",
854
+ "enum": [
855
+ "off",
856
+ "partial"
857
+ ]
873
858
  },
874
- {
875
- "type": "object",
876
- "properties": {
877
- "mode": {
878
- "default": "partial",
879
- "type": "string",
880
- "enum": [
881
- "off",
882
- "partial"
883
- ]
884
- },
885
- "c2cStreamApi": {
886
- "type": "boolean"
887
- }
888
- },
889
- "required": [
890
- "mode"
891
- ],
892
- "additionalProperties": {}
859
+ "nativeTransport": {
860
+ "type": "boolean"
893
861
  }
894
- ]
862
+ },
863
+ "required": [
864
+ "mode"
865
+ ],
866
+ "additionalProperties": false
895
867
  },
896
868
  "execApprovals": {
897
869
  "type": "object",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openclaw/qqbot",
3
- "version": "2026.7.1-beta.6",
3
+ "version": "2026.7.2-beta.1",
4
4
  "private": false,
5
5
  "description": "OpenClaw QQ Bot channel plugin for group and direct-message workflows.",
6
6
  "repository": {
@@ -11,12 +11,14 @@
11
11
  "dependencies": {
12
12
  "@tencent-connect/qqbot-connector": "1.1.0",
13
13
  "mpg123-decoder": "1.0.3",
14
+ "p-map": "7.0.5",
15
+ "pretty-ms": "9.3.0",
14
16
  "silk-wasm": "3.7.1",
15
17
  "ws": "8.21.0",
16
18
  "zod": "4.4.3"
17
19
  },
18
20
  "peerDependencies": {
19
- "openclaw": ">=2026.7.1-beta.6"
21
+ "openclaw": ">=2026.7.2-beta.1"
20
22
  },
21
23
  "peerDependenciesMeta": {
22
24
  "openclaw": {
@@ -45,10 +47,10 @@
45
47
  "minHostVersion": ">=2026.4.10"
46
48
  },
47
49
  "compat": {
48
- "pluginApi": ">=2026.7.1-beta.6"
50
+ "pluginApi": ">=2026.7.2-beta.1"
49
51
  },
50
52
  "build": {
51
- "openclawVersion": "2026.7.1-beta.6"
53
+ "openclawVersion": "2026.7.2-beta.1"
52
54
  },
53
55
  "release": {
54
56
  "publishToClawHub": true,
@@ -69,6 +71,8 @@
69
71
  "bundledDependencies": [
70
72
  "@tencent-connect/qqbot-connector",
71
73
  "mpg123-decoder",
74
+ "p-map",
75
+ "pretty-ms",
72
76
  "silk-wasm",
73
77
  "ws",
74
78
  "zod"
@@ -1,141 +0,0 @@
1
- import crypto from "node:crypto";
2
- import { asObjectRecord } from "openclaw/plugin-sdk/runtime-doctor";
3
- //#region extensions/qqbot/src/doctor-contract.ts
4
- const RESTRICTED_GROUP_TOOLS = { deny: [
5
- "exec",
6
- "read",
7
- "write"
8
- ] };
9
- function hasLegacyGroupToolPolicy(value) {
10
- const groups = asObjectRecord(value);
11
- if (!groups) return false;
12
- return Object.values(groups).some((group) => asObjectRecord(group)?.toolPolicy !== void 0);
13
- }
14
- function hasLegacyAccountGroupToolPolicy(value) {
15
- const accounts = asObjectRecord(value);
16
- if (!accounts) return false;
17
- return Object.values(accounts).some((account) => hasLegacyGroupToolPolicy(asObjectRecord(account)?.groups));
18
- }
19
- function migrateToolPolicy(value) {
20
- if (value === "none") return { deny: ["*"] };
21
- if (value === "full") return { allow: [] };
22
- if (value === "restricted") return { ...RESTRICTED_GROUP_TOOLS };
23
- }
24
- function describeToolPolicy(value) {
25
- return typeof value === "string" ? value : String(value);
26
- }
27
- function migrateGroups(params) {
28
- let changed = false;
29
- const nextGroups = { ...params.groups };
30
- for (const [groupId, rawGroup] of Object.entries(params.groups)) {
31
- const group = asObjectRecord(rawGroup);
32
- if (!group || group.toolPolicy === void 0) continue;
33
- const { toolPolicy, ...rest } = group;
34
- const nextGroup = { ...rest };
35
- const policy = migrateToolPolicy(toolPolicy);
36
- const path = `${params.pathPrefix}.${groupId}`;
37
- if (nextGroup.tools !== void 0) params.changes.push(`Removed ${path}.toolPolicy (${path}.tools already exists).`);
38
- else if (policy) {
39
- nextGroup.tools = policy;
40
- params.changes.push(`Moved ${path}.toolPolicy=${describeToolPolicy(toolPolicy)} to ${path}.tools.`);
41
- } else params.changes.push(`Removed unsupported ${path}.toolPolicy=${describeToolPolicy(toolPolicy)}.`);
42
- nextGroups[groupId] = nextGroup;
43
- changed = true;
44
- }
45
- return {
46
- groups: nextGroups,
47
- changed
48
- };
49
- }
50
- const legacyConfigRules = [{
51
- path: [
52
- "channels",
53
- "qqbot",
54
- "groups"
55
- ],
56
- message: "channels.qqbot.groups.<id>.toolPolicy is legacy and was ignored by QQBot group tool enforcement; use channels.qqbot.groups.<id>.tools instead. Run \"openclaw doctor --fix\".",
57
- match: hasLegacyGroupToolPolicy
58
- }, {
59
- path: [
60
- "channels",
61
- "qqbot",
62
- "accounts"
63
- ],
64
- message: "channels.qqbot.accounts.<id>.groups.<groupId>.toolPolicy is legacy and was ignored by QQBot group tool enforcement; use channels.qqbot.accounts.<id>.groups.<groupId>.tools instead. Run \"openclaw doctor --fix\".",
65
- match: hasLegacyAccountGroupToolPolicy
66
- }];
67
- function normalizeCompatibilityConfig({ cfg }) {
68
- const rawEntry = asObjectRecord(cfg.channels?.qqbot);
69
- if (!rawEntry) return {
70
- config: cfg,
71
- changes: []
72
- };
73
- const changes = [];
74
- let updated = rawEntry;
75
- let changed = false;
76
- const groups = asObjectRecord(updated.groups);
77
- if (groups) {
78
- const migrated = migrateGroups({
79
- groups,
80
- pathPrefix: "channels.qqbot.groups",
81
- changes
82
- });
83
- if (migrated.changed) {
84
- updated = {
85
- ...updated,
86
- groups: migrated.groups
87
- };
88
- changed = true;
89
- }
90
- }
91
- const accounts = asObjectRecord(updated.accounts);
92
- if (accounts) {
93
- let accountsChanged = false;
94
- const nextAccounts = { ...accounts };
95
- for (const [accountId, rawAccount] of Object.entries(accounts)) {
96
- const account = asObjectRecord(rawAccount);
97
- const accountGroups = asObjectRecord(account?.groups);
98
- if (!account || !accountGroups) continue;
99
- const migrated = migrateGroups({
100
- groups: accountGroups,
101
- pathPrefix: `channels.qqbot.accounts.${accountId}.groups`,
102
- changes
103
- });
104
- if (migrated.changed) {
105
- nextAccounts[accountId] = {
106
- ...account,
107
- groups: migrated.groups
108
- };
109
- accountsChanged = true;
110
- }
111
- }
112
- if (accountsChanged) {
113
- updated = {
114
- ...updated,
115
- accounts: nextAccounts
116
- };
117
- changed = true;
118
- }
119
- }
120
- if (!changed) return {
121
- config: cfg,
122
- changes: []
123
- };
124
- return {
125
- config: {
126
- ...cfg,
127
- channels: {
128
- ...cfg.channels,
129
- qqbot: updated
130
- }
131
- },
132
- changes
133
- };
134
- }
135
- //#endregion
136
- //#region extensions/qqbot/src/engine/utils/state-keys.ts
137
- function buildQQBotStateKey(...parts) {
138
- return crypto.createHash("sha256").update(JSON.stringify(parts)).digest("hex");
139
- }
140
- //#endregion
141
- export { legacyConfigRules as n, normalizeCompatibilityConfig as r, buildQQBotStateKey as t };