feat: detect replies to bot messages in group chats

This commit is contained in:
linuztx 2026-03-26 09:57:34 +08:00
parent b4492e0759
commit 6bf63eb9c6
5 changed files with 27 additions and 11 deletions

View file

@ -23,7 +23,7 @@ The WhatsApp session persists across restarts in `usr/whatsapp/sessions/`. No re
|---------|-------------|---------|
| `enabled` | Enable bridge and polling | `false` |
| `mode` | `dedicated` (separate number) or `self-chat` (personal number) | `dedicated` |
| `allow_group` | Respond in group chats when mentioned | `false` |
| `allow_group` | Respond in group chats when mentioned or replied to | `false` |
| `bridge_port` | Local HTTP port for bridge | `3100` |
| `poll_interval_seconds` | Poll frequency (min 2) | `3` |
| `allowed_users` | Phone numbers without + prefix | `[]` (all) |

View file

@ -5,7 +5,7 @@ mode: dedicated
bridge_port: 3100
poll_interval_seconds: 3
allow_group: false
# allow_group: respond in group chats when mentioned
# allow_group: respond in group chats when mentioned or replied to
allowed_users: []
# Example: ["34652029134", "1234567890"]
project: ""

View file

@ -69,13 +69,13 @@ async def _dispatch_message(config: dict, msg: dict) -> None:
chat_id = msg.get("chatId", "")
is_group = msg.get("isGroup", False)
# Group filtering: skip unless allow_group enabled AND bot was mentioned
# Group filtering: skip unless allow_group enabled AND bot was mentioned or replied to
if is_group:
if not config.get("allow_group", False):
PrintStyle.debug(f"WhatsApp: skipping group message (allow_group disabled)")
return
if not msg.get("mentionedMe", False):
PrintStyle.debug(f"WhatsApp: skipping group message (not mentioned)")
if not msg.get("mentionedMe", False) and not msg.get("repliedToMe", False):
PrintStyle.debug(f"WhatsApp: skipping group message (not mentioned or replied to)")
return
# Show typing indicator immediately so user sees activity

View file

@ -131,7 +131,7 @@
<div class="field">
<div class="field-label">
<div class="field-title">Allow Group</div>
<div class="field-description">Respond in group chats when mentioned</div>
<div class="field-description">Respond in group chats when mentioned or replied to</div>
</div>
<div class="field-control">
<label class="toggle">

View file

@ -260,28 +260,43 @@ async function startSocket() {
continue;
}
// Detect if the bot was mentioned in a group message
// Detect if the bot was mentioned or replied to in a group message
let mentionedMe = false;
let repliedToMe = false;
if (isGroup && sock.user) {
const contextInfo = msg.message.extendedTextMessage?.contextInfo
|| msg.message.imageMessage?.contextInfo
|| msg.message.videoMessage?.contextInfo
|| msg.message.documentMessage?.contextInfo
|| null;
const mentionedJids = contextInfo?.mentionedJid || [];
// Build set of bot's own numbers for comparison
const myNums = new Set();
if (sock.user.id) myNums.add(numOf(sock.user.id));
if (sock.user.lid) myNums.add(numOf(sock.user.lid));
// Include reverse LID mappings so either format matches
for (const [lid, phone] of Object.entries(lidToPhone)) {
if (myNums.has(lid)) myNums.add(String(phone));
if (myNums.has(String(phone))) myNums.add(lid);
}
// Check @mentions
const mentionedJids = contextInfo?.mentionedJid || [];
for (const jid of mentionedJids) {
if (myNums.has(numOf(jid))) { mentionedMe = true; break; }
}
if (WHATSAPP_DEBUG && mentionedJids.length > 0) {
try { console.log(JSON.stringify({ event: 'mention_check', myNums: [...myNums], mentionedJids, mentionedMe })); } catch {}
// Check if replying to a bot message
if (contextInfo?.stanzaId) {
const replyParticipant = contextInfo.participant || '';
if (replyParticipant && myNums.has(numOf(replyParticipant))) {
repliedToMe = true;
} else if (recentlySentIds.has(contextInfo.stanzaId)) {
repliedToMe = true;
}
}
if (WHATSAPP_DEBUG && (mentionedJids.length > 0 || repliedToMe)) {
try { console.log(JSON.stringify({ event: 'mention_reply_check', myNums: [...myNums], mentionedJids, mentionedMe, repliedToMe, stanzaId: contextInfo?.stanzaId })); } catch {}
}
}
@ -325,6 +340,7 @@ async function startSocket() {
chatName,
isGroup,
mentionedMe,
repliedToMe,
body: cleanBody,
hasMedia,
mediaType,