(msg: Api.Message, args: string[])
| 478 | await msg.edit({ text: `🧭 正在摸排嫌疑人 ${target.name} 的窝点...`, parseMode: "html" }); |
| 479 | |
| 480 | let bestPeer: string | null = null; |
| 481 | let bestCount = 0; |
| 482 | let bestMsg: CachedMsg | null = null; |
| 483 | |
| 484 | for (const [peer, chat] of this.chatCache) { |
| 485 | let cnt = 0; |
| 486 | let latest: CachedMsg | null = null; |
| 487 | for (const m of chat.msgs) { |
| 488 | if (String(m.senderId) === target.id) { |
| 489 | cnt++; |
| 490 | if (!latest) latest = m; // first hit = newest (msgs newest-first) |
| 491 | } |
| 492 | } |
| 493 | if (cnt > bestCount) { |
| 494 | bestCount = cnt; |
| 495 | bestPeer = peer; |
| 496 | bestMsg = latest; |
| 497 | } |
| 498 | } |
| 499 | |
| 500 | await msg.delete().catch(() => {}); |
| 501 | |
| 502 | if (!bestPeer || bestCount === 0) { |
| 503 | await this.sendReply(msg, `🤦♀ 摸排结果不尽人意,嫌疑人 ${target.name} 藏的很深。`); |
| 504 | return; |
| 505 | } |
| 506 | |
| 507 | // link text = group name, href points to target's latest msg in that group |
| 508 | let link = `https://t.me/c/${peelChatId(bestPeer)}`; |
| 509 | if (bestMsg) { |
| 510 | const chat = this.chatCache.get(bestPeer)!; |
| 511 | const mid = bestMsg.id; |
| 512 | const href = chat.username ? `https://t.me/${chat.username}/${mid}` : `https://t.me/c/${peelChatId(bestPeer)}/${mid}`; |
| 513 | link = `<a href="${href}">${htmlEsc(chat.title || chat.username || bestPeer)}</a>`; |
| 514 | } |
| 515 | await this.sendReply(msg, `🏚 发现嫌疑人 ${target.name} 的窝点:\n\n${link}\n\n<i>跑得了和尚跑不了庙。</i>`); |
| 516 | } |
| 517 | |
| 518 | /* ====== obs (group-scoped surveillance) ====== */ |
| 519 | |
| 520 | private async doObs(msg: Api.Message, args: string[]) { |
| 521 | const cl = await getGlobalClient(); |
| 522 | if (!cl) return; |
| 523 | |
| 524 | // parse group link from first arg |
| 525 | let scopePeer: string | undefined; |
| 526 | const tme = args[0]?.match(/^(?:https?:\/\/)?t\.me\/(\w+)/i); |
| 527 | let targetArgs = args; |
| 528 | if (tme) { |
| 529 | const gn = tme[1].toLowerCase(); |
| 530 | targetArgs = args.slice(1); |
| 531 | for (const [p, c] of this.chatCache) |
no test coverage detected