@zaofan/dsh-qqbot 1.10.10 → 1.10.13
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 +83 -0
- package/README_EN.md +31 -0
- package/client/qqbot-settings.js +116 -4
- package/dist/channel-tools.d.ts +0 -12
- package/dist/channel-tools.d.ts.map +1 -1
- package/dist/channel-tools.js +286 -21
- package/dist/channel-tools.js.map +1 -1
- package/dist/config.d.ts +18 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +11 -0
- package/dist/config.js.map +1 -1
- package/dist/features/group-join-request.d.ts.map +1 -1
- package/dist/features/group-join-request.js +29 -0
- package/dist/features/group-join-request.js.map +1 -1
- package/dist/features/msg-history.d.ts +78 -0
- package/dist/features/msg-history.d.ts.map +1 -0
- package/dist/features/msg-history.js +312 -0
- package/dist/features/msg-history.js.map +1 -0
- package/dist/features/msg-recent.d.ts +72 -0
- package/dist/features/msg-recent.d.ts.map +1 -0
- package/dist/features/msg-recent.js +131 -0
- package/dist/features/msg-recent.js.map +1 -0
- package/dist/gateway/bootstrap.d.ts.map +1 -1
- package/dist/gateway/bootstrap.js +83 -4
- package/dist/gateway/bootstrap.js.map +1 -1
- package/dist/gateway/middleware-setup.d.ts.map +1 -1
- package/dist/gateway/middleware-setup.js +52 -0
- package/dist/gateway/middleware-setup.js.map +1 -1
- package/dist/transport/inbound.d.ts.map +1 -1
- package/dist/transport/inbound.js +32 -0
- package/dist/transport/inbound.js.map +1 -1
- package/dist/transport/msg-content-cache.d.ts +50 -0
- package/dist/transport/msg-content-cache.d.ts.map +1 -1
- package/dist/transport/msg-content-cache.js +58 -14
- package/dist/transport/msg-content-cache.js.map +1 -1
- package/package.json +1 -1
- package/settings-host.js +48 -24
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* msg-history.ts — 群消息历史台账(2026-10-20 主人定:独立台账 + 按会话分目录 + 一天一个文件)
|
|
3
|
+
*
|
|
4
|
+
* 目录结构(`{dataRoot}/.qqbot/msg-history/`):
|
|
5
|
+
* group_<群openid>/2026-10-20.jsonl
|
|
6
|
+
* c2c_<对方openid>/2026-10-20.jsonl
|
|
7
|
+
*
|
|
8
|
+
* 设计要点(主人要求):
|
|
9
|
+
* · **一会话一目录** → 群与群、群与私聊天然隔离,读的时候根本碰不到别人的文件;
|
|
10
|
+
* · **一天一个文件** → 不会反复读写同一个越滚越大的文件;
|
|
11
|
+
* · **默认只保留 7 天** → 启动时 + 每 200 次写顺手清掉过期日期文件;
|
|
12
|
+
* · 一行一条:`{"id":"message_id","s":"发送者","n":"昵称","t":毫秒,"k":"text|image|voice|video|file","x":"正文摘要","me":true?}`
|
|
13
|
+
*
|
|
14
|
+
* 用途:`group_recall`(撤某人最近一条)、`group_msg_search`(按关键词/类型搜)、
|
|
15
|
+
* `group_recall_batch`(批量撤 + 顺带禁言)。与引用补全用的 msg-content.jsonl **互不干扰**。
|
|
16
|
+
*/
|
|
17
|
+
import { appendFileSync, existsSync, mkdirSync, readFileSync, readdirSync, rmSync, statSync, writeFileSync } from 'node:fs';
|
|
18
|
+
import { join } from 'node:path';
|
|
19
|
+
/** 默认保留天数(主人定:7 天) */
|
|
20
|
+
export const KEEP_DAYS = 7;
|
|
21
|
+
/** 单日文件读取上限(防御:一天消息特别多时别把内存吃爆) */
|
|
22
|
+
const MAX_READ_LINES = 5000;
|
|
23
|
+
/** 正文摘要长度 */
|
|
24
|
+
const TEXT_MAX = 200;
|
|
25
|
+
let historyRoot = '';
|
|
26
|
+
let writeTick = 0;
|
|
27
|
+
const pad = (n) => String(n).padStart(2, '0');
|
|
28
|
+
/** 本地日期 YYYY-MM-DD(不能用 toISOString,那是 UTC 会错日) */
|
|
29
|
+
function dayOf(ts) {
|
|
30
|
+
const d = new Date(ts);
|
|
31
|
+
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;
|
|
32
|
+
}
|
|
33
|
+
function safeId(id) {
|
|
34
|
+
return String(id).replace(/[^0-9A-Za-z_-]/gu, '');
|
|
35
|
+
}
|
|
36
|
+
function dirOf(scope, peerId) {
|
|
37
|
+
return join(historyRoot, `${scope}_${safeId(peerId)}`);
|
|
38
|
+
}
|
|
39
|
+
/** 初始化(bootstrap 启动时调一次):建目录 + 清过期 */
|
|
40
|
+
export function initMsgHistory(dataRoot) {
|
|
41
|
+
if (!dataRoot)
|
|
42
|
+
return;
|
|
43
|
+
historyRoot = join(dataRoot, '.qqbot', 'msg-history');
|
|
44
|
+
try {
|
|
45
|
+
mkdirSync(historyRoot, { recursive: true });
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
historyRoot = '';
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
pruneOld();
|
|
52
|
+
}
|
|
53
|
+
/** 删掉超过 KEEP_DAYS 天的日期文件(顺带删空目录) */
|
|
54
|
+
export function pruneOld() {
|
|
55
|
+
if (!historyRoot)
|
|
56
|
+
return;
|
|
57
|
+
const cutoff = Date.now() - KEEP_DAYS * 24 * 60 * 60 * 1000;
|
|
58
|
+
const cutoffDay = dayOf(cutoff);
|
|
59
|
+
let dirs = [];
|
|
60
|
+
try {
|
|
61
|
+
dirs = readdirSync(historyRoot);
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
for (const d of dirs) {
|
|
67
|
+
const dir = join(historyRoot, d);
|
|
68
|
+
let files = [];
|
|
69
|
+
try {
|
|
70
|
+
if (!statSync(dir).isDirectory())
|
|
71
|
+
continue;
|
|
72
|
+
files = readdirSync(dir);
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
let alive = 0;
|
|
78
|
+
for (const f of files) {
|
|
79
|
+
if (!/^\d{4}-\d{2}-\d{2}\.jsonl$/u.test(f))
|
|
80
|
+
continue;
|
|
81
|
+
if (f.slice(0, 10) < cutoffDay) {
|
|
82
|
+
try {
|
|
83
|
+
rmSync(join(dir, f), { force: true });
|
|
84
|
+
}
|
|
85
|
+
catch { /* ignore */ }
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
alive++;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
if (alive === 0) {
|
|
92
|
+
try {
|
|
93
|
+
rmSync(dir, { recursive: true, force: true });
|
|
94
|
+
}
|
|
95
|
+
catch { /* ignore */ }
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
/** 已经写过名字文件的会话(避免每条消息都写) */
|
|
100
|
+
const marked = new Set();
|
|
101
|
+
/** 读 {dataRoot}/.qqbot/groups.json 拿群名 */
|
|
102
|
+
function groupNameOf(gid) {
|
|
103
|
+
try {
|
|
104
|
+
const f = join(historyRoot, '..', 'groups.json');
|
|
105
|
+
const j = JSON.parse(readFileSync(f, 'utf8'));
|
|
106
|
+
const n = j?.[gid]?.name;
|
|
107
|
+
if (n)
|
|
108
|
+
return String(n).trim();
|
|
109
|
+
}
|
|
110
|
+
catch { /* 没注册表就算了 */ }
|
|
111
|
+
return '';
|
|
112
|
+
}
|
|
113
|
+
/** 根目录索引:所有群文件夹 ↔ 群名 对照(方便肉眼找) */
|
|
114
|
+
function refreshIndex() {
|
|
115
|
+
if (!historyRoot)
|
|
116
|
+
return;
|
|
117
|
+
let dirs = [];
|
|
118
|
+
try {
|
|
119
|
+
dirs = readdirSync(historyRoot);
|
|
120
|
+
}
|
|
121
|
+
catch {
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
const lines = ['QQ 消息历史台账索引', '', '目录 → 群名(本目录只保留最近 ' + KEEP_DAYS + ' 天)', ''];
|
|
125
|
+
for (const d of dirs.sort()) {
|
|
126
|
+
if (!d.startsWith('group_') && !d.startsWith('c2c_'))
|
|
127
|
+
continue;
|
|
128
|
+
const id = d.slice(6);
|
|
129
|
+
const name = d.startsWith('group_') ? (groupNameOf(id) || '未命名群') : ('私聊 ' + id.slice(0, 8));
|
|
130
|
+
lines.push(' ' + d + ' → ' + name);
|
|
131
|
+
}
|
|
132
|
+
lines.push('');
|
|
133
|
+
try {
|
|
134
|
+
writeFileSync(join(historyRoot, '_索引.txt'), lines.join(String.fromCharCode(10)) + String.fromCharCode(10), 'utf8');
|
|
135
|
+
}
|
|
136
|
+
catch { /* ignore */ }
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* 在该会话目录里放一个「<群名>.txt」(主人要求:打开文件夹一眼认出是哪个群)。
|
|
140
|
+
* 群名变了会顺手删掉旧名字文件;同时刷新根目录 _索引.txt。
|
|
141
|
+
*/
|
|
142
|
+
export function markSession(scope, peerId) {
|
|
143
|
+
if (!historyRoot || !peerId)
|
|
144
|
+
return;
|
|
145
|
+
const key = scope + ':' + peerId;
|
|
146
|
+
if (marked.has(key))
|
|
147
|
+
return;
|
|
148
|
+
const dir = dirOf(scope, peerId);
|
|
149
|
+
try {
|
|
150
|
+
mkdirSync(dir, { recursive: true });
|
|
151
|
+
}
|
|
152
|
+
catch {
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
const rawName = scope === 'group' ? (groupNameOf(peerId) || '未命名群') : ('私聊_' + peerId.slice(0, 8));
|
|
156
|
+
const BAD = String.fromCharCode(92) + '/:*?"<>|' + String.fromCharCode(13) + String.fromCharCode(10);
|
|
157
|
+
const safe = rawName.split('').map((ch) => (BAD.indexOf(ch) >= 0 ? '_' : ch)).join('').slice(0, 40) || '未命名';
|
|
158
|
+
try {
|
|
159
|
+
for (const f of readdirSync(dir)) {
|
|
160
|
+
if (f.endsWith('.txt') && f !== safe + '.txt')
|
|
161
|
+
rmSync(join(dir, f), { force: true });
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
catch { /* ignore */ }
|
|
165
|
+
const body = [
|
|
166
|
+
rawName,
|
|
167
|
+
'',
|
|
168
|
+
'群号(gid): ' + peerId,
|
|
169
|
+
'类型: ' + (scope === 'group' ? 'QQ群' : '私聊'),
|
|
170
|
+
'本目录保存最近 ' + KEEP_DAYS + ' 天的历史消息,每天一个 .jsonl(一行一条)。',
|
|
171
|
+
'由 dsh-qqbot 自动生成,仅用于人工辨认;删掉会自动重建。',
|
|
172
|
+
'',
|
|
173
|
+
].join(String.fromCharCode(10));
|
|
174
|
+
try {
|
|
175
|
+
writeFileSync(join(dir, safe + '.txt'), body, 'utf8');
|
|
176
|
+
}
|
|
177
|
+
catch { /* ignore */ }
|
|
178
|
+
marked.add(key);
|
|
179
|
+
refreshIndex();
|
|
180
|
+
}
|
|
181
|
+
/** 记一条(写入当天文件) */
|
|
182
|
+
export function appendMsgHistory(scope, peerId, rec) {
|
|
183
|
+
if (!historyRoot || !peerId || !rec?.id)
|
|
184
|
+
return;
|
|
185
|
+
markSession(scope, peerId);
|
|
186
|
+
const now = Date.now();
|
|
187
|
+
const row = {
|
|
188
|
+
id: String(rec.id),
|
|
189
|
+
s: String(rec.s ?? ''),
|
|
190
|
+
n: String(rec.n ?? ''),
|
|
191
|
+
t: Number(rec.t ?? now),
|
|
192
|
+
k: (rec.k ?? 'text'),
|
|
193
|
+
x: String(rec.x ?? '').replace(/\s+/gu, ' ').trim().slice(0, TEXT_MAX),
|
|
194
|
+
...(rec.me ? { me: true } : {}),
|
|
195
|
+
};
|
|
196
|
+
try {
|
|
197
|
+
const dir = dirOf(scope, peerId);
|
|
198
|
+
mkdirSync(dir, { recursive: true });
|
|
199
|
+
appendFileSync(join(dir, `${dayOf(row.t)}.jsonl`), `${JSON.stringify(row)}\n`, 'utf8');
|
|
200
|
+
}
|
|
201
|
+
catch {
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
writeTick = (writeTick + 1) % 200;
|
|
205
|
+
if (writeTick === 0)
|
|
206
|
+
pruneOld();
|
|
207
|
+
}
|
|
208
|
+
/** 读该会话的历史(**只碰它自己的目录**),新→旧 */
|
|
209
|
+
export function readMsgHistory(scope, peerId, q = {}) {
|
|
210
|
+
if (!historyRoot || !peerId)
|
|
211
|
+
return [];
|
|
212
|
+
const dir = dirOf(scope, peerId);
|
|
213
|
+
if (!existsSync(dir))
|
|
214
|
+
return [];
|
|
215
|
+
const now = Date.now();
|
|
216
|
+
const within = q.withinMs ?? KEEP_DAYS * 24 * 60 * 60 * 1000;
|
|
217
|
+
const from = now - within;
|
|
218
|
+
const limit = Math.max(1, Math.min(200, q.limit ?? 20));
|
|
219
|
+
const kw = String(q.keyword ?? '').trim().toLowerCase();
|
|
220
|
+
// 只读窗口覆盖到的日期文件(新→旧)
|
|
221
|
+
const days = [];
|
|
222
|
+
for (let d = new Date(now); d.getTime() >= from && days.length <= KEEP_DAYS; d = new Date(d.getTime() - 24 * 60 * 60 * 1000)) {
|
|
223
|
+
days.push(`${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`);
|
|
224
|
+
}
|
|
225
|
+
const out = [];
|
|
226
|
+
for (const day of days) {
|
|
227
|
+
if (out.length >= limit)
|
|
228
|
+
break;
|
|
229
|
+
const f = join(dir, `${day}.jsonl`);
|
|
230
|
+
if (!existsSync(f))
|
|
231
|
+
continue;
|
|
232
|
+
let text = '';
|
|
233
|
+
try {
|
|
234
|
+
text = readFileSync(f, 'utf8');
|
|
235
|
+
}
|
|
236
|
+
catch {
|
|
237
|
+
continue;
|
|
238
|
+
}
|
|
239
|
+
const lines = text.split('\n');
|
|
240
|
+
const start = Math.max(0, lines.length - MAX_READ_LINES);
|
|
241
|
+
for (let i = lines.length - 1; i >= start && out.length < limit; i--) {
|
|
242
|
+
const line = lines[i];
|
|
243
|
+
if (!line)
|
|
244
|
+
continue;
|
|
245
|
+
let r;
|
|
246
|
+
try {
|
|
247
|
+
r = JSON.parse(line);
|
|
248
|
+
}
|
|
249
|
+
catch {
|
|
250
|
+
continue;
|
|
251
|
+
}
|
|
252
|
+
if (!r?.id)
|
|
253
|
+
continue;
|
|
254
|
+
if (Number(r.t) < from)
|
|
255
|
+
continue;
|
|
256
|
+
if (q.fromSelf !== undefined && Boolean(r.me) !== q.fromSelf)
|
|
257
|
+
continue;
|
|
258
|
+
if (q.senderId && r.s !== q.senderId)
|
|
259
|
+
continue;
|
|
260
|
+
if (q.kind && (r.k ?? 'text') !== q.kind)
|
|
261
|
+
continue;
|
|
262
|
+
if (kw && !String(r.x ?? '').toLowerCase().includes(kw))
|
|
263
|
+
continue;
|
|
264
|
+
out.push(r);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
return out;
|
|
268
|
+
}
|
|
269
|
+
/** 找「某人最近一条」/「最近一条」 */
|
|
270
|
+
export function latestMsgHistory(scope, peerId, opts = {}) {
|
|
271
|
+
return readMsgHistory(scope, peerId, { ...opts, limit: 1 })[0];
|
|
272
|
+
}
|
|
273
|
+
/** 诊断:会话目录 + 今天文件行数 */
|
|
274
|
+
export function historyDebug(scope, peerId) {
|
|
275
|
+
if (!historyRoot)
|
|
276
|
+
return '(台账未初始化)';
|
|
277
|
+
const dir = dirOf(scope, peerId);
|
|
278
|
+
if (!existsSync(dir))
|
|
279
|
+
return `(该会话还没有台账目录: ${dir})`;
|
|
280
|
+
const f = join(dir, `${dayOf(Date.now())}.jsonl`);
|
|
281
|
+
let n = 0;
|
|
282
|
+
try {
|
|
283
|
+
if (existsSync(f))
|
|
284
|
+
n = readFileSync(f, 'utf8').split('\n').filter(Boolean).length;
|
|
285
|
+
}
|
|
286
|
+
catch { /* ignore */ }
|
|
287
|
+
return `(台账 ${dir} · 今天 ${n} 条 · 保留 ${KEEP_DAYS} 天)`;
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* 最近有消息写入的群目录对应的 gid(2026-10-20)。
|
|
291
|
+
* 用途:web 会话里拿不到群会话记录时的兜底 —— 一般就是"当前正在聊的群"。
|
|
292
|
+
*/
|
|
293
|
+
export function latestGroupId() {
|
|
294
|
+
if (!historyRoot)
|
|
295
|
+
return '';
|
|
296
|
+
let best = '';
|
|
297
|
+
let bestT = 0;
|
|
298
|
+
try {
|
|
299
|
+
for (const d of readdirSync(historyRoot)) {
|
|
300
|
+
if (!d.startsWith('group_'))
|
|
301
|
+
continue;
|
|
302
|
+
const st = statSync(join(historyRoot, d));
|
|
303
|
+
if (st.mtimeMs > bestT) {
|
|
304
|
+
bestT = st.mtimeMs;
|
|
305
|
+
best = d.slice(6);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
catch { /* ignore */ }
|
|
310
|
+
return best;
|
|
311
|
+
}
|
|
312
|
+
//# sourceMappingURL=msg-history.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"msg-history.js","sourceRoot":"","sources":["../../src/features/msg-history.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* msg-recent.ts — 入站/出站消息的「最近 msgId」环形缓冲(2026-10-20 主人需求: 撤回成员消息)
|
|
3
|
+
*
|
|
4
|
+
* 背景:官方 `DELETE /v2/groups/{gid}/messages/{message_id}` 允许**群管理员撤回普通成员的消息**
|
|
5
|
+
* (2 分钟内),但需要那条消息的 message_id。插件拿到 message_id 的地方只有:
|
|
6
|
+
* · 入站事件(bootstrap 的 `bot.on('message')` 里 `msg.messageId`)
|
|
7
|
+
* · 出站发送的返回值(机器人自己发的)
|
|
8
|
+
* 而现有台账都不记全量 msgId:
|
|
9
|
+
* · `msg-index/[peer]/refs.json` 只记「被引用/被回复」的消息(不是全量)
|
|
10
|
+
* · `self-said/[peer].json` 只记机器人自己发的(且是给引用用的短号映射)
|
|
11
|
+
* · `chat-raw.jsonl` 是给 AI 的正文,没有 id
|
|
12
|
+
*
|
|
13
|
+
* 所以这里**不新增落盘台账**:只做一个**进程内内存**环形缓冲(每 peer 最近 RECENT_MAX 条,
|
|
14
|
+
* 且只保留最近 2 分钟——正好是官方撤回窗口),结构:
|
|
15
|
+
* `peerKey → [{ msgId, senderId, senderName, at, text, kind, fromSelf }]`
|
|
16
|
+
* 重启即清空。用途:
|
|
17
|
+
* · `group_recall` —— 撤某人最近一条 / 群里最近一条 / 指定 msgId
|
|
18
|
+
* · `group_msg_search` —— 按关键词/类型搜出命中消息(含机器人自己发的)
|
|
19
|
+
* · `group_recall_batch` —— 批量撤回 + 可选批量禁言发送者
|
|
20
|
+
*/
|
|
21
|
+
export declare const RECENT_MAX = 80;
|
|
22
|
+
/** 保留窗口:官方撤回窗口就是 2 分钟,超过就没意义了(2026-10-20 主人定:按 2 分钟缓冲) */
|
|
23
|
+
export declare const RETENTION_MS = 120000;
|
|
24
|
+
/** 正文摘要长度(只用于搜索/回显,不存全文) */
|
|
25
|
+
export declare const TEXT_SNIPPET = 120;
|
|
26
|
+
export type MsgKind = 'text' | 'image' | 'voice' | 'file' | 'video';
|
|
27
|
+
export interface RecentMsg {
|
|
28
|
+
msgId: string;
|
|
29
|
+
senderId: string;
|
|
30
|
+
senderName: string;
|
|
31
|
+
at: number;
|
|
32
|
+
/** 正文摘要(图片/语音等可留空或写占位符) */
|
|
33
|
+
text?: string;
|
|
34
|
+
/** 消息类型(默认 text) */
|
|
35
|
+
kind?: MsgKind;
|
|
36
|
+
/** 是否机器人自己发的(自己发的只能自己撤,成员消息需要群管理员) */
|
|
37
|
+
fromSelf?: boolean;
|
|
38
|
+
}
|
|
39
|
+
export declare function peerKeyOf(scope: 'group' | 'c2c', peerId: string): string;
|
|
40
|
+
/** 正文摘要:去换行/压空白/截断 */
|
|
41
|
+
export declare function snippetOf(text: string | undefined | null): string;
|
|
42
|
+
/** 记一条消息(入站/出站同用;同 msgId 去重;先按 2 分钟窗口裁旧,再按容量裁尾) */
|
|
43
|
+
export declare function rememberInbound(scope: 'group' | 'c2c', peerId: string, rec: RecentMsg): void;
|
|
44
|
+
/** 记一条**机器人自己发的**消息(出站成功拿到 message_id 后调用) */
|
|
45
|
+
export declare function rememberSelf(scope: 'group' | 'c2c', peerId: string, rec: {
|
|
46
|
+
msgId: string;
|
|
47
|
+
text?: string;
|
|
48
|
+
kind?: MsgKind;
|
|
49
|
+
at?: number;
|
|
50
|
+
senderName?: string;
|
|
51
|
+
}): void;
|
|
52
|
+
/** 取最近消息;senderId 为空 = 不限发送者(群里最近一条) */
|
|
53
|
+
export declare function findRecent(scope: 'group' | 'c2c', peerId: string, opts?: {
|
|
54
|
+
senderId?: string;
|
|
55
|
+
withinMs?: number;
|
|
56
|
+
}): RecentMsg | undefined;
|
|
57
|
+
/** 找「某人 2 分钟内最近一条」并返回下标距离(批量用) */
|
|
58
|
+
export declare function filterRecent(scope: 'group' | 'c2c', peerId: string, opts?: {
|
|
59
|
+
keyword?: string;
|
|
60
|
+
kind?: MsgKind;
|
|
61
|
+
fromSelf?: boolean;
|
|
62
|
+
senderId?: string;
|
|
63
|
+
withinMs?: number;
|
|
64
|
+
limit?: number;
|
|
65
|
+
}): RecentMsg[];
|
|
66
|
+
/** 列出该 peer 最近消息(调试/工具回显用) */
|
|
67
|
+
export declare function listRecent(scope: 'group' | 'c2c', peerId: string, limit?: number): RecentMsg[];
|
|
68
|
+
/** 清空(测试用) */
|
|
69
|
+
export declare function clearRecent(): void;
|
|
70
|
+
/** 诊断: 当前缓冲区里有哪些 peer 键、各有几条(查不到时回给 AI,方便定位键不匹配) */
|
|
71
|
+
export declare function debugSummary(): string;
|
|
72
|
+
//# sourceMappingURL=msg-recent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"msg-recent.d.ts","sourceRoot":"","sources":["../../src/features/msg-recent.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,eAAO,MAAM,UAAU,KAAK,CAAC;AAC7B,0DAA0D;AAC1D,eAAO,MAAM,YAAY,SAAU,CAAC;AACpC,4BAA4B;AAC5B,eAAO,MAAM,YAAY,MAAM,CAAC;AAEhC,MAAM,MAAM,OAAO,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO,CAAC;AAEpE,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,2BAA2B;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,oBAAoB;IACpB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,sCAAsC;IACtC,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAKD,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAExE;AAED,sBAAsB;AACtB,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GAAG,MAAM,CAGjE;AAkBD,mDAAmD;AACnD,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,SAAS,GAAG,IAAI,CAc5F;AAED,8CAA8C;AAC9C,wBAAgB,YAAY,CAC1B,KAAK,EAAE,OAAO,GAAG,KAAK,EACtB,MAAM,EAAE,MAAM,EACd,GAAG,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,OAAO,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,GACtF,IAAI,CAUN;AAED,wCAAwC;AACxC,wBAAgB,UAAU,CACxB,KAAK,EAAE,OAAO,GAAG,KAAK,EACtB,MAAM,EAAE,MAAM,EACd,IAAI,GAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAO,GAClD,SAAS,GAAG,SAAS,CAMvB;AAED,kCAAkC;AAClC,wBAAgB,YAAY,CAC1B,KAAK,EAAE,OAAO,GAAG,KAAK,EACtB,MAAM,EAAE,MAAM,EACd,IAAI,GAAE;IACJ,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CACX,GACL,SAAS,EAAE,CAeb;AAED,8BAA8B;AAC9B,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,SAAK,GAAG,SAAS,EAAE,CAE1F;AAED,cAAc;AACd,wBAAgB,WAAW,IAAI,IAAI,CAElC;AAED,oDAAoD;AACpD,wBAAgB,YAAY,IAAI,MAAM,CAQrC"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* msg-recent.ts — 入站/出站消息的「最近 msgId」环形缓冲(2026-10-20 主人需求: 撤回成员消息)
|
|
3
|
+
*
|
|
4
|
+
* 背景:官方 `DELETE /v2/groups/{gid}/messages/{message_id}` 允许**群管理员撤回普通成员的消息**
|
|
5
|
+
* (2 分钟内),但需要那条消息的 message_id。插件拿到 message_id 的地方只有:
|
|
6
|
+
* · 入站事件(bootstrap 的 `bot.on('message')` 里 `msg.messageId`)
|
|
7
|
+
* · 出站发送的返回值(机器人自己发的)
|
|
8
|
+
* 而现有台账都不记全量 msgId:
|
|
9
|
+
* · `msg-index/[peer]/refs.json` 只记「被引用/被回复」的消息(不是全量)
|
|
10
|
+
* · `self-said/[peer].json` 只记机器人自己发的(且是给引用用的短号映射)
|
|
11
|
+
* · `chat-raw.jsonl` 是给 AI 的正文,没有 id
|
|
12
|
+
*
|
|
13
|
+
* 所以这里**不新增落盘台账**:只做一个**进程内内存**环形缓冲(每 peer 最近 RECENT_MAX 条,
|
|
14
|
+
* 且只保留最近 2 分钟——正好是官方撤回窗口),结构:
|
|
15
|
+
* `peerKey → [{ msgId, senderId, senderName, at, text, kind, fromSelf }]`
|
|
16
|
+
* 重启即清空。用途:
|
|
17
|
+
* · `group_recall` —— 撤某人最近一条 / 群里最近一条 / 指定 msgId
|
|
18
|
+
* · `group_msg_search` —— 按关键词/类型搜出命中消息(含机器人自己发的)
|
|
19
|
+
* · `group_recall_batch` —— 批量撤回 + 可选批量禁言发送者
|
|
20
|
+
*/
|
|
21
|
+
export const RECENT_MAX = 80;
|
|
22
|
+
/** 保留窗口:官方撤回窗口就是 2 分钟,超过就没意义了(2026-10-20 主人定:按 2 分钟缓冲) */
|
|
23
|
+
export const RETENTION_MS = 120_000;
|
|
24
|
+
/** 正文摘要长度(只用于搜索/回显,不存全文) */
|
|
25
|
+
export const TEXT_SNIPPET = 120;
|
|
26
|
+
/** peerKey(`group:<gid>` / `c2c:<openid>`) → 最近消息(新→旧) */
|
|
27
|
+
const store = new Map();
|
|
28
|
+
export function peerKeyOf(scope, peerId) {
|
|
29
|
+
return `${scope}:${peerId}`;
|
|
30
|
+
}
|
|
31
|
+
/** 正文摘要:去换行/压空白/截断 */
|
|
32
|
+
export function snippetOf(text) {
|
|
33
|
+
const s = String(text ?? '').replace(/\s+/gu, ' ').trim();
|
|
34
|
+
return s.length > TEXT_SNIPPET ? `${s.slice(0, TEXT_SNIPPET)}…` : s;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* 取消息列表:优先精确键;**若该键没有数据,就合并所有同 scope 的键**。
|
|
38
|
+
* 原因(2026-10-20 实测): 入站事件里的 groupOpenid 与出站 target 的群 openid 不一定同源,
|
|
39
|
+
* 按单一 key 查会查不到;这里做兜底,避免"明明有消息却搜不到"。
|
|
40
|
+
*/
|
|
41
|
+
function collect(scope, peerId) {
|
|
42
|
+
// ★ 严格按会话隔离(2026-10-20 主人要求): 绝不合并其它群的键
|
|
43
|
+
return (store.get(peerKeyOf(scope, peerId)) ?? []).slice().sort((a, b) => b.at - a.at);
|
|
44
|
+
}
|
|
45
|
+
function prune(key, now) {
|
|
46
|
+
const arr = (store.get(key) ?? []).filter((x) => now - x.at <= RETENTION_MS);
|
|
47
|
+
store.set(key, arr);
|
|
48
|
+
return arr;
|
|
49
|
+
}
|
|
50
|
+
/** 记一条消息(入站/出站同用;同 msgId 去重;先按 2 分钟窗口裁旧,再按容量裁尾) */
|
|
51
|
+
export function rememberInbound(scope, peerId, rec) {
|
|
52
|
+
if (!peerId || !rec?.msgId)
|
|
53
|
+
return;
|
|
54
|
+
const key = peerKeyOf(scope, peerId);
|
|
55
|
+
const now = Date.now();
|
|
56
|
+
const arr = prune(key, now);
|
|
57
|
+
if (arr.some((x) => x.msgId === rec.msgId))
|
|
58
|
+
return;
|
|
59
|
+
arr.unshift({
|
|
60
|
+
...rec,
|
|
61
|
+
text: snippetOf(rec.text),
|
|
62
|
+
kind: rec.kind ?? 'text',
|
|
63
|
+
fromSelf: rec.fromSelf === true,
|
|
64
|
+
});
|
|
65
|
+
if (arr.length > RECENT_MAX)
|
|
66
|
+
arr.length = RECENT_MAX;
|
|
67
|
+
store.set(key, arr);
|
|
68
|
+
}
|
|
69
|
+
/** 记一条**机器人自己发的**消息(出站成功拿到 message_id 后调用) */
|
|
70
|
+
export function rememberSelf(scope, peerId, rec) {
|
|
71
|
+
rememberInbound(scope, peerId, {
|
|
72
|
+
msgId: rec.msgId,
|
|
73
|
+
senderId: 'self',
|
|
74
|
+
senderName: rec.senderName ?? '机器人',
|
|
75
|
+
at: rec.at ?? Date.now(),
|
|
76
|
+
text: rec.text,
|
|
77
|
+
kind: rec.kind,
|
|
78
|
+
fromSelf: true,
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
/** 取最近消息;senderId 为空 = 不限发送者(群里最近一条) */
|
|
82
|
+
export function findRecent(scope, peerId, opts = {}) {
|
|
83
|
+
const arr = collect(scope, peerId);
|
|
84
|
+
if (arr.length === 0)
|
|
85
|
+
return undefined;
|
|
86
|
+
const now = Date.now();
|
|
87
|
+
const maxAge = opts.withinMs ?? RETENTION_MS;
|
|
88
|
+
return arr.find((x) => (!opts.senderId || x.senderId === opts.senderId) && now - x.at <= maxAge);
|
|
89
|
+
}
|
|
90
|
+
/** 找「某人 2 分钟内最近一条」并返回下标距离(批量用) */
|
|
91
|
+
export function filterRecent(scope, peerId, opts = {}) {
|
|
92
|
+
const arr = collect(scope, peerId);
|
|
93
|
+
const now = Date.now();
|
|
94
|
+
const maxAge = opts.withinMs ?? RETENTION_MS;
|
|
95
|
+
const kw = String(opts.keyword ?? '').trim().toLowerCase();
|
|
96
|
+
const out = arr.filter((x) => {
|
|
97
|
+
if (now - x.at > maxAge)
|
|
98
|
+
return false;
|
|
99
|
+
if (opts.fromSelf !== undefined && Boolean(x.fromSelf) !== opts.fromSelf)
|
|
100
|
+
return false;
|
|
101
|
+
if (opts.senderId && x.senderId !== opts.senderId)
|
|
102
|
+
return false;
|
|
103
|
+
if (opts.kind && (x.kind ?? 'text') !== opts.kind)
|
|
104
|
+
return false;
|
|
105
|
+
if (kw && !String(x.text ?? '').toLowerCase().includes(kw))
|
|
106
|
+
return false;
|
|
107
|
+
return true;
|
|
108
|
+
});
|
|
109
|
+
const limit = Math.max(1, Math.min(RECENT_MAX, opts.limit ?? 20));
|
|
110
|
+
return out.slice(0, limit);
|
|
111
|
+
}
|
|
112
|
+
/** 列出该 peer 最近消息(调试/工具回显用) */
|
|
113
|
+
export function listRecent(scope, peerId, limit = 10) {
|
|
114
|
+
return (store.get(peerKeyOf(scope, peerId)) ?? []).slice(0, Math.max(1, limit));
|
|
115
|
+
}
|
|
116
|
+
/** 清空(测试用) */
|
|
117
|
+
export function clearRecent() {
|
|
118
|
+
store.clear();
|
|
119
|
+
}
|
|
120
|
+
/** 诊断: 当前缓冲区里有哪些 peer 键、各有几条(查不到时回给 AI,方便定位键不匹配) */
|
|
121
|
+
export function debugSummary() {
|
|
122
|
+
const now = Date.now();
|
|
123
|
+
const rows = [];
|
|
124
|
+
for (const [k, v] of store) {
|
|
125
|
+
const alive = v.filter((x) => now - x.at <= RETENTION_MS);
|
|
126
|
+
if (alive.length > 0)
|
|
127
|
+
rows.push(k.slice(0, 26) + '…(' + alive.length + '条)');
|
|
128
|
+
}
|
|
129
|
+
return rows.length ? rows.join(' | ') : '(空)';
|
|
130
|
+
}
|
|
131
|
+
//# sourceMappingURL=msg-recent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"msg-recent.js","sourceRoot":"","sources":["../../src/features/msg-recent.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bootstrap.d.ts","sourceRoot":"","sources":["../../src/gateway/bootstrap.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAKnD,OAAO,EAAkB,KAAK,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAK5E,OAAO,KAAK,EAAE,aAAa,EAAsB,MAAM,cAAc,CAAC;AACtE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"bootstrap.d.ts","sourceRoot":"","sources":["../../src/gateway/bootstrap.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAKnD,OAAO,EAAkB,KAAK,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAK5E,OAAO,KAAK,EAAE,aAAa,EAAsB,MAAM,cAAc,CAAC;AACtE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AA0C1C;;;;;;;;;GASG;AACH,MAAM,WAAW,qBAAqB;IACpC,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC;CACrD;AAED,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,gBAAgB,EACxB,MAAM,EAAE,aAAa,EACrB,MAAM,EAAE,MAAM,EACd,KAAK,CAAC,EAAE,qBAAqB,GAC5B,OAAO,CAAC,IAAI,CAAC,CA02Bf"}
|