fix(platforms): carry the inbound message id into the session source everywhere
Same bug class as the Slack/Feishu picks: buzz, dingtalk, email, google_chat, line, ntfy, photon, sms, teams, wecom and whatsapp already had the platform message id on the MessageEvent but built the SessionSource without it, so source.message_id consumers (reply anchor in run.py, /sethome synthetic-thread check, relay _event_ids fallback, shutdown notice anchor) saw None. Only sites where the id variable was already in scope are widened.
This commit is contained in:
@@ -1897,7 +1897,7 @@ class BuzzAdapter(BasePlatformAdapter):
|
||||
message_type = MessageType.DOCUMENT
|
||||
source = self.build_source(
|
||||
chat_id=chat_id, chat_name=self._channel_names.get(chat_id, chat_id), chat_type=chat_type,
|
||||
user_id=user_id, user_name=user_name, thread_id=thread_id,
|
||||
user_id=user_id, user_name=user_name, thread_id=thread_id, message_id=message_id,
|
||||
)
|
||||
event = MessageEvent(
|
||||
text=text, message_type=message_type, source=source, raw_message=raw_message, message_id=message_id,
|
||||
|
||||
@@ -365,7 +365,8 @@ class DingTalkAdapter(BasePlatformAdapter):
|
||||
if not text and not media_urls:
|
||||
return logger.debug("[%s] Empty message, skipping", self.name)
|
||||
source = self.build_source(chat_id=chat_id, chat_name=getattr(message, "conversation_title", None), chat_type="group" if is_group else "dm",
|
||||
user_id=sender_id, user_name=sender_nick, user_id_alt=sender_staff_id if sender_staff_id else None)
|
||||
user_id=sender_id, user_name=sender_nick, user_id_alt=sender_staff_id if sender_staff_id else None,
|
||||
message_id=msg_id)
|
||||
create_at = getattr(message, "create_at", None)
|
||||
try:
|
||||
timestamp = datetime.fromtimestamp(int(create_at) / 1000, tz=timezone.utc) if create_at else datetime.now(tz=timezone.utc)
|
||||
|
||||
@@ -644,7 +644,8 @@ class EmailAdapter(BasePlatformAdapter):
|
||||
event = MessageEvent(
|
||||
text=text or "(empty email)", message_id=msg_data["message_id"],
|
||||
message_type=MessageType.DOCUMENT if "document" in kinds else MessageType.PHOTO if "image" in kinds else MessageType.TEXT,
|
||||
source=self.build_source(chat_id=sender_addr, chat_name=name, chat_type="dm", user_id=sender_addr, user_name=name),
|
||||
source=self.build_source(chat_id=sender_addr, chat_name=name, chat_type="dm", user_id=sender_addr, user_name=name,
|
||||
message_id=msg_data["message_id"]),
|
||||
media_urls=[att["path"] for att in attachments], media_types=[att["media_type"] for att in attachments],
|
||||
reply_to_message_id=msg_data["in_reply_to"] or None)
|
||||
logger.info("[Email] New message from %s: %s", sender_addr, subject)
|
||||
|
||||
@@ -920,7 +920,7 @@ class GoogleChatAdapter(BasePlatformAdapter):
|
||||
# Email is the canonical id (allowlists use emails); the ``users/{id}``
|
||||
# resource name moves to user_id_alt.
|
||||
user_id=(sender_email or sender_name), user_name=sender.get("displayName") or sender_email or sender_name,
|
||||
thread_id=session_thread_id, user_id_alt=(sender_name or None),
|
||||
thread_id=session_thread_id, user_id_alt=(sender_name or None), message_id=msg.get("name") or None,
|
||||
)
|
||||
return MessageEvent(
|
||||
text=text, message_type=message_type, source=source, raw_message=msg, message_id=msg.get("name") or None,
|
||||
|
||||
@@ -582,7 +582,8 @@ class LineAdapter(BasePlatformAdapter):
|
||||
if chat_type == "dm" and self._client: # best-effort typing indicator (DM only)
|
||||
asyncio.create_task(self._client.loading(chat_id))
|
||||
source_obj = self.build_source(
|
||||
chat_id=chat_id, chat_type=chat_type, user_id=user_id, user_name=user_id, chat_name=chat_id)
|
||||
chat_id=chat_id, chat_type=chat_type, user_id=user_id, user_name=user_id, chat_name=chat_id,
|
||||
message_id=message_id)
|
||||
await self.handle_message(MessageEvent(
|
||||
text=text, message_type=_LINE_MESSAGE_TYPES.get(msg_type, MessageType.TEXT), source=source_obj,
|
||||
raw_message=event, message_id=message_id, media_urls=media_urls, media_types=media_types))
|
||||
|
||||
@@ -256,7 +256,7 @@ class NtfyAdapter(BasePlatformAdapter):
|
||||
# NOT drive authorization, so user_id is fixed to the topic name.
|
||||
topic = event.get("topic") or self._topic
|
||||
source = self.build_source(
|
||||
chat_id=topic, chat_name=topic, chat_type="dm", user_id=topic, user_name=topic)
|
||||
chat_id=topic, chat_name=topic, chat_type="dm", user_id=topic, user_name=topic, message_id=msg_id)
|
||||
unix_ts, timestamp = event.get("time"), datetime.now(tz=timezone.utc)
|
||||
try:
|
||||
timestamp = datetime.fromtimestamp(int(unix_ts), tz=timezone.utc) if unix_ts else timestamp
|
||||
|
||||
@@ -759,7 +759,7 @@ class PhotonAdapter(BasePlatformAdapter):
|
||||
|
||||
def _event(text: str, mtype: MessageType = MessageType.TEXT, **kwargs: Any) -> MessageEvent:
|
||||
source = self.build_source(chat_id=space_id, chat_name=space_id, chat_type=chat_type,
|
||||
user_id=sender_id, user_name=sender_id or None)
|
||||
user_id=sender_id, user_name=sender_id or None, message_id=message_id)
|
||||
return MessageEvent(text=text, message_type=mtype, source=source, message_id=message_id,
|
||||
raw_message=event, timestamp=timestamp, **kwargs)
|
||||
if ctype in {"read", "read_receipt"}: # presence signal, not a user turn (receipts for our sends)
|
||||
|
||||
@@ -259,7 +259,8 @@ class SmsAdapter(BasePlatformAdapter):
|
||||
return _twiml_response()
|
||||
logger.info("[sms] inbound from %s -> %s: %s", redact_phone(from_number), redact_phone(to_number), text[:80])
|
||||
source = self.build_source(
|
||||
chat_id=from_number, chat_name=from_number, chat_type="dm", user_id=from_number, user_name=from_number)
|
||||
chat_id=from_number, chat_name=from_number, chat_type="dm", user_id=from_number, user_name=from_number,
|
||||
message_id=message_sid)
|
||||
event = MessageEvent(
|
||||
text=text, message_type=MessageType.TEXT, source=source, raw_message=form, message_id=message_sid)
|
||||
# Non-blocking: Twilio expects a fast response
|
||||
|
||||
@@ -492,7 +492,8 @@ class TeamsAdapter(BasePlatformAdapter):
|
||||
chat_type=_CHAT_TYPES.get(getattr(conv, "conversation_type", None) or "", "dm"),
|
||||
user_id=str(user_id),
|
||||
user_name=getattr(from_account, "name", None) or "",
|
||||
guild_id=getattr(conv, "tenant_id", None) or self._tenant_id)
|
||||
guild_id=getattr(conv, "tenant_id", None) or self._tenant_id,
|
||||
message_id=msg_id)
|
||||
media: list = [m for m in [await self._cache_attachment(a) for a in getattr(activity, "attachments", None) or []] if m]
|
||||
media_kinds = [kind for _, _, kind in media] # media items are (path, media_type, kind)
|
||||
msg_type = next((t for kind, t in _MEDIA_KIND_PRECEDENCE if kind in media_kinds), MessageType.TEXT)
|
||||
|
||||
@@ -462,7 +462,8 @@ class WeComAdapter(WeComStreamMixin, WeComMediaMixin, ChatSendQueueMixin, BasePl
|
||||
if not text and not media_urls:
|
||||
logger.info("[%s] Empty WeCom message skipped: is_group=%s chat=%s msgtype=%r", self.name, is_group, chat_id, body.get("msgtype"))
|
||||
return
|
||||
source = self.build_source(chat_id=chat_id, chat_type="group" if is_group else "dm", user_id=sender_id or None, user_name=sender_id or None)
|
||||
source = self.build_source(chat_id=chat_id, chat_type="group" if is_group else "dm", user_id=sender_id or None, user_name=sender_id or None,
|
||||
message_id=msg_id)
|
||||
event = MessageEvent(
|
||||
text=text, message_type=message_type, source=source, raw_message=payload, message_id=msg_id, media_urls=media_urls, media_types=media_types,
|
||||
reply_to_message_id=f"quote:{msg_id}" if has_reply_context else None, reply_to_text=reply_text if has_reply_context else None, timestamp=datetime.now(tz=timezone.utc),
|
||||
|
||||
@@ -827,7 +827,8 @@ class WhatsAppAdapter(WhatsAppBehaviorMixin, BasePlatformAdapter):
|
||||
return None
|
||||
msg_type = self._classify_bridge_message(data)
|
||||
source = self.build_source(chat_id=data.get("chatId", ""), chat_name=data.get("chatName"), chat_type="group" if data.get("isGroup", False) else "dm",
|
||||
user_id=data.get("senderId"), user_name=data.get("senderName"))
|
||||
user_id=data.get("senderId"), user_name=data.get("senderName"),
|
||||
message_id=data.get("messageId"))
|
||||
cached_urls, media_types = await self._collect_bridge_media(data, msg_type)
|
||||
body = data.get("body", "")
|
||||
if data.get("isGroup"):
|
||||
|
||||
Reference in New Issue
Block a user