import logging logger = logging.getLogger(__name__) MAX_HISTORY_FETCH_LIMIT = 100 MAX_HISTORY_BODY_CHARS = 2000 async def fetch_chat_history( client, chat_guid: str, limit: int = 50, before_guid: str | None = None, ) -> list[dict]: params = {"limit": min(limit, MAX_HISTORY_FETCH_LIMIT)} if before_guid: params["before"] = before_guid for path, extra_params in _history_api_paths(chat_guid): merged = {**params, **extra_params} try: resp = await client.get(path, params=merged) if resp.status_code < 300: data = _extract_message_list(resp.json()) return [_normalize_history_message(m) for m in data] except Exception as e: logger.debug("History fetch failed for %s: %s", path, e) continue return [] def _history_api_paths(chat_guid: str) -> list[tuple[str, dict]]: return [ (f"/api/v1/chat/{chat_guid}/messages", {"sort": "DESC"}), ("/api/v1/messages", {"chatGuid": chat_guid}), (f"/api/v1/chat/{chat_guid}/message", {}), ] def _extract_message_list(response_data) -> list[dict]: if isinstance(response_data, list): return response_data if isinstance(response_data, dict): for key in ("data", "messages", "results"): val = response_data.get(key) if isinstance(val, list): return val return [] def _normalize_history_message(msg: dict) -> dict: body = msg.get("text", msg.get("message", msg.get("body", ""))) return { "guid": msg.get("guid", ""), "text": body[:MAX_HISTORY_BODY_CHARS], "sender": msg.get("sender", msg.get("handle", {}).get("id", "")), "date": msg.get("dateDelivered", msg.get("date_delivered", msg.get("date", 0))), "is_from_me": msg.get("isFromMe", msg.get("is_from_me", False)), "chat_guid": msg.get("chatGuid", msg.get("chat_guid", "")), "attachments": msg.get("attachments", []), }