MAX: добавление контакта по номеру телефона

This commit is contained in:
Alexey Polyakov
2026-05-09 15:50:47 +03:00
parent ac40cc53c9
commit dff6937da8
5 changed files with 132 additions and 1 deletions

View File

@@ -44,6 +44,7 @@ class Opcodes:
CONTACT_MUTUAL = 38 CONTACT_MUTUAL = 38
CONTACT_PHOTOS = 39 CONTACT_PHOTOS = 39
CONTACT_SORT = 40 CONTACT_SORT = 40
CONTACT_ADD_BY_PHONE = 41
CONTACT_VERIFY = 42 CONTACT_VERIFY = 42
REMOVE_CONTACT_PHOTO = 43 REMOVE_CONTACT_PHOTO = 43
CHAT_INFO = 48 CHAT_INFO = 48

View File

@@ -145,6 +145,10 @@ class ContactListPayloadModel(pydantic.BaseModel):
class ContactPresencePayloadModel(pydantic.BaseModel): class ContactPresencePayloadModel(pydantic.BaseModel):
contactIds: list contactIds: list
class ContactAddByPhonePayloadModel(pydantic.BaseModel):
phone: str
firstName: str
class ContactUpdatePayloadModel(pydantic.BaseModel): class ContactUpdatePayloadModel(pydantic.BaseModel):
action: str action: str
contactId: int contactId: int

View File

@@ -2,7 +2,7 @@ import pydantic
import json import json
import time import time
from classes.baseprocessor import BaseProcessor from classes.baseprocessor import BaseProcessor
from oneme.models import ContactListPayloadModel, ContactPresencePayloadModel, ContactUpdatePayloadModel from oneme.models import ContactAddByPhonePayloadModel, ContactListPayloadModel, ContactPresencePayloadModel, ContactUpdatePayloadModel
class ContactsProcessors(BaseProcessor): class ContactsProcessors(BaseProcessor):
async def contact_list(self, payload, seq, writer, userId): async def contact_list(self, payload, seq, writer, userId):
@@ -112,6 +112,23 @@ class ContactsProcessors(BaseProcessor):
"INSERT INTO contacts (owner_id, contact_id, custom_firstname, custom_lastname, is_blocked) VALUES (%s, %s, %s, %s, FALSE)", "INSERT INTO contacts (owner_id, contact_id, custom_firstname, custom_lastname, is_blocked) VALUES (%s, %s, %s, %s, FALSE)",
(userId, contactId, firstName, lastName) (userId, contactId, firstName, lastName)
) )
# Создаем диалог, если его нет
chatId = userId ^ contactId
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, userId, "DIALOG")
)
for uid in [int(userId), int(contactId)]:
await cursor.execute(
"INSERT INTO chat_participants (chat_id, user_id) VALUES (%s, %s)",
(chatId, uid)
)
# а если уже существует, отправляем ошибку # а если уже существует, отправляем ошибку
else: else:
await self._send_error(seq, self.opcodes.CONTACT_UPDATE, self.error_types.CONTACT_ALREADY_ADDED, writer) await self._send_error(seq, self.opcodes.CONTACT_UPDATE, self.error_types.CONTACT_ALREADY_ADDED, writer)
@@ -277,6 +294,97 @@ class ContactsProcessors(BaseProcessor):
await self._send(writer, packet) await self._send(writer, packet)
async def contact_add_by_phone(self, payload, seq, writer, userId):
"""Добавление контакта по номеру телефона"""
# Валидируем данные пакета
try:
ContactAddByPhonePayloadModel.model_validate(payload)
except pydantic.ValidationError as error:
self.logger.error(f"Возникли ошибки при валидации пакета: {error}")
await self._send_error(seq, self.opcodes.CONTACT_ADD_BY_PHONE, self.error_types.INVALID_PAYLOAD, writer)
return
phone = payload.get("phone")
firstName = payload.get("firstName")
lastName = payload.get("lastName")
# Ищем пользователя по номеру телефона
async with self.db_pool.acquire() as conn:
async with conn.cursor() as cursor:
await cursor.execute("SELECT * FROM users WHERE phone = %s", (int(phone),))
user = await cursor.fetchone()
if not user:
await self._send_error(seq, self.opcodes.CONTACT_ADD_BY_PHONE, self.error_types.CONTACT_NOT_FOUND, writer)
return
contactId = user.get("id")
# Проверяем, не добавлен ли уже контакт
await cursor.execute(
"SELECT * FROM contacts WHERE owner_id = %s AND contact_id = %s",
(userId, contactId)
)
existing_contact = await cursor.fetchone()
is_new = existing_contact is None
if is_new:
# Добавляем контакт
await cursor.execute(
"INSERT INTO contacts (owner_id, contact_id, custom_firstname, custom_lastname) VALUES (%s, %s, %s, %s)",
(userId, contactId, firstName, lastName)
)
# Создаем диалог, если его нет
chatId = userId ^ contactId
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, userId, "DIALOG")
)
for uid in [int(userId), int(contactId)]:
await cursor.execute(
"INSERT INTO chat_participants (chat_id, user_id) VALUES (%s, %s)",
(chatId, uid)
)
# Генерируем профиль
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 + str(photoId)
contact = 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")),
accountStatus=int(user.get("accountstatus")),
description=user.get("description"),
includeProfileOptions=False,
custom_firstname=firstName,
custom_lastname=lastName,
username=user.get("username"),
)
response_payload = {
"new": is_new,
"contact": contact
}
packet = self.proto.pack_packet(
cmd=self.proto.CMD_OK, seq=seq, opcode=self.opcodes.CONTACT_ADD_BY_PHONE, payload=response_payload
)
await self._send(writer, packet)
async def contact_presence(self, payload, seq, writer): async def contact_presence(self, payload, seq, writer):
"""Обработчик получения статуса контактов""" """Обработчик получения статуса контактов"""
# Валидируем данные пакета # Валидируем данные пакета

View File

@@ -311,6 +311,15 @@ class OnemeMobile:
writer, writer,
userId, userId,
) )
case self.opcodes.CONTACT_ADD_BY_PHONE:
await self.auth_required(
userPhone,
self.processors.contact_add_by_phone,
payload,
seq,
writer,
userId,
)
case self.opcodes.CONTACT_PRESENCE: case self.opcodes.CONTACT_PRESENCE:
await self.auth_required( await self.auth_required(
userPhone, userPhone,

View File

@@ -294,6 +294,15 @@ class OnemeWS:
websocket, websocket,
userId, userId,
) )
case self.opcodes.CONTACT_ADD_BY_PHONE:
await self.auth_required(
userPhone,
self.processors.contact_add_by_phone,
payload,
seq,
websocket,
userId,
)
case self.opcodes.CONTACT_PRESENCE: case self.opcodes.CONTACT_PRESENCE:
await self.auth_required( await self.auth_required(
userPhone, userPhone,