(msg: Api.Message, args: string[])
| 395 | targetName: target.name, |
| 396 | triggerPeer: String(msg.chatId), |
| 397 | triggerMsgId: msg.id, |
| 398 | }); |
| 399 | await this.persistDb(); |
| 400 | } |
| 401 | |
| 402 | /* ====== listen — update cache + check surveillance ====== */ |
| 403 | |
| 404 | private async onMsg(msg: Api.Message) { |
| 405 | // 1) update cache — only public groups, auto-vivify on first sighting |
| 406 | if (msg.chatId) { |
| 407 | const peer = String(msg.chatId); |
| 408 | let chat = this.chatCache.get(peer); |
| 409 | if (!chat) { |
| 410 | // first sighting → check if public, cache only public groups |
| 411 | const cl = await getGlobalClient(); |
| 412 | if (cl) { |
| 413 | try { |
| 414 | const entity = entityFields(await cl.getEntity(msg.chatId)); |
| 415 | if (entity.username && (entity.className === 'Channel' || entity.className === 'Chat')) { |
| 416 | chat = { username: entity.username, title: entity.title, msgs: [] }; |
| 417 | this.chatCache.set(peer, chat); |
| 418 | } |
| 419 | } catch { /* getEntity failed → skip */ } |
| 420 | } |
| 421 | } |
| 422 | if (chat) { |
| 423 | chat.msgs.unshift(stripMsg(msg)); |
| 424 | this.pruneExpired(chat); |
| 425 | if (chat.msgs.length > CACHE_MSG_LIMIT) chat.msgs.length = CACHE_MSG_LIMIT; |
| 426 | this.schedulePersistCache(); |
| 427 | } |
| 428 | } |
| 429 | |
| 430 | // 2) sv surveillance |
| 431 | if (this.sv.size === 0) return; |
| 432 | const sid = msg.senderId ? String(msg.senderId) : ""; |
| 433 | if (!sid || !this.sv.has(sid)) return; |
| 434 | const entry = this.sv.get(sid)!; |
| 435 | |
| 436 | // prevent self-trigger |
| 437 | if (String(msg.chatId) === entry.triggerPeer && msg.id === entry.triggerMsgId) return; |
| 438 | |
| 439 | // mon scope — only trigger if message is in the target group |
| 440 | if (entry.scopePeer && String(msg.chatId) !== entry.scopePeer) return; |
| 441 | |
| 442 | // check group is public (has username) before consuming the sv entry |
| 443 | const cl = await getGlobalClient(); |
| 444 | if (!cl) return; |
| 445 | const chatEntity = entityFields(await cl.getEntity(msg.peerId)); |
| 446 | if (!chatEntity.username) return; // private group — skip silently, keep sv alive |
| 447 | |
| 448 | this.sv.delete(sid); |
| 449 | this.persistDb().catch((e) => console.error("[fbi] persistDb error", e)); |
no test coverage detected