mirror of
https://github.com/openmax-server/server.git
synced 2026-05-23 20:11:41 +03:00
255 lines
12 KiB
Python
255 lines
12 KiB
Python
import json
|
||
import pydantic
|
||
from classes.baseprocessor import BaseProcessor
|
||
from oneme.models import (
|
||
SearchUsersPayloadModel,
|
||
SearchChatsPayloadModel,
|
||
SearchByPhonePayloadModel
|
||
)
|
||
|
||
|
||
class SearchProcessors(BaseProcessor):
|
||
async def contact_info(self, payload, seq, writer, senderId):
|
||
"""Поиск пользователей по ID"""
|
||
# Валидируем данные пакета
|
||
try:
|
||
SearchUsersPayloadModel.model_validate(payload)
|
||
except pydantic.ValidationError as error:
|
||
self.logger.error(f"Возникли ошибки при валидации пакета: {error}")
|
||
await self._send_error(seq, self.opcodes.CONTACT_INFO, self.error_types.INVALID_PAYLOAD, writer)
|
||
return
|
||
|
||
# Итоговый список пользователей
|
||
users = []
|
||
|
||
# ID пользователей, которые нам предстоит найти
|
||
contactIds = payload.get("contactIds")
|
||
|
||
# Ищем пользователей в бд
|
||
async with self.db_pool.acquire() as conn:
|
||
async with conn.cursor() as cursor:
|
||
for contactId in contactIds:
|
||
await cursor.execute("SELECT * FROM users WHERE id = %s", (contactId,))
|
||
user = await cursor.fetchone()
|
||
|
||
# Если такой пользователь есть, добавляем его в список
|
||
if user:
|
||
# Аватарка с биографией
|
||
photoId = None if not user.get("avatar_id") else int(user.get("avatar_id"))
|
||
avatar_url = None if not photoId else self.config.avatar_base_url + photoId
|
||
description = None if not user.get("description") else user.get("description")
|
||
|
||
# Получаем данные контакта
|
||
await cursor.execute(
|
||
"SELECT * FROM contacts WHERE owner_id = %s AND contact_id = %s",
|
||
(senderId, contactId),
|
||
)
|
||
contact_row = await cursor.fetchone()
|
||
custom_firstname = contact_row.get("custom_firstname") if contact_row else None
|
||
custom_lastname = contact_row.get("custom_lastname") if contact_row else None
|
||
blocked = bool(contact_row.get("is_blocked")) if contact_row else False
|
||
|
||
# Генерируем профиль
|
||
users.append(
|
||
self.tools.generate_profile(
|
||
id=user.get("id"),
|
||
phone=int(user.get("phone")),
|
||
avatarUrl=avatar_url,
|
||
photoId=photoId,
|
||
updateTime=int(user.get("updatetime")),
|
||
firstName=user.get("firstname"),
|
||
lastName=user.get("lastname"),
|
||
options=json.loads(user.get("options")),
|
||
description=description,
|
||
accountStatus=int(user.get("accountstatus")),
|
||
profileOptions=json.loads(user.get("profileoptions")),
|
||
includeProfileOptions=False,
|
||
username=user.get("username"),
|
||
custom_firstname=custom_firstname,
|
||
custom_lastname=custom_lastname,
|
||
blocked=blocked,
|
||
)
|
||
)
|
||
|
||
# Создаем данные пакета
|
||
payload = {
|
||
"contacts": users
|
||
}
|
||
|
||
# Создаем пакет
|
||
response = self.proto.pack_packet(
|
||
cmd=self.proto.CMD_OK, seq=seq, opcode=self.opcodes.CONTACT_INFO, payload=payload
|
||
)
|
||
|
||
# Отправляем
|
||
await self._send(writer, response)
|
||
|
||
async def contact_info_by_phone(self, payload, seq, writer, senderId):
|
||
"""Поиск по номеру телефона"""
|
||
# Валидируем данные пакета
|
||
try:
|
||
SearchByPhonePayloadModel.model_validate(payload)
|
||
except Exception as e:
|
||
await self._send_error(seq, self.opcodes.CONTACT_INFO_BY_PHONE, self.error_types.INVALID_PAYLOAD, writer)
|
||
return
|
||
|
||
# Ищем пользователя в бд
|
||
async with self.db_pool.acquire() as conn:
|
||
async with conn.cursor() as cursor:
|
||
await cursor.execute("SELECT * FROM users WHERE phone = %s", (int(payload.get("phone")),))
|
||
user = await cursor.fetchone()
|
||
|
||
# Если пользователь не найден, отправляем ошибку
|
||
if not user:
|
||
await self._send_error(seq, self.opcodes.CONTACT_INFO_BY_PHONE, self.error_types.USER_NOT_FOUND, writer)
|
||
return
|
||
|
||
# ID чата
|
||
chatId = senderId ^ user.get("id")
|
||
|
||
# Ищем диалог в бд
|
||
await cursor.execute("SELECT * FROM chats WHERE id = %s", (chatId,))
|
||
chat = await cursor.fetchone()
|
||
|
||
# Если диалога нет - создаем
|
||
if not chat:
|
||
await cursor.execute(
|
||
"INSERT INTO chats (id, owner, type) VALUES (%s, %s, %s)",
|
||
(chatId, senderId, "DIALOG")
|
||
)
|
||
|
||
# Добавляем участников в таблицу chat_participants
|
||
participants = [int(senderId), int(user.get("id"))]
|
||
|
||
for user_id in participants:
|
||
await cursor.execute(
|
||
"INSERT INTO chat_participants (chat_id, user_id) VALUES (%s, %s)",
|
||
(chatId, user_id)
|
||
)
|
||
|
||
# Аватарка с биографией
|
||
photoId = None if not user.get("avatar_id") else int(user.get("avatar_id"))
|
||
avatar_url = None if not photoId else self.config.avatar_base_url + photoId
|
||
description = None if not user.get("description") else user.get("description")
|
||
|
||
# Получаем данные контакта
|
||
async with self.db_pool.acquire() as conn:
|
||
async with conn.cursor() as cursor:
|
||
await cursor.execute(
|
||
"SELECT * FROM contacts WHERE owner_id = %s AND contact_id = %s",
|
||
(senderId, user.get("id")),
|
||
)
|
||
contact_row = await cursor.fetchone()
|
||
custom_firstname = contact_row.get("custom_firstname") if contact_row else None
|
||
custom_lastname = contact_row.get("custom_lastname") if contact_row else None
|
||
blocked = bool(contact_row.get("is_blocked")) if contact_row else False
|
||
|
||
# Генерируем профиль
|
||
profile = self.tools.generate_profile(
|
||
id=user.get("id"),
|
||
phone=int(user.get("phone")),
|
||
avatarUrl=avatar_url,
|
||
photoId=photoId,
|
||
updateTime=int(user.get("updatetime")),
|
||
firstName=user.get("firstname"),
|
||
lastName=user.get("lastname"),
|
||
options=json.loads(user.get("options")),
|
||
description=description,
|
||
accountStatus=int(user.get("accountstatus")),
|
||
profileOptions=json.loads(user.get("profileoptions")),
|
||
includeProfileOptions=False,
|
||
username=user.get("username"),
|
||
custom_firstname=custom_firstname,
|
||
custom_lastname=custom_lastname,
|
||
blocked=blocked,
|
||
)
|
||
|
||
# Создаем данные пакета
|
||
payload = {
|
||
"contact": profile
|
||
}
|
||
|
||
# Создаем пакет
|
||
response = self.proto.pack_packet(
|
||
cmd=self.proto.CMD_OK, seq=seq, opcode=self.opcodes.CONTACT_INFO_BY_PHONE, payload=payload
|
||
)
|
||
|
||
# Отправляем
|
||
await self._send(writer, response)
|
||
|
||
async def chat_info(self, payload, seq, writer, senderId):
|
||
"""Поиск чатов по ID"""
|
||
# Валидируем данные пакета
|
||
try:
|
||
SearchChatsPayloadModel.model_validate(payload)
|
||
except pydantic.ValidationError as error:
|
||
self.logger.error(f"Возникли ошибки при валидации пакета: {error}")
|
||
await self._send_error(seq, self.opcodes.CHAT_INFO, self.error_types.INVALID_PAYLOAD, writer)
|
||
return
|
||
|
||
# Итоговый список чатов
|
||
chats = []
|
||
|
||
# ID чатов, которые нам предстоит найти
|
||
chatIds = payload.get("chatIds")
|
||
|
||
# Ищем чаты в бд
|
||
async with self.db_pool.acquire() as conn:
|
||
async with conn.cursor() as cursor:
|
||
for chatId in chatIds:
|
||
if chatId != 0:
|
||
await cursor.execute("SELECT * FROM chats WHERE id = %s", (chatId,))
|
||
chat = await cursor.fetchone()
|
||
|
||
if chat:
|
||
# Проверяем, является ли пользователь участником чата
|
||
participants = await self.tools.get_chat_participants(chatId, self.db_pool)
|
||
# (в max нельзя смотреть и отправлять сообщения в чат, в котором ты не участник, в отличие от tg (например, комментарии в каналах),
|
||
# так что надо тоже так делать)
|
||
if int(senderId) not in participants:
|
||
continue
|
||
|
||
# Получаем последнее сообщение из чата
|
||
message, messageTime = await self.tools.get_last_message(
|
||
chatId, self.db_pool, protocol_type=self.type
|
||
)
|
||
|
||
# Добавляем чат в список
|
||
chats.append(
|
||
self.tools.generate_chat(
|
||
chatId, chat.get("owner"),
|
||
chat.get("type"), participants,
|
||
message, messageTime
|
||
)
|
||
)
|
||
else:
|
||
# Получаем последнее сообщение из избранного
|
||
message, messageTime = await self.tools.get_last_message(
|
||
-senderId, self.db_pool, protocol_type=self.type
|
||
)
|
||
|
||
# ID избранного для клиента
|
||
chatId = senderId ^ senderId
|
||
|
||
# Добавляем чат в список
|
||
chats.append(
|
||
self.tools.generate_chat(
|
||
chatId, senderId,
|
||
"DIALOG", [senderId],
|
||
message, messageTime
|
||
)
|
||
)
|
||
|
||
# Создаем данные пакета
|
||
payload = {
|
||
"chats": chats
|
||
}
|
||
|
||
# Собираем пакет
|
||
response = self.proto.pack_packet(
|
||
cmd=self.proto.CMD_OK, seq=seq, opcode=self.opcodes.CHAT_INFO, payload=payload
|
||
)
|
||
|
||
# Отправляем
|
||
await self._send(writer, response)
|