from __future__ import annotations import logging from datetime import datetime, timezone logger = logging.getLogger(__name__) def convert_webhook_to_message(payload: dict, account: dict) -> dict | None: inner = payload.get("payload", {}).get("object", {}) if not inner: logger.warning("Empty Zoom webhook payload") return None message_id = inner.get("id", "") sender_email = inner.get("sender", "") content = inner.get("message", "") channel_id = inner.get("channel_id", "") timestamp_str = inner.get("date_time", "") chat_type = inner.get("chat_type", "group") thread_root_id = inner.get("thread_root_message_id") or None files = inner.get("files", []) bot_user_id = account.get("bot_user_id", "") if sender_email == bot_user_id: logger.debug("Skipping self-sent message from bot: %s", message_id) return None timestamp = None try: timestamp = datetime.fromisoformat(timestamp_str.replace("Z", "+00:00")) except (ValueError, TypeError): timestamp = datetime.now(timezone.utc) was_mentioned = _check_bot_mentioned(content, account) kind = "direct" if chat_type == "1on1" else "group" media_urls = [] for f in files: url = f.get("download_url") or f.get("url") or f.get("href") if url: media_urls.append(url) return { "msg_id": message_id, "channel_type": "zoomchat", "account_id": account.get("account_id", ""), "content": content, "sender": { "id": sender_email, "display_name": sender_email, "kind": kind, "is_bot": False, "is_self": False, }, "group": {"id": channel_id, "name": channel_id, "kind": kind} if kind == "group" else None, "timestamp": timestamp, "was_mentioned": was_mentioned, "message_thread_id": thread_root_id, "reply_to_id": thread_root_id, "media_urls": media_urls, "raw_payload": payload, } def _check_bot_mentioned(content: str, account: dict) -> bool: if not content: return False bot_email = account.get("bot_user_email", "") if bot_email and bot_email.lower() in content.lower(): return True return True