fix: add message deduplication to WhatsApp channel
Prevent infinite loops by tracking processed message IDs in WhatsApp channel. The bridge may send duplicate messages which caused the bot to respond repeatedly with the same generic message. Changes: - Add _processed_message_ids deque (max 2000) to track seen messages - Skip processing if message_id was already processed - Align WhatsApp dedup with other channels (Feishu, Email, Mochat, QQ) This fixes the issue where WhatsApp gets stuck in a loop sending identical responses repeatedly. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
import json
|
import json
|
||||||
|
from collections import deque
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from loguru import logger
|
from loguru import logger
|
||||||
@@ -21,12 +22,14 @@ class WhatsAppChannel(BaseChannel):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
name = "whatsapp"
|
name = "whatsapp"
|
||||||
|
MAX_PROCESSED_MESSAGE_IDS = 2000
|
||||||
|
|
||||||
def __init__(self, config: WhatsAppConfig, bus: MessageBus):
|
def __init__(self, config: WhatsAppConfig, bus: MessageBus):
|
||||||
super().__init__(config, bus)
|
super().__init__(config, bus)
|
||||||
self.config: WhatsAppConfig = config
|
self.config: WhatsAppConfig = config
|
||||||
self._ws = None
|
self._ws = None
|
||||||
self._connected = False
|
self._connected = False
|
||||||
|
self._processed_message_ids: deque[str] = deque(maxlen=self.MAX_PROCESSED_MESSAGE_IDS)
|
||||||
|
|
||||||
async def start(self) -> None:
|
async def start(self) -> None:
|
||||||
"""Start the WhatsApp channel by connecting to the bridge."""
|
"""Start the WhatsApp channel by connecting to the bridge."""
|
||||||
@@ -108,6 +111,15 @@ class WhatsAppChannel(BaseChannel):
|
|||||||
# New LID sytle typically:
|
# New LID sytle typically:
|
||||||
sender = data.get("sender", "")
|
sender = data.get("sender", "")
|
||||||
content = data.get("content", "")
|
content = data.get("content", "")
|
||||||
|
message_id = data.get("id", "")
|
||||||
|
|
||||||
|
# Dedup by message ID to prevent loops
|
||||||
|
if message_id and message_id in self._processed_message_ids:
|
||||||
|
logger.debug("Duplicate message {}, skipping", message_id)
|
||||||
|
return
|
||||||
|
|
||||||
|
if message_id:
|
||||||
|
self._processed_message_ids.append(message_id)
|
||||||
|
|
||||||
# Extract just the phone number or lid as chat_id
|
# Extract just the phone number or lid as chat_id
|
||||||
user_id = pn if pn else sender
|
user_id = pn if pn else sender
|
||||||
@@ -124,7 +136,7 @@ class WhatsAppChannel(BaseChannel):
|
|||||||
chat_id=sender, # Use full LID for replies
|
chat_id=sender, # Use full LID for replies
|
||||||
content=content,
|
content=content,
|
||||||
metadata={
|
metadata={
|
||||||
"message_id": data.get("id"),
|
"message_id": message_id,
|
||||||
"timestamp": data.get("timestamp"),
|
"timestamp": data.get("timestamp"),
|
||||||
"is_group": data.get("isGroup", False)
|
"is_group": data.get("isGroup", False)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user