mirror of
https://github.com/openmax-server/server.git
synced 2026-05-22 19:41:41 +03:00
Compare commits
5 Commits
ac40cc53c9
...
17245f44d0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
17245f44d0 | ||
|
|
b1a37bfa24 | ||
|
|
d81eec5532 | ||
|
|
ddb810589f | ||
|
|
dff6937da8 |
@@ -44,6 +44,7 @@ class Opcodes:
|
||||
CONTACT_MUTUAL = 38
|
||||
CONTACT_PHOTOS = 39
|
||||
CONTACT_SORT = 40
|
||||
CONTACT_ADD_BY_PHONE = 41
|
||||
CONTACT_VERIFY = 42
|
||||
REMOVE_CONTACT_PHOTO = 43
|
||||
CHAT_INFO = 48
|
||||
|
||||
@@ -6,9 +6,9 @@ class SQLQueries:
|
||||
|
||||
INSERT_USER = """
|
||||
INSERT INTO users
|
||||
(phone, telegram_id, firstname, lastname, username,
|
||||
(id, phone, telegram_id, firstname, lastname, username,
|
||||
profileoptions, options, accountstatus, updatetime, lastseen)
|
||||
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
|
||||
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
|
||||
"""
|
||||
|
||||
INSERT_USER_DATA = """
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import json
|
||||
import secrets
|
||||
import time
|
||||
import os
|
||||
|
||||
import geoip2.database
|
||||
|
||||
@@ -204,27 +204,28 @@ class Tools:
|
||||
|
||||
if include_favourites:
|
||||
# Получаем последнее сообщение из избранного
|
||||
favouriteChatId = -senderId
|
||||
message, messageTime = await self.get_last_message(
|
||||
senderId, db_pool, protocol_type=protocol_type
|
||||
favouriteChatId, db_pool, protocol_type=protocol_type
|
||||
)
|
||||
|
||||
# ID избранного
|
||||
# ID избранного для клиента
|
||||
chatId = senderId ^ senderId
|
||||
|
||||
# Получаем последнюю активность участника (отправителя) в избранном
|
||||
# Получаем последнюю активность в избранном
|
||||
participants = await self.get_participant_last_activity(
|
||||
senderId, [senderId], db_pool
|
||||
favouriteChatId, [senderId], db_pool
|
||||
)
|
||||
|
||||
# Получаем ID предыдущего сообщения для избранного (чат ID = senderId)
|
||||
# Получаем ID предыдущего сообщения для избранного
|
||||
prevMessageId = await self.get_previous_message_id(
|
||||
senderId, db_pool, protocol_type=protocol_type
|
||||
favouriteChatId, db_pool, protocol_type=protocol_type
|
||||
)
|
||||
|
||||
# Хардкодим в лист чатов избранное
|
||||
chats.append(
|
||||
self.generate_chat(
|
||||
chatId if protocol_type == "mobile" else str(chatId),
|
||||
chatId,
|
||||
senderId,
|
||||
"DIALOG",
|
||||
participants,
|
||||
@@ -561,4 +562,14 @@ class Tools:
|
||||
response = reader.country(ip)
|
||||
return response.country.name or "Localhost Federation"
|
||||
except Exception:
|
||||
return "Localhost Federation"
|
||||
return "Localhost Federation"
|
||||
|
||||
async def generate_user_id(self, db_pool):
|
||||
"""Генерация id пользователя"""
|
||||
async with db_pool.acquire() as conn:
|
||||
async with conn.cursor() as cursor:
|
||||
while True:
|
||||
user_id = secrets.randbelow(2_147_383_647) + 100_000
|
||||
await cursor.execute("SELECT id FROM users WHERE id = %s", (user_id,))
|
||||
if not await cursor.fetchone():
|
||||
return user_id
|
||||
|
||||
@@ -145,6 +145,10 @@ class ContactListPayloadModel(pydantic.BaseModel):
|
||||
class ContactPresencePayloadModel(pydantic.BaseModel):
|
||||
contactIds: list
|
||||
|
||||
class ContactAddByPhonePayloadModel(pydantic.BaseModel):
|
||||
phone: str
|
||||
firstName: str
|
||||
|
||||
class ContactUpdatePayloadModel(pydantic.BaseModel):
|
||||
action: str
|
||||
contactId: int
|
||||
|
||||
@@ -397,15 +397,19 @@ class AuthProcessors(BaseProcessor):
|
||||
now_ms = int(time.time() * 1000)
|
||||
now_s = int(time.time())
|
||||
|
||||
# Генерируем ID пользователя
|
||||
user_id = await self.tools.generate_user_id(self.db_pool)
|
||||
|
||||
# Создаем пользователя
|
||||
await cursor.execute(
|
||||
"""
|
||||
INSERT INTO users
|
||||
(phone, telegram_id, firstname, lastname, username,
|
||||
(id, phone, telegram_id, firstname, lastname, username,
|
||||
profileoptions, options, accountstatus, updatetime, lastseen)
|
||||
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
|
||||
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
|
||||
""",
|
||||
(
|
||||
user_id,
|
||||
phone,
|
||||
None,
|
||||
first_name,
|
||||
@@ -419,8 +423,6 @@ class AuthProcessors(BaseProcessor):
|
||||
),
|
||||
)
|
||||
|
||||
user_id = cursor.lastrowid
|
||||
|
||||
# Добавляем данные аккаунта
|
||||
await cursor.execute(
|
||||
"""
|
||||
|
||||
@@ -2,7 +2,7 @@ import pydantic
|
||||
import json
|
||||
import time
|
||||
from classes.baseprocessor import BaseProcessor
|
||||
from oneme.models import ContactListPayloadModel, ContactPresencePayloadModel, ContactUpdatePayloadModel
|
||||
from oneme.models import ContactAddByPhonePayloadModel, ContactListPayloadModel, ContactPresencePayloadModel, ContactUpdatePayloadModel
|
||||
|
||||
class ContactsProcessors(BaseProcessor):
|
||||
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)",
|
||||
(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:
|
||||
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)
|
||||
|
||||
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):
|
||||
"""Обработчик получения статуса контактов"""
|
||||
# Валидируем данные пакета
|
||||
|
||||
@@ -23,16 +23,17 @@ class HistoryProcessors(BaseProcessor):
|
||||
messages = []
|
||||
|
||||
# Если пользователь хочет получить историю из избранного,
|
||||
# то выставляем в качестве ID чата его ID
|
||||
if chatId == (senderId ^ senderId):
|
||||
chatId = senderId
|
||||
# то выставляем в качестве ID чата отрицательный ID отправителя
|
||||
isFavourite = chatId == (senderId ^ senderId)
|
||||
if isFavourite:
|
||||
chatId = -senderId
|
||||
|
||||
# Проверяем, существует ли чат
|
||||
async with self.db_pool.acquire() as conn:
|
||||
async with conn.cursor() as cursor:
|
||||
# Проверяем состоит ли пользователь в чате,
|
||||
# только в случае того, если это не избранное
|
||||
if chatId != senderId:
|
||||
if not isFavourite:
|
||||
await cursor.execute("SELECT * FROM chats WHERE id = %s", (chatId,))
|
||||
chat = await cursor.fetchone()
|
||||
|
||||
|
||||
@@ -88,9 +88,9 @@ class MessagesProcessors(BaseProcessor):
|
||||
chatId = userId ^ senderId
|
||||
|
||||
# Если клиент хочет отправить сообщение в избранное,
|
||||
# то выставляем в качестве ID чата ID отправителя
|
||||
# то выставляем в качестве ID чата отрицательный ID отправителя
|
||||
if chatId == (senderId ^ senderId):
|
||||
chatId = senderId
|
||||
chatId = -senderId
|
||||
participants = [senderId]
|
||||
else:
|
||||
# Если все таки клиент хочет отправить сообщение в нормальный чат,
|
||||
@@ -143,7 +143,7 @@ class MessagesProcessors(BaseProcessor):
|
||||
participant,
|
||||
{
|
||||
"eventType": "new_msg",
|
||||
"chatId": 0 if chatId == (senderId ^ senderId) else chatId,
|
||||
"chatId": 0 if chatId == -senderId else chatId,
|
||||
"message": bodyMessage,
|
||||
"prevMessageId": lastMessageId,
|
||||
"time": messageTime,
|
||||
@@ -153,7 +153,7 @@ class MessagesProcessors(BaseProcessor):
|
||||
|
||||
# Данные пакета
|
||||
payload = {
|
||||
"chatId": 0 if chatId == senderId else chatId,
|
||||
"chatId": 0 if chatId == -senderId else chatId,
|
||||
"message": bodyMessage,
|
||||
"unread": 0,
|
||||
"mark": messageTime
|
||||
|
||||
@@ -223,12 +223,12 @@ class SearchProcessors(BaseProcessor):
|
||||
)
|
||||
)
|
||||
else:
|
||||
# Получаем последнее сообщение из чата
|
||||
# Получаем последнее сообщение из избранного
|
||||
message, messageTime = await self.tools.get_last_message(
|
||||
senderId, self.db_pool, protocol_type=self.type
|
||||
-senderId, self.db_pool, protocol_type=self.type
|
||||
)
|
||||
|
||||
# ID избранного
|
||||
# ID избранного для клиента
|
||||
chatId = senderId ^ senderId
|
||||
|
||||
# Добавляем чат в список
|
||||
|
||||
@@ -311,6 +311,15 @@ class OnemeMobile:
|
||||
writer,
|
||||
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:
|
||||
await self.auth_required(
|
||||
userPhone,
|
||||
|
||||
@@ -294,6 +294,15 @@ class OnemeWS:
|
||||
websocket,
|
||||
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:
|
||||
await self.auth_required(
|
||||
userPhone,
|
||||
|
||||
@@ -135,7 +135,7 @@ class MessagesProcessors(BaseProcessor):
|
||||
participant,
|
||||
{
|
||||
"eventType": "new_msg",
|
||||
"chatId": 0 if chatId == senderId else chatId,
|
||||
"chatId": chatId,
|
||||
"message": bodyMessage,
|
||||
"prevMessageId": lastMessageId,
|
||||
"time": messageTime,
|
||||
@@ -145,7 +145,7 @@ class MessagesProcessors(BaseProcessor):
|
||||
|
||||
# Данные пакета
|
||||
payload = {
|
||||
"chatId": 0 if chatId == senderId else chatId,
|
||||
"chatId": chatId,
|
||||
"message": bodyMessage,
|
||||
"unread": 0,
|
||||
"mark": messageTime
|
||||
|
||||
@@ -88,10 +88,14 @@ class TelegramBot:
|
||||
username = (message.from_user.username or f"user{int(time.time() * 1000)}")[:60]
|
||||
|
||||
try:
|
||||
# Генерируем ID пользователя
|
||||
user_id = await self.tools.generate_user_id(self.db_pool)
|
||||
|
||||
# Создаем юзера
|
||||
await cursor.execute(
|
||||
self.sql_queries.INSERT_USER,
|
||||
(
|
||||
user_id, # id
|
||||
new_phone, # phone
|
||||
tg_id, # telegram_id
|
||||
firstname, # firstname
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
CREATE TABLE `users` (
|
||||
`id` INT NOT NULL AUTO_INCREMENT,
|
||||
`id` INT NOT NULL,
|
||||
`phone` VARCHAR(20) UNIQUE,
|
||||
`telegram_id` VARCHAR(64) UNIQUE,
|
||||
`telegram_id` VARCHAR(64),
|
||||
`firstname` VARCHAR(59) NOT NULL,
|
||||
`lastname` VARCHAR(59),
|
||||
`description` VARCHAR(400),
|
||||
|
||||
Reference in New Issue
Block a user