Просмотр исходного кода

Resolve chat sender account IDs to display names in service clients

Airbnb: parse thread participants in get_thread() and map each message's
sender_account_id to a real name (Paul, Zach, etc.), falling back to
'Airbnb' for system/service accounts. Booking.com: translate GUEST/PARTNER
role strings to 'Guest'/'Host' at parse time via _SENDER_LABELS.

Both API and MCP consumers prefer sender_name over the raw sender field.
Frontend chatSenderLabel simplified to a passthrough — no service-specific
logic needed there.
ZiB 4 месяцев назад
Родитель
Сommit
5f15855512

+ 1 - 1
room_cal/api/_routes/chat.py

@@ -13,7 +13,7 @@ def _normalize_message(m) -> dict:
     'id': m.id,
     'created_at': getattr(m, 'created_at_ms', None) or getattr(m, 'created_at', None),
     'body': m.body,
-    'sender': getattr(m, 'sender_account_id', None) or getattr(m, 'sender', None),
+    'sender': getattr(m, 'sender_name', None) or getattr(m, 'sender', None),
   }
   translated = getattr(m, 'body_translated', None)
   if translated is not None:

+ 1 - 1
room_cal/mcp/__init__.py

@@ -230,7 +230,7 @@ async def get_chat_thread(service_key: str, chat_id: str) -> dict:
         'id': m.id,
         'created_at': getattr(m, 'created_at_ms', None) or getattr(m, 'created_at', None),
         'body': m.body,
-        'sender': getattr(m, 'sender_account_id', None) or getattr(m, 'sender', None),
+        'sender': getattr(m, 'sender_name', None) or getattr(m, 'sender', None),
       }
       for m in thread.messages
     ],

+ 16 - 10
room_cal/service_api/_airbnb.py

@@ -29,6 +29,7 @@ class AirbnbMessage:
   body: str | None      # None for non-text messages (photos, system events, etc.)
   body_translated: str | None  # Airbnb AI translation; None when not provided
   sender_account_id: str
+  sender_name: str | None = None  # resolved from thread participants; None only if resolution failed
 
 
 @dataclass
@@ -439,20 +440,25 @@ class _AirbnbClient:
       },
       f'https://www.airbnb.com/messages/{thread_id}',
     )
-    raw_messages = (
-      resp.get('data', {}).get('threadData', {})
-          .get('messageData', {}).get('messages', [])
-    )
-    messages = [
-      AirbnbMessage(
+    thread_data = resp.get('data', {}).get('threadData', {})
+    participants: dict[str, str] = {}
+    for edge in thread_data.get('participants', {}).get('edges', []):
+      node = edge.get('node', {})
+      account_id = node.get('accountId', '')
+      name = (node.get('enrichedParticipantInfo') or {}).get('name', '')
+      if account_id and name:
+        participants[account_id] = name
+    messages = []
+    for m in thread_data.get('messageData', {}).get('messages', []):
+      aid = (m.get('account') or {}).get('accountId', '')
+      messages.append(AirbnbMessage(
         id=m['id'],
         created_at_ms=m['createdAtMs'],
         body=(((m.get('hydratedContent') or {}).get('content') or {}).get('body')),
         body_translated=(((m.get('hydratedContent') or {}).get('content') or {}).get('bodyTranslated')),
-        sender_account_id=(m.get('account') or {}).get('accountId', ''),
-      )
-      for m in raw_messages
-    ]
+        sender_account_id=aid,
+        sender_name=participants.get(aid, 'Airbnb'),
+      ))
     return AirbnbThread(thread_id=thread_id, messages=messages)
 
   async def send_message(self, thread_id: str, body: str) -> None:

+ 2 - 1
room_cal/service_api/_booking.py

@@ -26,6 +26,7 @@ def _is_past(d: str) -> bool:
 
 _BASE = 'https://admin.booking.com'
 _AUTH_HINT = 'refresh-creds'
+_SENDER_LABELS: dict[str, str] = {'GUEST': 'Guest', 'PARTNER': 'Host'}
 
 _UPDATE_MUTATION = """mutation updateRoomDateMutation($input: PartnerAvailabilityUpdateInput) {
   partnerAvailabilityMutations {
@@ -625,7 +626,7 @@ class _BookingClient:
         id=m['messageId'],
         created_at=m['created'],
         body=body,
-        sender=(m.get('sender') or {}).get('participantType', ''),
+        sender=_SENDER_LABELS.get((m.get('sender') or {}).get('participantType', ''), 'Unknown'),
         body_translated=body_translated,
       ))
     return BookingThread(reservation_id=reservation_id, messages=messages, is_reply_needed=is_reply_needed)

+ 1 - 8
room_cal/vue/calendar.html

@@ -1608,14 +1608,7 @@ createApp({
     });
 
     function chatSenderLabel(sender) {
-      if (!sender) return 'Unknown';
-      if (sender === 'PARTNER') return 'Host';
-      if (sender === 'GUEST') return 'Guest';
-      // Airbnb: numeric account ID compared against host_account_id
-      const sel = selection.value;
-      const svc = sel?.service ? services.value.find(s => s.key === sel.service) : null;
-      if (svc?.host_account_id && String(sender) === String(svc.host_account_id)) return 'Host';
-      return 'Guest';
+      return sender || 'Unknown';
     }
 
     function scrollChatToBottom() {