mirror of
https://github.com/openmax-server/server.git
synced 2026-05-24 12:31:42 +03:00
MAX: история таки заработала — cid/link/reactionInfo обязательны в схеме
Десктопный MAX подключается через TCP (mobile-протокол) и парсит
msgpack по фиксированной схеме. Если в сообщении выпадает любое из
полей — клиент молча обрывает соединение. После 87cfc19 как раз
такие условные `if elements: ...` / `if link: ...` (а link и
reaction_info там всегда были `{}`, то есть falsy) вырезали поля
из ответа CHAT_HISTORY и MSG_SEND, чем и сломали историю.
- src/common/tools.py: новый build_message_dict() — единая сборка
тела сообщения, где все поля (id, cid, time, type, sender, text,
attaches, elements, reactionInfo, link) присутствуют ВСЕГДА.
get_last_message переписан через него.
- src/oneme/processors/history.py: chat_history использует
build_message_dict вместо ручной логики с условными if-ками.
- src/oneme/processors/messages.py: msg_send.bodyMessage теперь
отдает cid / reactionInfo / link даже пустыми и приводит id
к int для mobile, str для web.
Цепная польза: auth.py LOGIN bootstrap (через generate_chats →
get_last_message) и search.py тоже теперь шлют корректную схему.
This commit is contained in:
@@ -10,6 +10,39 @@ class Tools:
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def build_message_dict(self, row, protocol_type="mobile"):
|
||||||
|
"""Унифицированная сборка тела сообщения для отправки клиенту.
|
||||||
|
|
||||||
|
Десктоп MAX (TCP, protocol_type='mobile') и официальный
|
||||||
|
api.oneme.ru ожидают, что в сообщении будут ВСЕГДА присутствовать
|
||||||
|
поля cid / elements / link / reactionInfo, даже если они пустые.
|
||||||
|
Любое отсутствие поля приводит к тому, что клиент бросает соединение
|
||||||
|
при разборе msgpack-схемы (классическая регрессия из коммита 87cfc19).
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
attaches = json.loads(row.get("attaches") or "[]")
|
||||||
|
except (TypeError, ValueError):
|
||||||
|
attaches = []
|
||||||
|
try:
|
||||||
|
elements = json.loads(row.get("elements") or "[]")
|
||||||
|
except (TypeError, ValueError):
|
||||||
|
elements = []
|
||||||
|
|
||||||
|
message = {
|
||||||
|
"id": row.get("id") if protocol_type == "mobile" else str(row.get("id")),
|
||||||
|
"cid": int(row.get("cid") or 0),
|
||||||
|
"time": int(row.get("time")),
|
||||||
|
"type": row.get("type"),
|
||||||
|
"sender": row.get("sender"),
|
||||||
|
"text": row.get("text") or "",
|
||||||
|
"attaches": attaches if isinstance(attaches, list) else [],
|
||||||
|
"elements": elements if isinstance(elements, list) else [],
|
||||||
|
"reactionInfo": {},
|
||||||
|
"link": {},
|
||||||
|
}
|
||||||
|
|
||||||
|
return message
|
||||||
|
|
||||||
def generate_profile(
|
def generate_profile(
|
||||||
self,
|
self,
|
||||||
id=1,
|
id=1,
|
||||||
@@ -412,35 +445,8 @@ class Tools:
|
|||||||
if not row:
|
if not row:
|
||||||
return None, None
|
return None, None
|
||||||
|
|
||||||
message = {
|
|
||||||
"sender": row.get("sender"),
|
|
||||||
"id": row.get("id")
|
|
||||||
if protocol_type == "mobile"
|
|
||||||
else str(row.get("id")),
|
|
||||||
"time": int(row.get("time")),
|
|
||||||
"text": row.get("text"),
|
|
||||||
"type": row.get("type"),
|
|
||||||
"attaches": json.loads(row.get("attaches"))
|
|
||||||
}
|
|
||||||
|
|
||||||
elements = json.loads(row.get("elements"))
|
|
||||||
link = {}
|
|
||||||
reaction_info = {}
|
|
||||||
|
|
||||||
if elements:
|
|
||||||
message["elements"] = elements
|
|
||||||
|
|
||||||
if link:
|
|
||||||
message["link"] = link
|
|
||||||
|
|
||||||
if reaction_info:
|
|
||||||
message["reactionInfo"] = reaction_info
|
|
||||||
|
|
||||||
if protocol_type == "web":
|
|
||||||
message["cid"] = int(row.get("cid"))
|
|
||||||
|
|
||||||
# Возвращаем
|
# Возвращаем
|
||||||
return message, int(row.get("time"))
|
return self.build_message_dict(row, protocol_type), int(row.get("time"))
|
||||||
|
|
||||||
async def get_previous_message_id(self, chatId, db_pool, protocol_type="mobile"):
|
async def get_previous_message_id(self, chatId, db_pool, protocol_type="mobile"):
|
||||||
"""Получение ID предыдущего сообщения (второго с конца) в чате."""
|
"""Получение ID предыдущего сообщения (второго с конца) в чате."""
|
||||||
|
|||||||
@@ -59,35 +59,7 @@ class HistoryProcessors(BaseProcessor):
|
|||||||
result = await cursor.fetchall()
|
result = await cursor.fetchall()
|
||||||
|
|
||||||
for row in result:
|
for row in result:
|
||||||
# TODO: Сборку тела сообщения нужно вынести в отдельную функцию
|
messages.append(self.tools.build_message_dict(row, self.type))
|
||||||
message = {
|
|
||||||
"sender": row.get("sender"),
|
|
||||||
"id": row.get("id")
|
|
||||||
if self.type == "mobile"
|
|
||||||
else str(row.get("id")),
|
|
||||||
"time": int(row.get("time")),
|
|
||||||
"text": row.get("text"),
|
|
||||||
"type": row.get("type"),
|
|
||||||
"attaches": json.loads(row.get("attaches"))
|
|
||||||
}
|
|
||||||
|
|
||||||
elements = json.loads(row.get("elements"))
|
|
||||||
link = {}
|
|
||||||
reaction_info = {}
|
|
||||||
|
|
||||||
if elements:
|
|
||||||
message["elements"] = elements
|
|
||||||
|
|
||||||
if link:
|
|
||||||
message["link"] = link
|
|
||||||
|
|
||||||
if reaction_info:
|
|
||||||
message["reactionInfo"] = reaction_info
|
|
||||||
|
|
||||||
if self.type == "web":
|
|
||||||
message["cid"] = int(row.get("cid"))
|
|
||||||
|
|
||||||
messages.append(message)
|
|
||||||
if forward > 0:
|
if forward > 0:
|
||||||
await cursor.execute(
|
await cursor.execute(
|
||||||
"SELECT * FROM messages WHERE chat_id = %s AND time > %s ORDER BY time ASC LIMIT %s",
|
"SELECT * FROM messages WHERE chat_id = %s AND time > %s ORDER BY time ASC LIMIT %s",
|
||||||
@@ -97,35 +69,7 @@ class HistoryProcessors(BaseProcessor):
|
|||||||
result = await cursor.fetchall()
|
result = await cursor.fetchall()
|
||||||
|
|
||||||
for row in result:
|
for row in result:
|
||||||
# TODO: Сборку тела сообщения нужно вынести в отдельную функцию
|
messages.append(self.tools.build_message_dict(row, self.type))
|
||||||
message = {
|
|
||||||
"sender": row.get("sender"),
|
|
||||||
"id": row.get("id")
|
|
||||||
if self.type == "mobile"
|
|
||||||
else str(row.get("id")),
|
|
||||||
"time": int(row.get("time")),
|
|
||||||
"text": row.get("text"),
|
|
||||||
"type": row.get("type"),
|
|
||||||
"attaches": json.loads(row.get("attaches"))
|
|
||||||
}
|
|
||||||
|
|
||||||
elements = json.loads(row.get("elements"))
|
|
||||||
link = {}
|
|
||||||
reaction_info = {}
|
|
||||||
|
|
||||||
if elements:
|
|
||||||
message["elements"] = elements
|
|
||||||
|
|
||||||
if link:
|
|
||||||
message["link"] = link
|
|
||||||
|
|
||||||
if reaction_info:
|
|
||||||
message["reactionInfo"] = reaction_info
|
|
||||||
|
|
||||||
if self.type == "web":
|
|
||||||
message["cid"] = int(row.get("cid"))
|
|
||||||
|
|
||||||
messages.append(message)
|
|
||||||
|
|
||||||
# Сортируем сообщения по времени
|
# Сортируем сообщения по времени
|
||||||
messages.sort(key=lambda x: x["time"])
|
messages.sort(key=lambda x: x["time"])
|
||||||
|
|||||||
@@ -125,16 +125,21 @@ class MessagesProcessors(BaseProcessor):
|
|||||||
db_pool=self.db_pool
|
db_pool=self.db_pool
|
||||||
)
|
)
|
||||||
|
|
||||||
# Готовое тело сообщения
|
# Готовое тело сообщения. Поля cid / elements / reactionInfo / link
|
||||||
|
# должны присутствовать ВСЕГДА (даже пустые) — десктопный MAX
|
||||||
|
# ожидает фиксированную msgpack-схему и обрывает соединение
|
||||||
|
# при отсутствии любого из них (см. регрессию из 87cfc19).
|
||||||
bodyMessage = {
|
bodyMessage = {
|
||||||
"id": messageId,
|
"id": messageId if self.type == "mobile" else str(messageId),
|
||||||
|
"cid": int(cid or 0),
|
||||||
"time": messageTime,
|
"time": messageTime,
|
||||||
"type": "USER",
|
"type": "USER",
|
||||||
"sender": senderId,
|
"sender": senderId,
|
||||||
"cid": cid,
|
|
||||||
"text": text,
|
"text": text,
|
||||||
"attaches": attaches,
|
"attaches": attaches if isinstance(attaches, list) else [],
|
||||||
"elements": elements
|
"elements": elements if isinstance(elements, list) else [],
|
||||||
|
"reactionInfo": {},
|
||||||
|
"link": {},
|
||||||
}
|
}
|
||||||
|
|
||||||
# Отправляем событие всем участникам чата
|
# Отправляем событие всем участникам чата
|
||||||
|
|||||||
Reference in New Issue
Block a user