From 861b75eb1c842df70389b1422fdddc4402bc7412 Mon Sep 17 00:00:00 2001 From: zavolo Date: Sun, 10 May 2026 22:27:42 +0300 Subject: [PATCH] =?UTF-8?q?MAX:=20bootstrap-=D0=B8=D1=81=D1=82=D0=BE=D1=80?= =?UTF-8?q?=D0=B8=D1=8F=20=D0=B2=20LOGIN=20=E2=80=94=20=D0=BA=D0=BB=D0=B8?= =?UTF-8?q?=D0=B5=D0=BD=D1=82=20=D0=BF=D0=B5=D1=80=D0=B5=D1=81=D1=82=D0=B0?= =?UTF-8?q?=D0=BB=20=D0=B4=D1=83=D0=BC=D0=B0=D1=82=D1=8C=20=D1=87=D1=82?= =?UTF-8?q?=D0=BE=20=D0=B2=D1=81=D1=91=20=D1=83=D0=B6=D0=B5=20=D1=81=D0=B8?= =?UTF-8?q?=D0=BD=D0=BA=D0=B0=D0=BD=D1=83=D0=BB=D0=BE=D1=81=D1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit В ответе LOGIN сервер слал messages: {} и chatMarker: 0. Десктопный клиент в этом случае считает, что локальная история уже синхронизирована со старого запуска, и НЕ отправляет CHAT_HISTORY (49) при открытии чата. В окне видно только lastMessage из chats[], а вся реальная переписка — ничерта. - src/common/tools.py: collect_bootstrap_history(chatIds, ...) — собирает карту {chatId: [последние N сообщений]}, в т.ч. избранное под клиентским id = senderId ^ senderId. - src/oneme/processors/auth.py: подсовываем эту карту в payload.messages, chatMarker = текущее время вместо 0. --- src/common/tools.py | 38 ++++++++++++++++++++++++++++++++++++ src/oneme/processors/auth.py | 17 ++++++++++++++-- 2 files changed, 53 insertions(+), 2 deletions(-) diff --git a/src/common/tools.py b/src/common/tools.py index 1b322f3..9ad93c8 100644 --- a/src/common/tools.py +++ b/src/common/tools.py @@ -429,6 +429,44 @@ class Tools: # Возвращаем айдишки return int(message_id), int(last_message_id), message_time + async def collect_bootstrap_history( + self, chatIds, db_pool, senderId, protocol_type="mobile", limit=50, include_favourites=True + ): + """Собирает карту {chatId: [messages...]} для bootstrap-pre-fetch в LOGIN. + + Десктопный MAX в ответе LOGIN ждёт поле `messages` как карту чат→история. + Если карта пустая — клиент полагает, что у него уже есть локальная + история и НЕ запрашивает CHAT_HISTORY (49). В итоге в окне чата + видно только lastMessage из chats[]. + """ + result = {} + + async def _fetch(chat_db_id, key_for_client): + async with db_pool.acquire() as conn: + async with conn.cursor() as cursor: + await cursor.execute( + "SELECT * FROM `messages` WHERE chat_id = %s ORDER BY time DESC LIMIT %s", + (chat_db_id, limit), + ) + rows = await cursor.fetchall() + + if not rows: + return + + messages = [self.build_message_dict(row, protocol_type) for row in rows] + messages.sort(key=lambda m: m["time"]) + result[key_for_client] = messages + + for chatId in chatIds: + await _fetch(chatId, chatId) + + if include_favourites: + # Избранное: в БД хранится как chat_id = -senderId, + # но клиенту отдаётся под id = senderId ^ senderId (= 0) + await _fetch(-senderId, senderId ^ senderId) + + return result + async def get_last_message(self, chatId, db_pool, protocol_type="mobile"): """Получение последнего сообщения в чате""" async with db_pool.acquire() as db_connection: diff --git a/src/oneme/processors/auth.py b/src/oneme/processors/auth.py index da646c1..4120200 100644 --- a/src/oneme/processors/auth.py +++ b/src/oneme/processors/auth.py @@ -603,11 +603,24 @@ class AuthProcessors(BaseProcessor): username=user.get("username"), ) + # Список ID чатов до того как generate_chats затрёт переменную + chat_ids_for_history = list(chats) + # Генерируем список чатов chats = await self.tools.generate_chats( chats, self.db_pool, user.get("id"), protocol_type=self.type ) + # Bootstrap-история: карта {chatId: [messages]}. + # Без неё десктопный MAX считает, что локальная история уже + # синхронизирована, и не запрашивает CHAT_HISTORY (49). + bootstrap_messages = await self.tools.collect_bootstrap_history( + chat_ids_for_history, + self.db_pool, + user.get("id"), + protocol_type=self.type, + ) + # Генерируем список контактов contacts = await self.tools.collect_user_contacts( user.get("id"), self.db_pool, self.config.avatar_base_url @@ -621,8 +634,8 @@ class AuthProcessors(BaseProcessor): payload = { "profile": profile, "chats": chats, - "chatMarker": 0, - "messages": {}, + "chatMarker": int(time.time() * 1000), + "messages": bootstrap_messages, "contacts": contacts, "presence": presence, "config": {