|
15 | 15 | import json |
16 | 16 | import os |
17 | 17 | import time |
18 | | -from typing import Dict, List, Literal, Optional, Union |
| 18 | +from datetime import datetime, timezone |
| 19 | +from typing import Any, Dict, List, Literal, Optional, Union |
19 | 20 |
|
20 | 21 | import requests |
21 | 22 |
|
@@ -118,6 +119,78 @@ def _get_tenant_http_headers(self) -> Dict[str, str]: |
118 | 119 | f"Failed to get tenant access token: {result.get('msg')}" |
119 | 120 | ) |
120 | 121 |
|
| 122 | + def _convert_timestamp(self, ts: Any) -> str: |
| 123 | + r"""Convert millisecond timestamp to readable datetime string. |
| 124 | +
|
| 125 | + Args: |
| 126 | + ts: Timestamp value (can be string or int, in milliseconds). |
| 127 | +
|
| 128 | + Returns: |
| 129 | + str: ISO format datetime string, or original value if conversion |
| 130 | + fails. |
| 131 | + """ |
| 132 | + try: |
| 133 | + ts_int = int(ts) |
| 134 | + # Convert milliseconds to seconds |
| 135 | + dt = datetime.fromtimestamp(ts_int / 1000, tz=timezone.utc) |
| 136 | + return dt.strftime("%Y-%m-%d %H:%M:%S UTC") |
| 137 | + except (ValueError, TypeError, OSError): |
| 138 | + return str(ts) |
| 139 | + |
| 140 | + def _process_message_items( |
| 141 | + self, items: List[Dict[str, Any]] |
| 142 | + ) -> List[Dict[str, Any]]: |
| 143 | + r"""Process message items to agent-friendly format. |
| 144 | +
|
| 145 | + Args: |
| 146 | + items: List of message items from API response. |
| 147 | +
|
| 148 | + Returns: |
| 149 | + List[Dict[str, Any]]: Simplified items with only essential fields. |
| 150 | + """ |
| 151 | + processed = [] |
| 152 | + for item in items: |
| 153 | + # Parse message content |
| 154 | + text = "" |
| 155 | + body = item.get("body", {}) |
| 156 | + content = body.get("content", "") |
| 157 | + if content: |
| 158 | + try: |
| 159 | + content_obj = json.loads(content) |
| 160 | + if "text" in content_obj: |
| 161 | + text = content_obj["text"] |
| 162 | + elif "template" in content_obj: |
| 163 | + # System message: render template |
| 164 | + tpl = content_obj["template"] |
| 165 | + for key in ["from_user", "to_chatters"]: |
| 166 | + val = content_obj.get(key, []) |
| 167 | + if val: |
| 168 | + tpl = tpl.replace( |
| 169 | + "{" + key + "}", ", ".join(val) |
| 170 | + ) |
| 171 | + else: |
| 172 | + tpl = tpl.replace("{" + key + "}", "") |
| 173 | + text = tpl.strip() |
| 174 | + elif "image_key" in content_obj: |
| 175 | + text = f"[Image: {content_obj['image_key']}]" |
| 176 | + elif "file_key" in content_obj: |
| 177 | + text = f"[File: {content_obj['file_key']}]" |
| 178 | + except (json.JSONDecodeError, TypeError): |
| 179 | + text = content |
| 180 | + |
| 181 | + # Build simplified message |
| 182 | + sender = item.get("sender", {}) |
| 183 | + msg = { |
| 184 | + "message_id": item.get("message_id"), |
| 185 | + "msg_type": item.get("msg_type"), |
| 186 | + "text": text, |
| 187 | + "time": self._convert_timestamp(item.get("create_time", "")), |
| 188 | + "sender_id": sender.get("id") or None, |
| 189 | + "sender_type": sender.get("sender_type") or None, |
| 190 | + } |
| 191 | + processed.append(msg) |
| 192 | + return processed |
| 193 | + |
121 | 194 | def lark_list_chats( |
122 | 195 | self, |
123 | 196 | sort_type: Literal["ByCreateTimeAsc", "ByActiveTimeDesc"] = ( |
@@ -174,7 +247,18 @@ def lark_list_chats( |
174 | 247 | "code": result.get("code"), |
175 | 248 | } |
176 | 249 |
|
177 | | - return result |
| 250 | + # Simplify chat items |
| 251 | + data = result.get("data", {}) |
| 252 | + items = data.get("items", []) |
| 253 | + simplified = [ |
| 254 | + {"chat_id": c.get("chat_id"), "name": c.get("name", "")} |
| 255 | + for c in items |
| 256 | + ] |
| 257 | + return { |
| 258 | + "chats": simplified, |
| 259 | + "has_more": data.get("has_more", False), |
| 260 | + "page_token": data.get("page_token", ""), |
| 261 | + } |
178 | 262 |
|
179 | 263 | except Exception as e: |
180 | 264 | logger.error(f"Error listing chats: {e}") |
@@ -259,7 +343,14 @@ def lark_get_chat_messages( |
259 | 343 | "code": result.get("code"), |
260 | 344 | } |
261 | 345 |
|
262 | | - return result |
| 346 | + # Process and simplify messages |
| 347 | + data = result.get("data", {}) |
| 348 | + items = data.get("items", []) |
| 349 | + return { |
| 350 | + "messages": self._process_message_items(items), |
| 351 | + "has_more": data.get("has_more", False), |
| 352 | + "page_token": data.get("page_token", ""), |
| 353 | + } |
263 | 354 |
|
264 | 355 | except Exception as e: |
265 | 356 | logger.error(f"Error getting chat messages: {e}") |
@@ -370,7 +461,12 @@ def lark_get_message_resource_key( |
370 | 461 | } |
371 | 462 |
|
372 | 463 | data = result.get("data", {}) or {} |
373 | | - body = data.get("body", {}) or {} |
| 464 | + items = data.get("items", []) or [] |
| 465 | + if not items: |
| 466 | + return {"error": "No message found."} |
| 467 | + # Get the first message item |
| 468 | + item = items[0] |
| 469 | + body = item.get("body", {}) or {} |
374 | 470 | content = body.get("content", "") |
375 | 471 | if not content: |
376 | 472 | return {"error": "Message content is empty."} |
|
0 commit comments