@sliverp/qqbot 1.3.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 +231 -0
- package/clawdbot.plugin.json +16 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.js +22 -0
- package/dist/src/api.d.ts +194 -0
- package/dist/src/api.js +555 -0
- package/dist/src/channel.d.ts +3 -0
- package/dist/src/channel.js +146 -0
- package/dist/src/config.d.ts +25 -0
- package/dist/src/config.js +148 -0
- package/dist/src/gateway.d.ts +17 -0
- package/dist/src/gateway.js +722 -0
- package/dist/src/image-server.d.ts +62 -0
- package/dist/src/image-server.js +401 -0
- package/dist/src/known-users.d.ts +100 -0
- package/dist/src/known-users.js +264 -0
- package/dist/src/onboarding.d.ts +10 -0
- package/dist/src/onboarding.js +190 -0
- package/dist/src/outbound.d.ts +149 -0
- package/dist/src/outbound.js +476 -0
- package/dist/src/proactive.d.ts +170 -0
- package/dist/src/proactive.js +398 -0
- package/dist/src/runtime.d.ts +3 -0
- package/dist/src/runtime.js +10 -0
- package/dist/src/session-store.d.ts +49 -0
- package/dist/src/session-store.js +242 -0
- package/dist/src/types.d.ts +116 -0
- package/dist/src/types.js +1 -0
- package/dist/src/utils/image-size.d.ts +51 -0
- package/dist/src/utils/image-size.js +234 -0
- package/dist/src/utils/payload.d.ts +112 -0
- package/dist/src/utils/payload.js +186 -0
- package/index.ts +27 -0
- package/moltbot.plugin.json +16 -0
- package/node_modules/ws/LICENSE +20 -0
- package/node_modules/ws/README.md +548 -0
- package/node_modules/ws/browser.js +8 -0
- package/node_modules/ws/index.js +13 -0
- package/node_modules/ws/lib/buffer-util.js +131 -0
- package/node_modules/ws/lib/constants.js +19 -0
- package/node_modules/ws/lib/event-target.js +292 -0
- package/node_modules/ws/lib/extension.js +203 -0
- package/node_modules/ws/lib/limiter.js +55 -0
- package/node_modules/ws/lib/permessage-deflate.js +528 -0
- package/node_modules/ws/lib/receiver.js +706 -0
- package/node_modules/ws/lib/sender.js +602 -0
- package/node_modules/ws/lib/stream.js +161 -0
- package/node_modules/ws/lib/subprotocol.js +62 -0
- package/node_modules/ws/lib/validation.js +152 -0
- package/node_modules/ws/lib/websocket-server.js +554 -0
- package/node_modules/ws/lib/websocket.js +1393 -0
- package/node_modules/ws/package.json +69 -0
- package/node_modules/ws/wrapper.mjs +8 -0
- package/openclaw.plugin.json +16 -0
- package/package.json +38 -0
- package/qqbot-1.3.0.tgz +0 -0
- package/scripts/proactive-api-server.ts +346 -0
- package/scripts/send-proactive.ts +273 -0
- package/scripts/upgrade.sh +106 -0
- package/skills/qqbot-cron/SKILL.md +490 -0
- package/skills/qqbot-media/SKILL.md +138 -0
- package/src/api.ts +752 -0
- package/src/channel.ts +303 -0
- package/src/config.ts +172 -0
- package/src/gateway.ts +1588 -0
- package/src/image-server.ts +474 -0
- package/src/known-users.ts +358 -0
- package/src/onboarding.ts +254 -0
- package/src/openclaw-plugin-sdk.d.ts +483 -0
- package/src/outbound.ts +571 -0
- package/src/proactive.ts +528 -0
- package/src/runtime.ts +14 -0
- package/src/session-store.ts +292 -0
- package/src/types.ts +123 -0
- package/src/utils/image-size.ts +266 -0
- package/src/utils/payload.ts +265 -0
- package/tsconfig.json +16 -0
- package/upgrade-and-run.sh +89 -0
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
#!/usr/bin/env npx ts-node
|
|
2
|
+
/**
|
|
3
|
+
* QQBot 主动消息 CLI 工具
|
|
4
|
+
*
|
|
5
|
+
* 使用示例:
|
|
6
|
+
* # 发送私聊消息
|
|
7
|
+
* npx ts-node scripts/send-proactive.ts --to "用户openid" --text "你好!"
|
|
8
|
+
*
|
|
9
|
+
* # 发送群聊消息
|
|
10
|
+
* npx ts-node scripts/send-proactive.ts --to "群组openid" --type group --text "群公告"
|
|
11
|
+
*
|
|
12
|
+
* # 列出已知用户
|
|
13
|
+
* npx ts-node scripts/send-proactive.ts --list
|
|
14
|
+
*
|
|
15
|
+
* # 列出群聊用户
|
|
16
|
+
* npx ts-node scripts/send-proactive.ts --list --type group
|
|
17
|
+
*
|
|
18
|
+
* # 广播消息
|
|
19
|
+
* npx ts-node scripts/send-proactive.ts --broadcast --text "系统公告" --type c2c --limit 10
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
import {
|
|
23
|
+
sendProactiveMessageDirect,
|
|
24
|
+
listKnownUsers,
|
|
25
|
+
getKnownUsersStats,
|
|
26
|
+
broadcastMessage,
|
|
27
|
+
} from "../src/proactive.js";
|
|
28
|
+
import type { ResolvedQQBotAccount } from "../src/types.js";
|
|
29
|
+
import * as fs from "node:fs";
|
|
30
|
+
import * as path from "node:path";
|
|
31
|
+
|
|
32
|
+
// 解析命令行参数
|
|
33
|
+
function parseArgs(): Record<string, string | boolean> {
|
|
34
|
+
const args: Record<string, string | boolean> = {};
|
|
35
|
+
const argv = process.argv.slice(2);
|
|
36
|
+
|
|
37
|
+
for (let i = 0; i < argv.length; i++) {
|
|
38
|
+
const arg = argv[i];
|
|
39
|
+
if (arg.startsWith("--")) {
|
|
40
|
+
const key = arg.slice(2);
|
|
41
|
+
const nextArg = argv[i + 1];
|
|
42
|
+
if (nextArg && !nextArg.startsWith("--")) {
|
|
43
|
+
args[key] = nextArg;
|
|
44
|
+
i++;
|
|
45
|
+
} else {
|
|
46
|
+
args[key] = true;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return args;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// 从配置文件加载账户信息
|
|
55
|
+
function loadAccount(accountId = "default"): ResolvedQQBotAccount | null {
|
|
56
|
+
const configPath = path.join(process.env.HOME || "/home/ubuntu", "clawd", "config.json");
|
|
57
|
+
|
|
58
|
+
try {
|
|
59
|
+
if (!fs.existsSync(configPath)) {
|
|
60
|
+
// 尝试从环境变量获取
|
|
61
|
+
const appId = process.env.QQBOT_APP_ID;
|
|
62
|
+
const clientSecret = process.env.QQBOT_CLIENT_SECRET;
|
|
63
|
+
|
|
64
|
+
if (appId && clientSecret) {
|
|
65
|
+
return {
|
|
66
|
+
accountId,
|
|
67
|
+
appId,
|
|
68
|
+
clientSecret,
|
|
69
|
+
enabled: true,
|
|
70
|
+
secretSource: "env",
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
console.error("配置文件不存在且环境变量未设置");
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const config = JSON.parse(fs.readFileSync(configPath, "utf-8"));
|
|
79
|
+
const qqbot = config.channels?.qqbot;
|
|
80
|
+
|
|
81
|
+
if (!qqbot) {
|
|
82
|
+
console.error("配置中没有 qqbot 配置");
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// 解析账户配置
|
|
87
|
+
if (accountId === "default") {
|
|
88
|
+
return {
|
|
89
|
+
accountId: "default",
|
|
90
|
+
appId: qqbot.appId || process.env.QQBOT_APP_ID,
|
|
91
|
+
clientSecret: qqbot.clientSecret || process.env.QQBOT_CLIENT_SECRET,
|
|
92
|
+
enabled: qqbot.enabled ?? true,
|
|
93
|
+
secretSource: qqbot.clientSecret ? "config" : "env",
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const accountConfig = qqbot.accounts?.[accountId];
|
|
98
|
+
if (accountConfig) {
|
|
99
|
+
return {
|
|
100
|
+
accountId,
|
|
101
|
+
appId: accountConfig.appId || qqbot.appId || process.env.QQBOT_APP_ID,
|
|
102
|
+
clientSecret: accountConfig.clientSecret || qqbot.clientSecret || process.env.QQBOT_CLIENT_SECRET,
|
|
103
|
+
enabled: accountConfig.enabled ?? true,
|
|
104
|
+
secretSource: accountConfig.clientSecret ? "config" : "env",
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
console.error(`账户 ${accountId} 不存在`);
|
|
109
|
+
return null;
|
|
110
|
+
} catch (err) {
|
|
111
|
+
console.error(`加载配置失败: ${err}`);
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
async function main() {
|
|
117
|
+
const args = parseArgs();
|
|
118
|
+
|
|
119
|
+
// 显示帮助
|
|
120
|
+
if (args.help || args.h) {
|
|
121
|
+
console.log(`
|
|
122
|
+
QQBot 主动消息 CLI 工具
|
|
123
|
+
|
|
124
|
+
用法:
|
|
125
|
+
npx ts-node scripts/send-proactive.ts [选项]
|
|
126
|
+
|
|
127
|
+
选项:
|
|
128
|
+
--to <openid> 目标用户或群组的 openid
|
|
129
|
+
--text <message> 要发送的消息内容
|
|
130
|
+
--type <type> 消息类型: c2c (私聊) 或 group (群聊),默认 c2c
|
|
131
|
+
--account <id> 账户 ID,默认 default
|
|
132
|
+
|
|
133
|
+
--list 列出已知用户
|
|
134
|
+
--stats 显示用户统计
|
|
135
|
+
--broadcast 广播消息给所有已知用户
|
|
136
|
+
--limit <n> 限制数量
|
|
137
|
+
|
|
138
|
+
--help, -h 显示帮助
|
|
139
|
+
|
|
140
|
+
示例:
|
|
141
|
+
# 发送私聊消息
|
|
142
|
+
npx ts-node scripts/send-proactive.ts --to "0Eda5EA7-xxx" --text "你好!"
|
|
143
|
+
|
|
144
|
+
# 发送群聊消息
|
|
145
|
+
npx ts-node scripts/send-proactive.ts --to "A1B2C3D4" --type group --text "群公告"
|
|
146
|
+
|
|
147
|
+
# 列出最近 10 个私聊用户
|
|
148
|
+
npx ts-node scripts/send-proactive.ts --list --type c2c --limit 10
|
|
149
|
+
|
|
150
|
+
# 广播消息
|
|
151
|
+
npx ts-node scripts/send-proactive.ts --broadcast --text "系统公告" --limit 5
|
|
152
|
+
`);
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
const accountId = (args.account as string) || "default";
|
|
157
|
+
const type = (args.type as "c2c" | "group") || "c2c";
|
|
158
|
+
const limit = args.limit ? parseInt(args.limit as string, 10) : undefined;
|
|
159
|
+
|
|
160
|
+
// 列出已知用户
|
|
161
|
+
if (args.list) {
|
|
162
|
+
const users = listKnownUsers({
|
|
163
|
+
type: args.type as "c2c" | "group" | "channel" | undefined,
|
|
164
|
+
accountId: args.account as string | undefined,
|
|
165
|
+
limit,
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
if (users.length === 0) {
|
|
169
|
+
console.log("没有已知用户");
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
console.log(`\n已知用户列表 (共 ${users.length} 个):\n`);
|
|
174
|
+
console.log("类型\t\tOpenID\t\t\t\t\t\t昵称\t\t最后交互时间");
|
|
175
|
+
console.log("─".repeat(100));
|
|
176
|
+
|
|
177
|
+
for (const user of users) {
|
|
178
|
+
const lastTime = new Date(user.lastInteractionAt).toLocaleString();
|
|
179
|
+
console.log(`${user.type}\t\t${user.openid.slice(0, 20)}...\t${user.nickname || "-"}\t\t${lastTime}`);
|
|
180
|
+
}
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// 显示统计
|
|
185
|
+
if (args.stats) {
|
|
186
|
+
const stats = getKnownUsersStats(args.account as string | undefined);
|
|
187
|
+
console.log(`\n用户统计:`);
|
|
188
|
+
console.log(` 总计: ${stats.total}`);
|
|
189
|
+
console.log(` 私聊: ${stats.c2c}`);
|
|
190
|
+
console.log(` 群聊: ${stats.group}`);
|
|
191
|
+
console.log(` 频道: ${stats.channel}`);
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// 广播消息
|
|
196
|
+
if (args.broadcast) {
|
|
197
|
+
if (!args.text) {
|
|
198
|
+
console.error("请指定消息内容 (--text)");
|
|
199
|
+
process.exit(1);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// 加载配置用于广播
|
|
203
|
+
const configPath = path.join(process.env.HOME || "/home/ubuntu", "clawd", "config.json");
|
|
204
|
+
let cfg: Record<string, unknown> = {};
|
|
205
|
+
try {
|
|
206
|
+
if (fs.existsSync(configPath)) {
|
|
207
|
+
cfg = JSON.parse(fs.readFileSync(configPath, "utf-8"));
|
|
208
|
+
}
|
|
209
|
+
} catch {}
|
|
210
|
+
|
|
211
|
+
console.log(`\n开始广播消息...\n`);
|
|
212
|
+
const result = await broadcastMessage(args.text as string, cfg as any, {
|
|
213
|
+
type,
|
|
214
|
+
accountId,
|
|
215
|
+
limit,
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
console.log(`\n广播完成:`);
|
|
219
|
+
console.log(` 发送总数: ${result.total}`);
|
|
220
|
+
console.log(` 成功: ${result.success}`);
|
|
221
|
+
console.log(` 失败: ${result.failed}`);
|
|
222
|
+
|
|
223
|
+
if (result.failed > 0) {
|
|
224
|
+
console.log(`\n失败详情:`);
|
|
225
|
+
for (const r of result.results) {
|
|
226
|
+
if (!r.result.success) {
|
|
227
|
+
console.log(` ${r.to}: ${r.result.error}`);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// 发送单条消息
|
|
235
|
+
if (args.to && args.text) {
|
|
236
|
+
const account = loadAccount(accountId);
|
|
237
|
+
if (!account) {
|
|
238
|
+
console.error("无法加载账户配置");
|
|
239
|
+
process.exit(1);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
console.log(`\n发送消息...`);
|
|
243
|
+
console.log(` 目标: ${args.to}`);
|
|
244
|
+
console.log(` 类型: ${type}`);
|
|
245
|
+
console.log(` 内容: ${args.text}`);
|
|
246
|
+
|
|
247
|
+
const result = await sendProactiveMessageDirect(
|
|
248
|
+
account,
|
|
249
|
+
args.to as string,
|
|
250
|
+
args.text as string,
|
|
251
|
+
type
|
|
252
|
+
);
|
|
253
|
+
|
|
254
|
+
if (result.success) {
|
|
255
|
+
console.log(`\n✅ 发送成功!`);
|
|
256
|
+
console.log(` 消息ID: ${result.messageId}`);
|
|
257
|
+
console.log(` 时间戳: ${result.timestamp}`);
|
|
258
|
+
} else {
|
|
259
|
+
console.log(`\n❌ 发送失败: ${result.error}`);
|
|
260
|
+
process.exit(1);
|
|
261
|
+
}
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// 没有有效参数
|
|
266
|
+
console.error("请指定操作。使用 --help 查看帮助。");
|
|
267
|
+
process.exit(1);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
main().catch((err) => {
|
|
271
|
+
console.error(`执行失败: ${err}`);
|
|
272
|
+
process.exit(1);
|
|
273
|
+
});
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# QQBot 插件升级脚本
|
|
3
|
+
# 用于清理旧版本插件并重新安装
|
|
4
|
+
# 兼容 clawdbot 和 openclaw 两种安装
|
|
5
|
+
|
|
6
|
+
set -e
|
|
7
|
+
|
|
8
|
+
echo "=== QQBot 插件升级脚本 ==="
|
|
9
|
+
|
|
10
|
+
# 检测使用的是 clawdbot 还是 openclaw
|
|
11
|
+
detect_installation() {
|
|
12
|
+
if [ -d "$HOME/.clawdbot" ]; then
|
|
13
|
+
echo "clawdbot"
|
|
14
|
+
elif [ -d "$HOME/.openclaw" ]; then
|
|
15
|
+
echo "openclaw"
|
|
16
|
+
else
|
|
17
|
+
echo ""
|
|
18
|
+
fi
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
# 清理指定目录的函数
|
|
22
|
+
cleanup_installation() {
|
|
23
|
+
local APP_NAME="$1"
|
|
24
|
+
local APP_DIR="$HOME/.$APP_NAME"
|
|
25
|
+
local CONFIG_FILE="$APP_DIR/$APP_NAME.json"
|
|
26
|
+
local EXTENSION_DIR="$APP_DIR/extensions/qqbot"
|
|
27
|
+
|
|
28
|
+
echo ""
|
|
29
|
+
echo ">>> 处理 $APP_NAME 安装..."
|
|
30
|
+
|
|
31
|
+
# 1. 删除旧的扩展目录
|
|
32
|
+
if [ -d "$EXTENSION_DIR" ]; then
|
|
33
|
+
echo "删除旧版本插件: $EXTENSION_DIR"
|
|
34
|
+
rm -rf "$EXTENSION_DIR"
|
|
35
|
+
else
|
|
36
|
+
echo "未找到旧版本插件目录,跳过删除"
|
|
37
|
+
fi
|
|
38
|
+
|
|
39
|
+
# 2. 清理配置文件中的 qqbot 相关字段
|
|
40
|
+
if [ -f "$CONFIG_FILE" ]; then
|
|
41
|
+
echo "清理配置文件中的 qqbot 字段..."
|
|
42
|
+
|
|
43
|
+
# 使用 node 处理 JSON(比 jq 更可靠处理复杂结构)
|
|
44
|
+
node -e "
|
|
45
|
+
const fs = require('fs');
|
|
46
|
+
const config = JSON.parse(fs.readFileSync('$CONFIG_FILE', 'utf8'));
|
|
47
|
+
|
|
48
|
+
// 删除 channels.qqbot
|
|
49
|
+
if (config.channels && config.channels.qqbot) {
|
|
50
|
+
delete config.channels.qqbot;
|
|
51
|
+
console.log(' - 已删除 channels.qqbot');
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// 删除 plugins.entries.qqbot
|
|
55
|
+
if (config.plugins && config.plugins.entries && config.plugins.entries.qqbot) {
|
|
56
|
+
delete config.plugins.entries.qqbot;
|
|
57
|
+
console.log(' - 已删除 plugins.entries.qqbot');
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// 删除 plugins.installs.qqbot
|
|
61
|
+
if (config.plugins && config.plugins.installs && config.plugins.installs.qqbot) {
|
|
62
|
+
delete config.plugins.installs.qqbot;
|
|
63
|
+
console.log(' - 已删除 plugins.installs.qqbot');
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
fs.writeFileSync('$CONFIG_FILE', JSON.stringify(config, null, 2));
|
|
67
|
+
console.log('配置文件已更新');
|
|
68
|
+
"
|
|
69
|
+
else
|
|
70
|
+
echo "未找到配置文件: $CONFIG_FILE"
|
|
71
|
+
fi
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
# 检测并处理所有可能的安装
|
|
75
|
+
FOUND_INSTALLATION=""
|
|
76
|
+
|
|
77
|
+
# 检查 clawdbot
|
|
78
|
+
if [ -d "$HOME/.clawdbot" ]; then
|
|
79
|
+
cleanup_installation "clawdbot"
|
|
80
|
+
FOUND_INSTALLATION="clawdbot"
|
|
81
|
+
fi
|
|
82
|
+
|
|
83
|
+
# 检查 openclaw
|
|
84
|
+
if [ -d "$HOME/.openclaw" ]; then
|
|
85
|
+
cleanup_installation "openclaw"
|
|
86
|
+
FOUND_INSTALLATION="openclaw"
|
|
87
|
+
fi
|
|
88
|
+
|
|
89
|
+
# 如果都没找到
|
|
90
|
+
if [ -z "$FOUND_INSTALLATION" ]; then
|
|
91
|
+
echo "未找到 clawdbot 或 openclaw 安装目录"
|
|
92
|
+
echo "请确认已安装 clawdbot 或 openclaw"
|
|
93
|
+
exit 1
|
|
94
|
+
fi
|
|
95
|
+
|
|
96
|
+
# 使用检测到的安装类型作为命令
|
|
97
|
+
CMD="$FOUND_INSTALLATION"
|
|
98
|
+
|
|
99
|
+
echo ""
|
|
100
|
+
echo "=== 清理完成 ==="
|
|
101
|
+
echo ""
|
|
102
|
+
echo "接下来请执行以下命令重新安装插件:"
|
|
103
|
+
echo " cd /path/to/qqbot"
|
|
104
|
+
echo " $CMD plugins install ."
|
|
105
|
+
echo " $CMD channels add --channel qqbot --token \"AppID:AppSecret\""
|
|
106
|
+
echo " $CMD gateway restart"
|