@tencent-connect/openclaw-qqbot 1.7.2 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +25 -8
- package/README.zh.md +24 -8
- package/bin/qqbot-cli.js +5 -2
- package/dist/index.cjs +15549 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +890 -0
- package/index.ts +56 -19
- package/openclaw.plugin.json +19 -3
- package/package.json +14 -23
- package/preload.cjs +17 -14
- package/scripts/link-sdk-core.cjs +133 -50
- package/scripts/upgrade-via-npm.sh +42 -11
- package/scripts/upgrade-via-source.sh +4 -4
- package/skills/qqbot-channel/SKILL.md +34 -12
- package/src/adapter/contract.ts +69 -0
- package/src/adapter/gateway.ts +61 -0
- package/src/adapter/index.ts +15 -0
- package/src/adapter/lint.ts +144 -0
- package/src/adapter/media.ts +112 -0
- package/src/adapter/pairing.ts +99 -0
- package/src/adapter/resolve.ts +333 -0
- package/src/adapter/setup.ts +55 -0
- package/src/adapter/webhook.ts +248 -0
- package/src/adapter/workspace.ts +29 -0
- package/src/bot-instance.ts +60 -0
- package/src/channel.ts +202 -413
- package/src/commands/bot-approve.ts +143 -0
- package/src/commands/bot-clear-storage.ts +114 -0
- package/src/commands/bot-group-always.ts +62 -0
- package/src/commands/bot-help.ts +40 -0
- package/src/commands/bot-logs.ts +248 -0
- package/src/commands/bot-me.ts +18 -0
- package/src/commands/bot-pairing.ts +57 -0
- package/src/commands/bot-ping.ts +33 -0
- package/src/commands/bot-streaming.ts +55 -0
- package/src/commands/bot-upgrade.ts +56 -0
- package/src/commands/bot-version.ts +41 -0
- package/src/commands/config-util.ts +96 -0
- package/src/commands/index.ts +49 -0
- package/src/config.ts +46 -19
- package/src/dispatch/body-assembler.ts +356 -0
- package/src/dispatch/ctx-builder.ts +110 -0
- package/src/dispatch/dispatch.ts +352 -0
- package/src/dispatch/envelope-builder.ts +112 -0
- package/src/dispatch/index.ts +2 -0
- package/src/{approval-handler.ts → features/approval-handler.ts} +40 -94
- package/src/features/approval-utils.ts +41 -0
- package/src/features/credential-backup.ts +82 -0
- package/src/features/history-store.ts +19 -0
- package/src/features/msgid-cache.ts +55 -0
- package/src/features/onboarding.ts +38 -0
- package/src/{proactive.ts → features/proactive.ts} +68 -49
- package/src/features/ref-index-store.ts +282 -0
- package/src/{update-checker.ts → features/update-checker.ts} +15 -35
- package/src/gateway/event-handlers.ts +241 -0
- package/src/gateway/index.ts +3 -0
- package/src/gateway/lifecycle.ts +221 -0
- package/src/gateway/middleware-setup.ts +139 -0
- package/src/gateway/qqbot-gateway.ts +342 -0
- package/src/middleware/access-control.ts +130 -0
- package/src/middleware/attachment.ts +314 -0
- package/src/middleware/policy-injector.ts +66 -0
- package/src/openclaw-plugin-sdk.d.ts +81 -10
- package/src/outbound/cron-scheduler.ts +130 -0
- package/src/outbound/debounce.ts +102 -0
- package/src/outbound/deliver-pipeline.ts +235 -0
- package/src/outbound/image-size.ts +123 -0
- package/src/outbound/index.ts +3 -0
- package/src/outbound/local-file-router.ts +145 -0
- package/src/outbound/media-send.ts +377 -0
- package/src/outbound/outbound-service.ts +222 -0
- package/src/outbound/reply-limiter.ts +128 -0
- package/src/outbound/sanitize.ts +32 -0
- package/src/outbound/streaming-controller.ts +228 -0
- package/src/outbound/target.ts +63 -0
- package/src/outbound/tts-provider.ts +84 -0
- package/src/request-context.ts +9 -8
- package/src/runtime.ts +31 -6
- package/src/setup/account-key.ts +41 -0
- package/src/setup/finalize.ts +110 -0
- package/src/setup/login.ts +197 -0
- package/src/setup/surface.ts +40 -0
- package/src/tools/platform.ts +149 -0
- package/src/tools/remind.ts +2 -0
- package/src/types-augment.d.ts +54 -0
- package/src/types.ts +51 -9
- package/src/utils/mention.ts +52 -0
- package/src/utils/pkg-version.ts +84 -47
- package/src/utils/platform.ts +31 -7
- package/src/utils/plugin-logger.ts +104 -0
- package/src/utils/ssrf-guard.ts +32 -2
- package/src/utils/stt.ts +137 -0
- package/src/utils/voice-text.ts +61 -0
- package/tsconfig.json +2 -1
- package/tsup.config.ts +57 -0
- package/dist/index.d.ts +0 -18
- package/dist/index.js +0 -27
- package/dist/src/admin-resolver.d.ts +0 -33
- package/dist/src/admin-resolver.js +0 -157
- package/dist/src/api.d.ts +0 -309
- package/dist/src/api.js +0 -923
- package/dist/src/approval-handler.d.ts +0 -47
- package/dist/src/approval-handler.js +0 -372
- package/dist/src/channel.d.ts +0 -29
- package/dist/src/channel.js +0 -528
- package/dist/src/config.d.ts +0 -60
- package/dist/src/config.js +0 -288
- package/dist/src/credential-backup.d.ts +0 -31
- package/dist/src/credential-backup.js +0 -66
- package/dist/src/deliver-debounce.d.ts +0 -74
- package/dist/src/deliver-debounce.js +0 -174
- package/dist/src/gateway.d.ts +0 -18
- package/dist/src/gateway.js +0 -2025
- package/dist/src/group-history.d.ts +0 -136
- package/dist/src/group-history.js +0 -226
- package/dist/src/image-server.d.ts +0 -87
- package/dist/src/image-server.js +0 -570
- package/dist/src/inbound-attachments.d.ts +0 -60
- package/dist/src/inbound-attachments.js +0 -248
- package/dist/src/known-users.d.ts +0 -100
- package/dist/src/known-users.js +0 -263
- package/dist/src/message-gating.d.ts +0 -53
- package/dist/src/message-gating.js +0 -107
- package/dist/src/message-queue.d.ts +0 -91
- package/dist/src/message-queue.js +0 -257
- package/dist/src/onboarding.d.ts +0 -10
- package/dist/src/onboarding.js +0 -203
- package/dist/src/outbound-deliver.d.ts +0 -48
- package/dist/src/outbound-deliver.js +0 -392
- package/dist/src/outbound.d.ts +0 -220
- package/dist/src/outbound.js +0 -975
- package/dist/src/proactive.d.ts +0 -170
- package/dist/src/proactive.js +0 -399
- package/dist/src/ref-index-store.d.ts +0 -101
- package/dist/src/ref-index-store.js +0 -298
- package/dist/src/reply-dispatcher.d.ts +0 -35
- package/dist/src/reply-dispatcher.js +0 -311
- package/dist/src/request-context.d.ts +0 -25
- package/dist/src/request-context.js +0 -37
- package/dist/src/runtime.d.ts +0 -3
- package/dist/src/runtime.js +0 -13
- package/dist/src/session-store.d.ts +0 -52
- package/dist/src/session-store.js +0 -254
- package/dist/src/slash-commands.d.ts +0 -82
- package/dist/src/slash-commands.js +0 -2233
- package/dist/src/startup-greeting.d.ts +0 -30
- package/dist/src/startup-greeting.js +0 -97
- package/dist/src/streaming.d.ts +0 -247
- package/dist/src/streaming.js +0 -899
- package/dist/src/stt.d.ts +0 -21
- package/dist/src/stt.js +0 -70
- package/dist/src/tools/channel.d.ts +0 -16
- package/dist/src/tools/channel.js +0 -231
- package/dist/src/tools/remind.d.ts +0 -2
- package/dist/src/tools/remind.js +0 -255
- package/dist/src/transport/index.d.ts +0 -10
- package/dist/src/transport/index.js +0 -9
- package/dist/src/transport/webhook-transport.d.ts +0 -67
- package/dist/src/transport/webhook-transport.js +0 -245
- package/dist/src/transport/webhook-verify.d.ts +0 -48
- package/dist/src/transport/webhook-verify.js +0 -98
- package/dist/src/types.d.ts +0 -462
- package/dist/src/types.js +0 -22
- package/dist/src/typing-keepalive.d.ts +0 -27
- package/dist/src/typing-keepalive.js +0 -64
- package/dist/src/update-checker.d.ts +0 -36
- package/dist/src/update-checker.js +0 -171
- package/dist/src/utils/audio-convert.d.ts +0 -98
- package/dist/src/utils/audio-convert.js +0 -783
- package/dist/src/utils/chunked-upload.d.ts +0 -68
- package/dist/src/utils/chunked-upload.js +0 -341
- package/dist/src/utils/file-utils.d.ts +0 -61
- package/dist/src/utils/file-utils.js +0 -172
- package/dist/src/utils/image-size.d.ts +0 -51
- package/dist/src/utils/image-size.js +0 -234
- package/dist/src/utils/media-send.d.ts +0 -158
- package/dist/src/utils/media-send.js +0 -502
- package/dist/src/utils/media-tags.d.ts +0 -14
- package/dist/src/utils/media-tags.js +0 -165
- package/dist/src/utils/payload.d.ts +0 -112
- package/dist/src/utils/payload.js +0 -186
- package/dist/src/utils/pkg-version.d.ts +0 -5
- package/dist/src/utils/pkg-version.js +0 -61
- package/dist/src/utils/platform.d.ts +0 -137
- package/dist/src/utils/platform.js +0 -390
- package/dist/src/utils/ssrf-guard.d.ts +0 -25
- package/dist/src/utils/ssrf-guard.js +0 -91
- package/dist/src/utils/text-parsing.d.ts +0 -31
- package/dist/src/utils/text-parsing.js +0 -74
- package/dist/src/utils/upload-cache.d.ts +0 -34
- package/dist/src/utils/upload-cache.js +0 -93
- package/node_modules/@eshaz/web-worker/LICENSE +0 -201
- package/node_modules/@eshaz/web-worker/README.md +0 -134
- package/node_modules/@eshaz/web-worker/browser.js +0 -17
- package/node_modules/@eshaz/web-worker/cjs/browser.js +0 -16
- package/node_modules/@eshaz/web-worker/cjs/node.js +0 -219
- package/node_modules/@eshaz/web-worker/index.d.ts +0 -4
- package/node_modules/@eshaz/web-worker/node.js +0 -223
- package/node_modules/@eshaz/web-worker/package.json +0 -54
- package/node_modules/@wasm-audio-decoders/common/index.js +0 -5
- package/node_modules/@wasm-audio-decoders/common/package.json +0 -36
- package/node_modules/@wasm-audio-decoders/common/src/WASMAudioDecoderCommon.js +0 -231
- package/node_modules/@wasm-audio-decoders/common/src/WASMAudioDecoderWorker.js +0 -129
- package/node_modules/@wasm-audio-decoders/common/src/puff/README +0 -67
- package/node_modules/@wasm-audio-decoders/common/src/puff/build_puff.js +0 -31
- package/node_modules/@wasm-audio-decoders/common/src/puff/puff.c +0 -863
- package/node_modules/@wasm-audio-decoders/common/src/puff/puff.h +0 -35
- package/node_modules/@wasm-audio-decoders/common/src/utilities.js +0 -3
- package/node_modules/@wasm-audio-decoders/common/types.d.ts +0 -7
- package/node_modules/mpg123-decoder/README.md +0 -265
- package/node_modules/mpg123-decoder/dist/mpg123-decoder.min.js +0 -185
- package/node_modules/mpg123-decoder/dist/mpg123-decoder.min.js.map +0 -1
- package/node_modules/mpg123-decoder/index.js +0 -8
- package/node_modules/mpg123-decoder/package.json +0 -58
- package/node_modules/mpg123-decoder/src/EmscriptenWasm.js +0 -464
- package/node_modules/mpg123-decoder/src/MPEGDecoder.js +0 -200
- package/node_modules/mpg123-decoder/src/MPEGDecoderWebWorker.js +0 -21
- package/node_modules/mpg123-decoder/types.d.ts +0 -30
- package/node_modules/silk-wasm/LICENSE +0 -21
- package/node_modules/silk-wasm/README.md +0 -85
- package/node_modules/silk-wasm/lib/index.cjs +0 -16
- package/node_modules/silk-wasm/lib/index.d.ts +0 -70
- package/node_modules/silk-wasm/lib/index.mjs +0 -16
- package/node_modules/silk-wasm/lib/silk.wasm +0 -0
- package/node_modules/silk-wasm/lib/utils.d.ts +0 -4
- package/node_modules/silk-wasm/package.json +0 -39
- package/node_modules/simple-yenc/.github/FUNDING.yml +0 -1
- package/node_modules/simple-yenc/.prettierignore +0 -1
- package/node_modules/simple-yenc/LICENSE +0 -7
- package/node_modules/simple-yenc/README.md +0 -163
- package/node_modules/simple-yenc/dist/esm.js +0 -1
- package/node_modules/simple-yenc/dist/index.js +0 -1
- package/node_modules/simple-yenc/package.json +0 -50
- package/node_modules/simple-yenc/rollup.config.js +0 -27
- package/node_modules/simple-yenc/src/simple-yenc.js +0 -302
- package/node_modules/ws/LICENSE +0 -20
- package/node_modules/ws/README.md +0 -548
- package/node_modules/ws/browser.js +0 -8
- package/node_modules/ws/index.js +0 -13
- package/node_modules/ws/lib/buffer-util.js +0 -131
- package/node_modules/ws/lib/constants.js +0 -19
- package/node_modules/ws/lib/event-target.js +0 -292
- package/node_modules/ws/lib/extension.js +0 -203
- package/node_modules/ws/lib/limiter.js +0 -55
- package/node_modules/ws/lib/permessage-deflate.js +0 -528
- package/node_modules/ws/lib/receiver.js +0 -706
- package/node_modules/ws/lib/sender.js +0 -602
- package/node_modules/ws/lib/stream.js +0 -161
- package/node_modules/ws/lib/subprotocol.js +0 -62
- package/node_modules/ws/lib/validation.js +0 -152
- package/node_modules/ws/lib/websocket-server.js +0 -554
- package/node_modules/ws/lib/websocket.js +0 -1393
- package/node_modules/ws/package.json +0 -69
- package/node_modules/ws/wrapper.mjs +0 -8
- package/scripts/postinstall-link-sdk.js +0 -170
- package/skills/qqbot-media/SKILL.md +0 -60
- package/src/admin-resolver.ts +0 -181
- package/src/api.ts +0 -1333
- package/src/credential-backup.ts +0 -72
- package/src/deliver-debounce.ts +0 -229
- package/src/gateway.ts +0 -2272
- package/src/group-history.ts +0 -328
- package/src/image-server.ts +0 -675
- package/src/inbound-attachments.ts +0 -321
- package/src/known-users.ts +0 -353
- package/src/message-gating.ts +0 -190
- package/src/message-queue.ts +0 -354
- package/src/onboarding.ts +0 -282
- package/src/outbound-deliver.ts +0 -486
- package/src/outbound.ts +0 -1179
- package/src/ref-index-store.ts +0 -412
- package/src/reply-dispatcher.ts +0 -334
- package/src/session-store.ts +0 -303
- package/src/slash-commands.ts +0 -2431
- package/src/startup-greeting.ts +0 -120
- package/src/streaming.ts +0 -1077
- package/src/stt.ts +0 -86
- package/src/tools/channel.ts +0 -275
- package/src/transport/index.ts +0 -11
- package/src/transport/webhook-transport.ts +0 -332
- package/src/transport/webhook-verify.ts +0 -119
- package/src/typing-keepalive.ts +0 -59
- package/src/utils/audio-convert.ts +0 -887
- package/src/utils/chunked-upload.ts +0 -483
- package/src/utils/file-utils.ts +0 -193
- package/src/utils/image-size.ts +0 -266
- package/src/utils/media-send.ts +0 -636
- package/src/utils/media-tags.ts +0 -183
- package/src/utils/payload.ts +0 -265
- package/src/utils/text-parsing.ts +0 -85
- package/src/utils/upload-cache.ts +0 -128
package/index.ts
CHANGED
|
@@ -1,32 +1,69 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
/**
|
|
2
|
+
* @tencent-connect/openclaw-qqbot
|
|
3
|
+
*
|
|
4
|
+
* 独立版 QQ Bot 通道插件 — 基于 @tencent-connect/qqbot-nodejs SDK 重构。
|
|
5
|
+
*
|
|
6
|
+
* 直接依赖:
|
|
7
|
+
* - openclaw/plugin-sdk:OpenClaw 插件框架
|
|
8
|
+
* - @tencent-connect/qqbot-nodejs:QQ 开放平台 Node.js SDK
|
|
9
|
+
*/
|
|
10
|
+
import type { OpenClawPluginApi } from 'openclaw/plugin-sdk';
|
|
11
|
+
import { emptyPluginConfigSchema } from 'openclaw/plugin-sdk';
|
|
3
12
|
|
|
4
|
-
import { qqbotPlugin } from
|
|
5
|
-
import { setQQBotRuntime } from
|
|
6
|
-
import {
|
|
7
|
-
import { registerRemindTool } from
|
|
13
|
+
import { qqbotPlugin } from './src/channel.js';
|
|
14
|
+
import { setQQBotRuntime } from './src/runtime.js';
|
|
15
|
+
import { registerPlatformTool } from './src/tools/platform.js';
|
|
16
|
+
import { registerRemindTool } from './src/tools/remind.js';
|
|
17
|
+
import { verifyRuntimeContract } from './src/adapter/contract.js';
|
|
18
|
+
|
|
19
|
+
let registered = false;
|
|
8
20
|
|
|
9
21
|
const plugin = {
|
|
10
|
-
id:
|
|
11
|
-
name:
|
|
12
|
-
description:
|
|
22
|
+
id: 'openclaw-qqbot',
|
|
23
|
+
name: 'QQ Bot',
|
|
24
|
+
description: 'QQ Bot channel plugin',
|
|
13
25
|
configSchema: emptyPluginConfigSchema(),
|
|
14
26
|
register(api: OpenClawPluginApi) {
|
|
15
27
|
setQQBotRuntime(api.runtime);
|
|
28
|
+
|
|
29
|
+
if (!registered) {
|
|
30
|
+
registered = true;
|
|
31
|
+
const contract = verifyRuntimeContract(api.runtime);
|
|
32
|
+
if (!contract.ok) {
|
|
33
|
+
throw new Error(
|
|
34
|
+
`openclaw-qqbot incompatible with openclaw ${contract.version}: ` +
|
|
35
|
+
`missing required APIs: ${contract.missing.join(', ')}. ` +
|
|
36
|
+
`Please upgrade openclaw or downgrade the plugin.`,
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
16
41
|
api.registerChannel({ plugin: qqbotPlugin as any });
|
|
17
|
-
|
|
42
|
+
registerPlatformTool(api);
|
|
18
43
|
registerRemindTool(api);
|
|
19
44
|
},
|
|
20
45
|
};
|
|
21
46
|
|
|
22
47
|
export default plugin;
|
|
23
48
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
export {
|
|
27
|
-
export
|
|
28
|
-
export
|
|
29
|
-
export
|
|
30
|
-
export
|
|
31
|
-
export
|
|
32
|
-
export
|
|
49
|
+
// ── Public API exports ──
|
|
50
|
+
|
|
51
|
+
export { qqbotPlugin } from './src/channel.js';
|
|
52
|
+
export { setQQBotRuntime, getQQBotRuntime } from './src/runtime.js';
|
|
53
|
+
export { getBotForAccount, tryGetBotForAccount, buildUserAgent } from './src/bot-instance.js';
|
|
54
|
+
export { qqbotOnboardingAdapter } from './src/features/onboarding.js';
|
|
55
|
+
export { QQBotGateway } from './src/gateway/index.js';
|
|
56
|
+
export { sendText, sendMedia } from './src/outbound/outbound-service.js';
|
|
57
|
+
export { parseTarget } from './src/outbound/target.js';
|
|
58
|
+
export { dispatchToOpenClaw } from './src/dispatch/index.js';
|
|
59
|
+
export {
|
|
60
|
+
PersistedRefIndexStore,
|
|
61
|
+
getPersistedRefIndexStore,
|
|
62
|
+
flushAllRefIndexStores,
|
|
63
|
+
} from './src/features/ref-index-store.js';
|
|
64
|
+
export {
|
|
65
|
+
StreamingController,
|
|
66
|
+
shouldUseStreaming,
|
|
67
|
+
} from './src/outbound/streaming-controller.js';
|
|
68
|
+
export * from './src/types.js';
|
|
69
|
+
export * from './src/config.js';
|
package/openclaw.plugin.json
CHANGED
|
@@ -4,18 +4,34 @@
|
|
|
4
4
|
"description": "QQ Bot channel plugin with message support, cron jobs, and proactive messaging",
|
|
5
5
|
"channels": ["qqbot"],
|
|
6
6
|
"extensions": ["./preload.cjs"],
|
|
7
|
-
"skills": ["skills/qqbot-channel", "skills/qqbot-remind", "skills/qqbot-
|
|
7
|
+
"skills": ["skills/qqbot-channel", "skills/qqbot-remind", "skills/qqbot-upgrade"],
|
|
8
|
+
"contracts": {
|
|
9
|
+
"tools": ["qqbot_platform_api", "qqbot_remind"]
|
|
10
|
+
},
|
|
8
11
|
"capabilities": {
|
|
9
12
|
"proactiveMessaging": true,
|
|
10
13
|
"cronJobs": true
|
|
11
14
|
},
|
|
12
15
|
"configSchema": {
|
|
13
16
|
"type": "object",
|
|
14
|
-
"additionalProperties":
|
|
15
|
-
"properties": {
|
|
17
|
+
"additionalProperties": true,
|
|
18
|
+
"properties": {
|
|
19
|
+
"appId": { "type": "string", "description": "QQ Bot AppID" },
|
|
20
|
+
"clientSecret": { "type": "string", "description": "QQ Bot AppSecret" }
|
|
21
|
+
}
|
|
16
22
|
},
|
|
17
23
|
"channelConfigs": {
|
|
18
24
|
"qqbot": {
|
|
25
|
+
"schema": {
|
|
26
|
+
"type": "object",
|
|
27
|
+
"additionalProperties": true,
|
|
28
|
+
"properties": {
|
|
29
|
+
"appId": { "type": "string", "description": "QQ Bot AppID" },
|
|
30
|
+
"clientSecret": { "type": "string", "description": "QQ Bot AppSecret" }
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
"label": "QQ Bot",
|
|
34
|
+
"description": "QQ Bot channel configuration with message support, cron jobs, and proactive messaging.",
|
|
19
35
|
"preferOver": ["qqbot"]
|
|
20
36
|
}
|
|
21
37
|
}
|
package/package.json
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tencent-connect/openclaw-qqbot",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"description": "QQ Bot channel plugin for OpenClaw",
|
|
4
5
|
"publishConfig": {
|
|
5
6
|
"access": "public"
|
|
6
7
|
},
|
|
7
8
|
"type": "module",
|
|
8
|
-
"main": "dist/index.
|
|
9
|
+
"main": "dist/index.cjs",
|
|
9
10
|
"types": "dist/index.d.ts",
|
|
10
11
|
"bin": {
|
|
11
12
|
"openclaw-qqbot": "./bin/qqbot-cli.js",
|
|
@@ -20,6 +21,7 @@
|
|
|
20
21
|
"index.ts",
|
|
21
22
|
"preload.cjs",
|
|
22
23
|
"tsconfig.json",
|
|
24
|
+
"tsup.config.ts",
|
|
23
25
|
"openclaw.plugin.json"
|
|
24
26
|
],
|
|
25
27
|
"openclaw": {
|
|
@@ -33,38 +35,27 @@
|
|
|
33
35
|
}
|
|
34
36
|
},
|
|
35
37
|
"scripts": {
|
|
36
|
-
"build": "
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
"postinstall": "node scripts/postinstall-link-sdk.js 2>/dev/null || true"
|
|
38
|
+
"build": "tsup",
|
|
39
|
+
"dev": "tsup --watch",
|
|
40
|
+
"typecheck": "tsc --noEmit",
|
|
41
|
+
"lint:runtime": "npx tsx src/runtime-adapter/lint-runtime-access.ts"
|
|
41
42
|
},
|
|
42
43
|
"dependencies": {
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
"ws": "^8.18.0"
|
|
44
|
+
"@tencent-connect/qqbot-connector": "1.2.0",
|
|
45
|
+
"@tencent-connect/qqbot-nodejs": "^1.0.4"
|
|
46
46
|
},
|
|
47
|
-
"bundledDependencies": [
|
|
48
|
-
"mpg123-decoder",
|
|
49
|
-
"silk-wasm",
|
|
50
|
-
"ws"
|
|
51
|
-
],
|
|
52
47
|
"devDependencies": {
|
|
53
|
-
"@types/node": "^20.
|
|
54
|
-
"
|
|
48
|
+
"@types/node": "^20.19.43",
|
|
49
|
+
"tsup": "^8.5.1",
|
|
55
50
|
"typescript": "^5.9.3"
|
|
56
51
|
},
|
|
57
52
|
"peerDependencies": {
|
|
53
|
+
"@tencent-connect/qqbot-connector": "1.2.0",
|
|
58
54
|
"openclaw": "*"
|
|
59
55
|
},
|
|
60
56
|
"homepage": "https://github.com/tencent-connect/openclaw-qqbot",
|
|
61
57
|
"repository": {
|
|
62
58
|
"type": "git",
|
|
63
59
|
"url": "git+https://github.com/tencent-connect/openclaw-qqbot.git"
|
|
64
|
-
}
|
|
65
|
-
"bundleDependencies": [
|
|
66
|
-
"mpg123-decoder",
|
|
67
|
-
"silk-wasm",
|
|
68
|
-
"ws"
|
|
69
|
-
]
|
|
60
|
+
}
|
|
70
61
|
}
|
package/preload.cjs
CHANGED
|
@@ -9,25 +9,28 @@
|
|
|
9
9
|
*/
|
|
10
10
|
"use strict";
|
|
11
11
|
|
|
12
|
+
const path = require("node:path");
|
|
13
|
+
const fs = require("node:fs");
|
|
12
14
|
const { ensurePluginSdkSymlink } = require("./scripts/link-sdk-core.cjs");
|
|
13
15
|
|
|
14
|
-
// 1) 同步创建 symlink
|
|
16
|
+
// 1) 同步创建 symlink(确保 openclaw/plugin-sdk 可解析)
|
|
15
17
|
ensurePluginSdkSymlink(__dirname, "[preload]");
|
|
16
18
|
|
|
17
|
-
// 2)
|
|
18
|
-
|
|
19
|
-
const
|
|
19
|
+
// 2) 加载编译产物(向后兼容:优先 .cjs,fallback .js)
|
|
20
|
+
const cjsPath = path.join(__dirname, "dist", "index.cjs");
|
|
21
|
+
const jsPath = path.join(__dirname, "dist", "index.js");
|
|
20
22
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
23
|
+
if (fs.existsSync(cjsPath)) {
|
|
24
|
+
module.exports = require(cjsPath);
|
|
25
|
+
} else {
|
|
26
|
+
// 兼容旧版 tsc 编译产物(ESM .js),需展平 default export
|
|
27
|
+
const _mod = require(jsPath);
|
|
28
|
+
const _default = _mod.default;
|
|
29
|
+
const merged = Object.assign({}, _mod);
|
|
30
|
+
if (_default && typeof _default === "object") {
|
|
31
|
+
for (const key of Object.keys(_default)) {
|
|
32
|
+
if (!(key in merged)) merged[key] = _default[key];
|
|
29
33
|
}
|
|
30
34
|
}
|
|
35
|
+
module.exports = merged;
|
|
31
36
|
}
|
|
32
|
-
|
|
33
|
-
module.exports = merged;
|
|
@@ -3,12 +3,14 @@
|
|
|
3
3
|
*
|
|
4
4
|
* 被 preload.cjs 和 postinstall-link-sdk.js 共同使用,避免代码重复。
|
|
5
5
|
* 必须是 CJS 格式,因为 preload.cjs 需要同步 require()。
|
|
6
|
+
*
|
|
7
|
+
* 注意:本模块不使用 child_process,避免被 openclaw 安全检查拦截。
|
|
6
8
|
*/
|
|
7
9
|
"use strict";
|
|
8
10
|
|
|
9
11
|
const path = require("node:path");
|
|
10
12
|
const fs = require("node:fs");
|
|
11
|
-
const
|
|
13
|
+
const os = require("node:os");
|
|
12
14
|
|
|
13
15
|
const CLI_NAMES = ["openclaw", "clawdbot", "moltbot"];
|
|
14
16
|
|
|
@@ -27,6 +29,104 @@ function compareVersionGte(version, target) {
|
|
|
27
29
|
return true;
|
|
28
30
|
}
|
|
29
31
|
|
|
32
|
+
/**
|
|
33
|
+
* 获取全局 node_modules 候选目录列表(按优先级排序)。
|
|
34
|
+
* 不依赖 npm/child_process,通过常用路径推导。
|
|
35
|
+
*/
|
|
36
|
+
function getGlobalNodeModulesDirs() {
|
|
37
|
+
const dirs = [];
|
|
38
|
+
const npmPrefix = process.env.npm_config_prefix || process.env.PREFIX;
|
|
39
|
+
if (npmPrefix) {
|
|
40
|
+
// macOS: prefix/lib/node_modules; Windows: prefix/node_modules
|
|
41
|
+
dirs.push(path.join(npmPrefix, "lib", "node_modules"));
|
|
42
|
+
dirs.push(path.join(npmPrefix, "node_modules"));
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// nvm / fnm / volta 等版本管理器
|
|
46
|
+
// process.execPath = .../versions/node/vX.Y.Z/bin/node
|
|
47
|
+
const execBase = path.dirname(path.dirname(process.execPath));
|
|
48
|
+
dirs.push(path.join(execBase, "lib", "node_modules"));
|
|
49
|
+
dirs.push(path.join(execBase, "node_modules"));
|
|
50
|
+
|
|
51
|
+
// Homebrew (macOS Intel)
|
|
52
|
+
dirs.push("/usr/local/lib/node_modules");
|
|
53
|
+
// Homebrew (macOS Apple Silicon)
|
|
54
|
+
dirs.push("/opt/homebrew/lib/node_modules");
|
|
55
|
+
// Linux / macOS 标准路径
|
|
56
|
+
dirs.push("/usr/lib/node_modules");
|
|
57
|
+
// pnpm global (XDG)
|
|
58
|
+
const xdgData = process.env.XDG_DATA_HOME || path.join(os.homedir(), ".local", "share");
|
|
59
|
+
dirs.push(path.join(xdgData, "pnpm", "global", "5", "node_modules"));
|
|
60
|
+
dirs.push(path.join(xdgData, "npm", "lib", "node_modules"));
|
|
61
|
+
|
|
62
|
+
return dirs;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* 在全局 node_modules 目录中查找指定包的 package.json。
|
|
67
|
+
*/
|
|
68
|
+
function findPackageInGlobalDirs(packageName) {
|
|
69
|
+
for (const dir of getGlobalNodeModulesDirs()) {
|
|
70
|
+
const pkgPath = path.join(dir, packageName, "package.json");
|
|
71
|
+
try {
|
|
72
|
+
if (fs.existsSync(pkgPath)) return pkgPath;
|
|
73
|
+
} catch {}
|
|
74
|
+
}
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* 在 $PATH 中查找 CLI 可执行文件。
|
|
80
|
+
*/
|
|
81
|
+
function findCliInPath(cliName) {
|
|
82
|
+
const pathEnv = process.env.PATH || "";
|
|
83
|
+
const ext = process.platform === "win32" ? ".cmd" : "";
|
|
84
|
+
const dirs = pathEnv.split(path.delimiter);
|
|
85
|
+
|
|
86
|
+
for (const dir of dirs) {
|
|
87
|
+
const binPath = path.join(dir, cliName + ext);
|
|
88
|
+
try {
|
|
89
|
+
if (fs.existsSync(binPath)) return fs.realpathSync(binPath);
|
|
90
|
+
} catch {}
|
|
91
|
+
}
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* 从 CLI 二进制路径反查全局 node_modules 中的 package.json。
|
|
97
|
+
*/
|
|
98
|
+
function resolveGlobalRootFromBin(binPath, cliName) {
|
|
99
|
+
// 方式 A: bin -> ../lib/node_modules/<cli>/package.json
|
|
100
|
+
const binDir = path.dirname(binPath);
|
|
101
|
+
const c1 = path.resolve(binDir, "..", "lib", "node_modules", cliName, "package.json");
|
|
102
|
+
try { if (fs.existsSync(c1)) return c1; } catch {}
|
|
103
|
+
|
|
104
|
+
// 方式 B: bin -> ../package.json (如果在 node_modules/.bin 下)
|
|
105
|
+
const c2 = path.resolve(binDir, "..", "package.json");
|
|
106
|
+
try {
|
|
107
|
+
if (fs.existsSync(c2)) {
|
|
108
|
+
const parentDir = path.dirname(c2);
|
|
109
|
+
if (fs.existsSync(path.join(parentDir, "plugin-sdk")) || fs.existsSync(path.join(parentDir, "dist", "plugin-sdk"))) {
|
|
110
|
+
return c2;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
} catch {}
|
|
114
|
+
|
|
115
|
+
return null;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* 读取 package.json 中的版本号。
|
|
120
|
+
*/
|
|
121
|
+
function readPkgVersion(pkgPath) {
|
|
122
|
+
try {
|
|
123
|
+
const v = JSON.parse(fs.readFileSync(pkgPath, "utf-8")).version;
|
|
124
|
+
return v || null;
|
|
125
|
+
} catch {
|
|
126
|
+
return null;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
30
130
|
/**
|
|
31
131
|
* 检查 openclaw 版本是否 >= 2026.3.22(需要 symlink 的最低版本)。
|
|
32
132
|
* 如果无法检测版本,返回 true(保守策略:宁可多创建也不遗漏)。
|
|
@@ -34,29 +134,25 @@ function compareVersionGte(version, target) {
|
|
|
34
134
|
function isOpenclawVersionRequiresSymlink() {
|
|
35
135
|
const REQUIRED = [2026, 3, 22];
|
|
36
136
|
|
|
37
|
-
// Strategy 1: 从全局
|
|
38
|
-
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
const
|
|
42
|
-
if (
|
|
43
|
-
const v = JSON.parse(fs.readFileSync(pkgPath, "utf-8")).version;
|
|
44
|
-
if (v) return compareVersionGte(v, REQUIRED);
|
|
45
|
-
}
|
|
137
|
+
// Strategy 1: 从全局 node_modules 读取 package.json 版本
|
|
138
|
+
for (const name of CLI_NAMES) {
|
|
139
|
+
const pkgPath = findPackageInGlobalDirs(name);
|
|
140
|
+
if (pkgPath) {
|
|
141
|
+
const v = readPkgVersion(pkgPath);
|
|
142
|
+
if (v) return compareVersionGte(v, REQUIRED);
|
|
46
143
|
}
|
|
47
|
-
}
|
|
144
|
+
}
|
|
48
145
|
|
|
49
|
-
// Strategy 2: 从 CLI
|
|
146
|
+
// Strategy 2: 从 CLI 二进制反查到 package.json
|
|
50
147
|
for (const name of CLI_NAMES) {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
} catch {}
|
|
148
|
+
const binPath = findCliInPath(name);
|
|
149
|
+
if (binPath) {
|
|
150
|
+
const pkgPath = resolveGlobalRootFromBin(binPath, name);
|
|
151
|
+
if (pkgPath) {
|
|
152
|
+
const v = readPkgVersion(pkgPath);
|
|
153
|
+
if (v) return compareVersionGte(v, REQUIRED);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
60
156
|
}
|
|
61
157
|
|
|
62
158
|
return true;
|
|
@@ -64,34 +160,22 @@ function isOpenclawVersionRequiresSymlink() {
|
|
|
64
160
|
|
|
65
161
|
/**
|
|
66
162
|
* 查找全局 openclaw 安装路径。
|
|
67
|
-
*
|
|
163
|
+
* 三种策略依次尝试:全局 node_modules、$PATH 反查、extensions 目录推断。
|
|
68
164
|
*/
|
|
69
165
|
function findOpenclawRoot(pluginRoot) {
|
|
70
|
-
// Strategy 1:
|
|
71
|
-
|
|
72
|
-
const
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
if (fs.existsSync(path.join(candidate, "package.json"))) return candidate;
|
|
76
|
-
}
|
|
77
|
-
} catch {}
|
|
166
|
+
// Strategy 1: 从全局 node_modules 查找
|
|
167
|
+
for (const name of CLI_NAMES) {
|
|
168
|
+
const pkgPath = findPackageInGlobalDirs(name);
|
|
169
|
+
if (pkgPath) return path.dirname(pkgPath);
|
|
170
|
+
}
|
|
78
171
|
|
|
79
|
-
// Strategy 2:
|
|
80
|
-
const whichCmd = process.platform === "win32" ? "where" : "which";
|
|
172
|
+
// Strategy 2: 从 $PATH 反查
|
|
81
173
|
for (const name of CLI_NAMES) {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
}).trim().split("\n")[0];
|
|
88
|
-
if (!bin) continue;
|
|
89
|
-
const realBin = fs.realpathSync(bin);
|
|
90
|
-
const c1 = path.resolve(path.dirname(realBin), "..", "lib", "node_modules", name);
|
|
91
|
-
if (fs.existsSync(path.join(c1, "package.json"))) return c1;
|
|
92
|
-
const c2 = path.resolve(path.dirname(realBin), "..");
|
|
93
|
-
if (fs.existsSync(path.join(c2, "package.json")) && fs.existsSync(path.join(c2, "plugin-sdk"))) return c2;
|
|
94
|
-
} catch {}
|
|
174
|
+
const binPath = findCliInPath(name);
|
|
175
|
+
if (binPath) {
|
|
176
|
+
const pkgPath = resolveGlobalRootFromBin(binPath, name);
|
|
177
|
+
if (pkgPath) return path.dirname(pkgPath);
|
|
178
|
+
}
|
|
95
179
|
}
|
|
96
180
|
|
|
97
181
|
// Strategy 3: 从 extensions 目录推断
|
|
@@ -100,11 +184,10 @@ function findOpenclawRoot(pluginRoot) {
|
|
|
100
184
|
const dataDirName = path.basename(dataDir);
|
|
101
185
|
const cliName = dataDirName.replace(/^\./, "");
|
|
102
186
|
if (cliName) {
|
|
103
|
-
|
|
104
|
-
const
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
} catch {}
|
|
187
|
+
for (const dir of getGlobalNodeModulesDirs()) {
|
|
188
|
+
const pkgPath = path.join(dir, cliName, "package.json");
|
|
189
|
+
try { if (fs.existsSync(pkgPath)) return path.dirname(pkgPath); } catch {}
|
|
190
|
+
}
|
|
108
191
|
}
|
|
109
192
|
|
|
110
193
|
return null;
|
|
@@ -929,22 +929,53 @@ NEW_VERSION=""; [ -f "$TARGET_DIR/package.json" ] && NEW_VERSION="$(read_pkg_ver
|
|
|
929
929
|
PREFLIGHT_OK=true
|
|
930
930
|
[ -z "$NEW_VERSION" ] && echo " ❌ 无法读取版本号" && PREFLIGHT_OK=false || echo " ✅ 版本: $NEW_VERSION"
|
|
931
931
|
|
|
932
|
-
ENTRY=""; for f in "dist/index.js" "index.js"; do [ -f "$TARGET_DIR/$f" ] && ENTRY="$f" && break; done
|
|
932
|
+
ENTRY=""; for f in "dist/index.cjs" "dist/index.js" "index.js"; do [ -f "$TARGET_DIR/$f" ] && ENTRY="$f" && break; done
|
|
933
933
|
[ -z "$ENTRY" ] && echo " ❌ 缺少入口文件" && PREFLIGHT_OK=false || echo " ✅ 入口: $ENTRY"
|
|
934
934
|
|
|
935
|
+
# 检测构建模式:bundled (tsup dist/index.cjs) vs unbundled (dist/src/ 独立文件)
|
|
936
|
+
# 优先看 dist/src/ 是否存在;存在 → unbundled;否则依赖入口文件大小判断
|
|
937
|
+
IS_BUNDLED=false
|
|
935
938
|
if [ -d "$TARGET_DIR/dist/src" ]; then
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
939
|
+
IS_BUNDLED=false
|
|
940
|
+
elif [ -f "$TARGET_DIR/$ENTRY" ]; then
|
|
941
|
+
BUNDLE_SIZE=$(wc -c < "$TARGET_DIR/$ENTRY" 2>/dev/null || echo "0")
|
|
942
|
+
# bundled 输出通常 > 200KB,unbundled 入口 < 50KB
|
|
943
|
+
[ "$BUNDLE_SIZE" -gt 200000 ] 2>/dev/null && IS_BUNDLED=true
|
|
941
944
|
fi
|
|
942
945
|
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
946
|
+
if [ "$IS_BUNDLED" = "true" ]; then
|
|
947
|
+
echo " ✅ bundled 构建 (${BUNDLE_SIZE} bytes)"
|
|
948
|
+
|
|
949
|
+
# 内联验证:bundle 中 grep 关键导出
|
|
950
|
+
BUNDLE_MISS=""
|
|
951
|
+
for sig in "GatewayConnection" "dispatchToOpenClaw" "qqbotPlugin" "sendText" "sendMedia"; do
|
|
952
|
+
if ! grep -qF "$sig" "$TARGET_DIR/$ENTRY" 2>/dev/null; then
|
|
953
|
+
BUNDLE_MISS="$BUNDLE_MISS $sig"
|
|
954
|
+
fi
|
|
955
|
+
done
|
|
956
|
+
[ -n "$BUNDLE_MISS" ] && echo " ❌ bundle 缺少签名:$BUNDLE_MISS" && PREFLIGHT_OK=false || echo " ✅ 关键模块签名完整"
|
|
957
|
+
|
|
958
|
+
# ws 依赖应该被 tsup noExternal 打包进 bundle
|
|
959
|
+
if grep -qF "ws" "$TARGET_DIR/$ENTRY" 2>/dev/null; then
|
|
960
|
+
echo " ✅ ws bundled"
|
|
961
|
+
else
|
|
962
|
+
echo " ⚠️ ws 未打包"
|
|
963
|
+
fi
|
|
964
|
+
else
|
|
965
|
+
if [ -d "$TARGET_DIR/dist/src" ]; then
|
|
966
|
+
JS_COUNT=$(find "$TARGET_DIR/dist/src" -name "*.js" -type f 2>/dev/null | wc -l | tr -d ' ')
|
|
967
|
+
echo " ✅ dist/src/ 含 ${JS_COUNT} 个 JS"
|
|
968
|
+
[ "$JS_COUNT" -lt 5 ] && echo " ❌ JS 数量异常偏少" && PREFLIGHT_OK=false
|
|
969
|
+
else
|
|
970
|
+
echo " ❌ 缺少 dist/src/"; PREFLIGHT_OK=false
|
|
971
|
+
fi
|
|
972
|
+
|
|
973
|
+
MISS=""
|
|
974
|
+
for m in "dist/src/gateway.js" "dist/src/api.js" "dist/src/admin-resolver.js"; do
|
|
975
|
+
[ ! -f "$TARGET_DIR/$m" ] && MISS="$MISS $m"
|
|
976
|
+
done
|
|
977
|
+
[ -n "$MISS" ] && echo " ❌ 缺少:$MISS" && PREFLIGHT_OK=false || echo " ✅ 关键模块完整"
|
|
978
|
+
fi
|
|
948
979
|
|
|
949
980
|
if [ -d "$TARGET_DIR/node_modules" ]; then
|
|
950
981
|
BOK=true
|
|
@@ -319,14 +319,14 @@ find "${TMPDIR:-/tmp}" -maxdepth 1 -name ".openclaw-qqbot-nm-bak-*" -exec rm -rf
|
|
|
319
319
|
# 导致新增的模块(如 streaming.js)缺失。
|
|
320
320
|
echo " 清空 dist/ 确保全量重新构建..."
|
|
321
321
|
rm -rf "$PROJ_DIR/dist"
|
|
322
|
-
if [ ! -f "$PROJ_DIR/dist/index.js" ]; then
|
|
322
|
+
if [ ! -f "$PROJ_DIR/dist/index.cjs" ] && [ ! -f "$PROJ_DIR/dist/index.js" ]; then
|
|
323
323
|
echo " dist/ 不存在,先执行构建..."
|
|
324
324
|
if [ ! -d "$PROJ_DIR/node_modules" ]; then
|
|
325
325
|
npm install --prefix "$PROJ_DIR" 2>&1 || true
|
|
326
326
|
fi
|
|
327
327
|
npm run --prefix "$PROJ_DIR" build 2>&1 || true
|
|
328
|
-
if [ ! -f "$PROJ_DIR/dist/index.js" ]; then
|
|
329
|
-
echo " ❌ 构建失败:dist/index.
|
|
328
|
+
if [ ! -f "$PROJ_DIR/dist/index.cjs" ] && [ ! -f "$PROJ_DIR/dist/index.js" ]; then
|
|
329
|
+
echo " ❌ 构建失败:dist/index.cjs 未生成"
|
|
330
330
|
echo " 请手动执行: cd $PROJ_DIR && npm install && npm run build"
|
|
331
331
|
exit 1
|
|
332
332
|
fi
|
|
@@ -360,7 +360,7 @@ if [ -n "$_NM_BACKUP" ] && [ -d "$_NM_BACKUP" ]; then
|
|
|
360
360
|
mv "$_NM_BACKUP" "$PROJ_DIR/node_modules"
|
|
361
361
|
echo " 已恢复源码目录 node_modules"
|
|
362
362
|
fi
|
|
363
|
-
if [ ! -f "$_INSTALL_DIR/dist/index.js" ] || [ ! -f "$_INSTALL_DIR/preload.cjs" ]; then
|
|
363
|
+
if { [ ! -f "$_INSTALL_DIR/dist/index.cjs" ] && [ ! -f "$_INSTALL_DIR/dist/index.js" ]; } || [ ! -f "$_INSTALL_DIR/preload.cjs" ]; then
|
|
364
364
|
echo ""
|
|
365
365
|
echo "❌ 插件安装失败!"
|
|
366
366
|
echo "========================================="
|
|
@@ -1,12 +1,33 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: qqbot-channel
|
|
3
|
-
description: QQ
|
|
3
|
+
description: QQ 频道管理技能(非QQ群)。查询频道列表、子频道、成员、发帖、公告、日程等操作。使用 qqbot_platform_api 工具代理 QQ 开放平台 HTTP 接口,自动处理 Token 鉴权。仅用于 QQ 频道(Guild/Channel)。触发条件:用户提到「频道」「子频道」「guild」「channel」「帖子」「日程」「公告」。
|
|
4
4
|
metadata: {"openclaw":{"emoji":"📡","requires":{"config":["channels.qqbot"]}}}
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# QQ 频道 API 请求指导
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
> **本 Skill 仅处理 QQ 频道(Guild/Channel)操作。** 频道 ID 为纯数字,API 路径为 `/guilds/...` 和 `/channels/...`。
|
|
10
|
+
|
|
11
|
+
`qqbot_platform_api` 是 QQ 开放平台统一 HTTP API 网关,**自动填充鉴权 Token**。你只需要指定 HTTP 方法、API 路径、请求体和查询参数即可调用频道相关接口。
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## 🔀 适用范围(必读)
|
|
16
|
+
|
|
17
|
+
QQ 频道是类似 Discord 的社区产品,层级结构为 **频道(Guild) → 子频道(Channel)**:
|
|
18
|
+
|
|
19
|
+
| 层级 | 中文名 | 英文 | API 路径 | ID 格式 |
|
|
20
|
+
|------|--------|------|----------|---------|
|
|
21
|
+
| 顶层 | 频道 | Guild | `/guilds/{guild_id}` | 纯数字(如 `123456`) |
|
|
22
|
+
| 次级 | 子频道 | Channel | `/channels/{channel_id}` | 纯数字(如 `789012`) |
|
|
23
|
+
|
|
24
|
+
**核心特征**:
|
|
25
|
+
- 频道内可以创建多个子频道(文字、语音、论坛、直播等)
|
|
26
|
+
- 支持发帖、公告、日程等功能
|
|
27
|
+
- 频道成员通过 `/guilds/{guild_id}/members` 管理
|
|
28
|
+
- ID 为纯数字格式,API 路径以 `/guilds/` 或 `/channels/` 开头
|
|
29
|
+
|
|
30
|
+
**触发关键词**:频道、子频道、guild、channel、帖子、日程、公告、论坛、频道成员
|
|
10
31
|
|
|
11
32
|
## 📚 详细参考文档
|
|
12
33
|
|
|
@@ -251,13 +272,14 @@ metadata: {"openclaw":{"emoji":"📡","requires":{"config":["channels.qqbot"]}}}
|
|
|
251
272
|
|
|
252
273
|
## ⚠️ 注意事项
|
|
253
274
|
|
|
254
|
-
1.
|
|
255
|
-
2.
|
|
256
|
-
3.
|
|
257
|
-
4.
|
|
258
|
-
5.
|
|
259
|
-
6.
|
|
260
|
-
7.
|
|
261
|
-
8.
|
|
262
|
-
9.
|
|
263
|
-
10.
|
|
275
|
+
1. **适用范围**:本 Skill 仅处理 QQ 频道(Guild/Channel)操作,API 路径以 `/guilds/` 或 `/channels/` 开头,ID 为纯数字
|
|
276
|
+
2. **路径中的占位符**(如 `{guild_id}`、`{channel_id}`)必须替换为实际的纯数字 ID
|
|
277
|
+
3. **query 参数的值必须为字符串类型**,如 `{ "limit": "100" }` 而非 `{ "limit": 100 }`
|
|
278
|
+
4. **成员列表翻页**时可能返回重复成员,需按 `user.id` 去重
|
|
279
|
+
5. **公告**的两种类型(消息公告和推荐子频道公告)会互相顶替
|
|
280
|
+
6. **日程**的时间戳为毫秒级字符串
|
|
281
|
+
7. **删除操作不可逆**,请谨慎使用
|
|
282
|
+
8. **论坛操作**仅私域机器人可用
|
|
283
|
+
9. **子频道分组**(type=4)的 `position` 必须 >= 2
|
|
284
|
+
10. **日程操作**有频率限制:单个管理员每天 10 次,单个频道每天 100 次
|
|
285
|
+
11. **头像/图标展示**:成员 `user.avatar` 和频道 `icon` 等图片 URL 必须使用 Markdown 图片语法 `` 展示,禁止作为纯文本或超链接展示
|