mirror of
https://github.com/openmax-server/server.git
synced 2026-06-18 17:08:26 +03:00
first commit
This commit is contained in:
0
src/tamtam_ws/__init__.py
Normal file
0
src/tamtam_ws/__init__.py
Normal file
22
src/tamtam_ws/controller.py
Normal file
22
src/tamtam_ws/controller.py
Normal file
@@ -0,0 +1,22 @@
|
||||
import asyncio
|
||||
from classes.controllerbase import ControllerBase
|
||||
from common.config import ServerConfig
|
||||
from tamtam_ws.server import TTWSServer
|
||||
|
||||
class TTWSController(ControllerBase):
|
||||
def __init__(self):
|
||||
self.config = ServerConfig()
|
||||
|
||||
def launch(self, api):
|
||||
async def _start_all():
|
||||
await asyncio.gather(
|
||||
TTWSServer(
|
||||
host=self.config.host,
|
||||
port=self.config.tamtam_ws_port,
|
||||
db_pool=api['db'],
|
||||
clients=api['clients'],
|
||||
send_event=api['event']
|
||||
).start()
|
||||
)
|
||||
|
||||
return _start_all()
|
||||
27
src/tamtam_ws/models.py
Normal file
27
src/tamtam_ws/models.py
Normal file
@@ -0,0 +1,27 @@
|
||||
import pydantic
|
||||
|
||||
class MessageModel(pydantic.BaseModel):
|
||||
ver: int
|
||||
cmd: int
|
||||
seq: int
|
||||
opcode: int
|
||||
payload: dict = None
|
||||
|
||||
class UserAgentModel(pydantic.BaseModel):
|
||||
deviceType: str
|
||||
appVersion: str
|
||||
osVersion: str
|
||||
locale: str
|
||||
deviceLocale: str
|
||||
deviceName: str
|
||||
screen: str
|
||||
headerUserAgent: str
|
||||
timezone: str
|
||||
|
||||
class HelloPayloadModel(pydantic.BaseModel):
|
||||
userAgent: UserAgentModel
|
||||
deviceId: str
|
||||
|
||||
class RequestCodePayloadModel(pydantic.BaseModel):
|
||||
phone: str
|
||||
requestType: str
|
||||
76
src/tamtam_ws/processors.py
Normal file
76
src/tamtam_ws/processors.py
Normal file
@@ -0,0 +1,76 @@
|
||||
import hashlib, secrets, random, time, logging, json
|
||||
from common.static import Static
|
||||
from common.tools import Tools
|
||||
from tamtam_ws.proto import Proto
|
||||
from tamtam_ws.models import *
|
||||
|
||||
class Processors:
|
||||
def __init__(self, db_pool=None, clients={}, send_event=None):
|
||||
self.static = Static()
|
||||
self.tools = Tools()
|
||||
self.proto = Proto()
|
||||
self.error_types = self.static.ErrorTypes()
|
||||
self.db_pool = db_pool
|
||||
self.logger = logging.getLogger(__name__)
|
||||
|
||||
async def _send(self, writer, packet):
|
||||
"""Отправка пакета"""
|
||||
await writer.send(packet)
|
||||
|
||||
async def _send_error(self, seq, opcode, type, writer):
|
||||
payload = self.static.ERROR_TYPES.get(type, {
|
||||
"localizedMessage": "Неизвестная ошибка",
|
||||
"error": "unknown.error",
|
||||
"message": "Unknown error",
|
||||
"title": "Неизвестная ошибка"
|
||||
})
|
||||
|
||||
packet = self.proto.pack_packet(
|
||||
seq=seq, opcode=opcode, payload=payload
|
||||
)
|
||||
|
||||
await self._send(writer, packet)
|
||||
|
||||
async def process_hello(self, payload, seq, writer):
|
||||
"""Обработчик приветствия"""
|
||||
# Валидируем данные пакета
|
||||
try:
|
||||
HelloPayloadModel.model_validate(payload)
|
||||
except Exception as e:
|
||||
await self._send_error(seq, self.proto.SESSION_INIT, self.error_types.INVALID_PAYLOAD, writer)
|
||||
return None, None
|
||||
|
||||
# Получаем данные из пакета
|
||||
deviceType = payload.get("userAgent").get("deviceType")
|
||||
deviceName = payload.get("userAgent").get("deviceName")
|
||||
|
||||
# Собираем данные ответа
|
||||
payload = {
|
||||
"proxy": "",
|
||||
"logs-enabled": False,
|
||||
"proxy-domains": [],
|
||||
"location": "RU"
|
||||
}
|
||||
|
||||
# Создаем пакет
|
||||
packet = self.proto.pack_packet(seq=seq, opcode=self.proto.SESSION_INIT, payload=payload)
|
||||
|
||||
# Отправляем
|
||||
await self._send(writer, packet)
|
||||
return deviceType, deviceName
|
||||
|
||||
async def process_ping(self, payload, seq, writer):
|
||||
"""Обработчик пинга"""
|
||||
# Создаем пакет
|
||||
packet = self.proto.pack_packet(seq=seq, opcode=self.proto.PING)
|
||||
|
||||
# Отправляем
|
||||
await self._send(writer, packet)
|
||||
|
||||
async def process_telemetry(self, payload, seq, writer):
|
||||
"""Обработчик телеметрии"""
|
||||
# Создаем пакет
|
||||
packet = self.proto.pack_packet(seq=seq, opcode=self.proto.LOG)
|
||||
|
||||
# Отправляем
|
||||
await self._send(writer, packet)
|
||||
153
src/tamtam_ws/proto.py
Normal file
153
src/tamtam_ws/proto.py
Normal file
@@ -0,0 +1,153 @@
|
||||
import json
|
||||
|
||||
class Proto:
|
||||
def pack_packet(self, ver=10, cmd=1, seq=0, opcode=1, payload=None):
|
||||
# а разве не надо в жсон запаковывать ещё
|
||||
# о всё
|
||||
return json.dumps({
|
||||
"ver": ver,
|
||||
"cmd": cmd,
|
||||
"seq": seq,
|
||||
"opcode": opcode,
|
||||
"payload": payload
|
||||
})
|
||||
|
||||
def unpack_packet(self, packet):
|
||||
# нужно try catch сделать
|
||||
# чтобы не сыпалось всё при неверных пакетах
|
||||
try:
|
||||
parsed_packet = json.loads(packet)
|
||||
except:
|
||||
return {}
|
||||
|
||||
return parsed_packet
|
||||
# мне кажется долго вручную всё писать
|
||||
# а как еще
|
||||
# ну вставить сюда целиком и потом через multiline cursor удалить лишнее
|
||||
# ну ты удалишь тогда. я на тачпаде
|
||||
# ладно щас другим способом удалю
|
||||
# всё нахуй
|
||||
# TAMTAM SOURCE LEAK 2026
|
||||
# так ну че делать будем
|
||||
# так ну
|
||||
|
||||
# 19 опкод сделан?
|
||||
# нет сэр пошли библиотеку тамы смотреть
|
||||
# мб найдем че. она без обфускации
|
||||
# а ты ее видишь?
|
||||
# пошли
|
||||
PING = 1
|
||||
LOG = 5
|
||||
SESSION_INIT = 6
|
||||
PROFILE = 16
|
||||
AUTH_REQUEST = 17
|
||||
AUTH_CHECK_SCENARIO = 263
|
||||
AUTH = 18
|
||||
LOGIN = 19
|
||||
LOGOUT = 20
|
||||
SYNC = 21
|
||||
CONFIG = 22
|
||||
AUTH_CONFIRM = 23
|
||||
ASSETS_GET = 26
|
||||
ASSETS_UPDATE = 27
|
||||
ASSETS_GET_BY_IDS = 28
|
||||
ASSETS_ADD = 29
|
||||
ASSETS_REMOVE = 259
|
||||
ASSETS_MOVE = 260
|
||||
ASSETS_LIST_MODIFY = 261
|
||||
CONTACT_INFO = 32
|
||||
CONTACT_UPDATE = 34
|
||||
CONTACT_PRESENCE = 35
|
||||
CONTACT_LIST = 36
|
||||
CONTACT_PHOTOS = 39
|
||||
CONTACT_CREATE = 41
|
||||
REMOVE_CONTACT_PHOTO = 43
|
||||
OWN_CONTACT_SEARCH = 44
|
||||
CHAT_INFO = 48
|
||||
CHAT_HISTORY = 49
|
||||
CHAT_MARK = 50
|
||||
CHAT_MEDIA = 51
|
||||
CHAT_DELETE = 52
|
||||
CHAT_LIST = 53
|
||||
CHAT_CLEAR = 54
|
||||
CHAT_UPDATE = 55
|
||||
CHAT_CHECK_LINK = 56
|
||||
CHAT_JOIN = 57
|
||||
CHAT_LEAVE = 58
|
||||
CHAT_MEMBERS = 59
|
||||
CHAT_CLOSE = 61
|
||||
CHAT_BOT_COMMANDS = 144
|
||||
CHAT_SUBSCRIBE = 75
|
||||
PUBLIC_SEARCH = 60
|
||||
CHAT_CREATE = 63
|
||||
MSG_SEND = 64
|
||||
MSG_TYPING = 65
|
||||
MSG_DELETE = 66
|
||||
MSG_EDIT = 67
|
||||
CHAT_SEARCH = 68
|
||||
MSG_SHARE_PREVIEW = 70
|
||||
MSG_SEARCH_TOUCH = 72
|
||||
MSG_SEARCH = 73
|
||||
MSG_GET_STAT = 74
|
||||
MSG_GET = 71
|
||||
VIDEO_CHAT_START = 76
|
||||
VIDEO_CHAT_JOIN = 102
|
||||
VIDEO_CHAT_COMMAND = 78
|
||||
VIDEO_CHAT_MEMBERS = 195
|
||||
CHAT_MEMBERS_UPDATE = 77
|
||||
PHOTO_UPLOAD = 80
|
||||
STICKER_UPLOAD = 81
|
||||
VIDEO_UPLOAD = 82
|
||||
VIDEO_PLAY = 83
|
||||
MUSIC_PLAY = 84
|
||||
MUSIC_PLAY30 = 85
|
||||
FILE_UPLOAD = 87
|
||||
FILE_DOWNLOAD = 88
|
||||
CHAT_PIN_SET_VISIBILITY = 86
|
||||
LINK_INFO = 89
|
||||
MESSAGE_LINK = 90
|
||||
MSG_CONSTRUCT = 94
|
||||
SESSIONS_INFO = 96
|
||||
SESSIONS_CLOSE = 97
|
||||
PHONE_BIND_REQUEST = 98
|
||||
PHONE_BIND_CONFIRM = 99
|
||||
UNBIND_OK_PROFILE = 100
|
||||
CHAT_COMPLAIN = 117
|
||||
MSG_SEND_CALLBACK = 118
|
||||
SUSPEND_BOT = 119
|
||||
MSG_REACT = 178
|
||||
MSG_CANCEL_REACTION = 179
|
||||
MSG_GET_REACTIONS = 180
|
||||
MSG_GET_DETAILED_REACTIONS = 181
|
||||
LOCATION_STOP = 124
|
||||
LOCATION_SEND = 125
|
||||
LOCATION_REQUEST = 126
|
||||
NOTIF_MESSAGE = 128
|
||||
NOTIF_TYPING = 129
|
||||
NOTIF_MARK = 130
|
||||
NOTIF_CONTACT = 131
|
||||
NOTIF_PRESENCE = 132
|
||||
NOTIF_CONFIG = 134
|
||||
NOTIF_CHAT = 135
|
||||
NOTIF_ATTACH = 136
|
||||
NOTIF_VIDEO_CHAT_START = 137
|
||||
NOTIF_VIDEO_CHAT_COMMAND = 138
|
||||
NOTIF_CALLBACK_ANSWER = 143
|
||||
NOTIF_MSG_CONSTRUCT = 146
|
||||
NOTIF_LOCATION = 147
|
||||
NOTIF_LOCATION_REQUEST = 148
|
||||
NOTIF_ASSETS_UPDATE = 150
|
||||
NOTIF_MSG_REACTIONS_CHANGED = 155
|
||||
NOTIF_MSG_YOU_REACTED = 156
|
||||
NOTIF_DRAFT = 152
|
||||
NOTIF_DRAFT_DISCARD = 153
|
||||
NOTIF_MSG_DELAYED = 154
|
||||
AUTH_CALL_INFO = 256
|
||||
CONTACT_INFO_EXTERNAL = 45
|
||||
DRAFT_SAVE = 176
|
||||
DRAFT_DISCARD = 177
|
||||
STICKER_CREATE = 193
|
||||
STICKER_SUGGEST = 194
|
||||
CHAT_SEARCH_COUNT_MSG = 197
|
||||
CHAT_SEARCH_COMMON_PARTICIPANTS = 198
|
||||
GET_USER_SCORE = 201
|
||||
61
src/tamtam_ws/server.py
Normal file
61
src/tamtam_ws/server.py
Normal file
@@ -0,0 +1,61 @@
|
||||
import asyncio, logging, json
|
||||
from websockets.asyncio.server import serve
|
||||
from tamtam_ws.models import *
|
||||
from pydantic import ValidationError
|
||||
from tamtam_ws.proto import Proto
|
||||
from tamtam_ws.processors import Processors
|
||||
|
||||
class TTWSServer:
|
||||
def __init__(self, host, port, db_pool=None, clients={}, send_event=None):
|
||||
self.host = host
|
||||
self.port = port
|
||||
self.proto = Proto()
|
||||
self.processors = Processors(db_pool=db_pool, clients=clients, send_event=send_event)
|
||||
self.logger = logging.getLogger(__name__)
|
||||
|
||||
async def handle_client(self, websocket):
|
||||
deviceType = None
|
||||
deviceName = None
|
||||
|
||||
async for message in websocket:
|
||||
# Распаковываем пакет
|
||||
packet = self.proto.unpack_packet(message)
|
||||
|
||||
# Валидируем структуру пакета
|
||||
try:
|
||||
MessageModel.model_validate(packet)
|
||||
except ValidationError as e:
|
||||
self.logger.error(e)
|
||||
|
||||
# Извлекаем данные из пакета
|
||||
seq = packet['seq']
|
||||
opcode = packet['opcode']
|
||||
payload = packet['payload']
|
||||
|
||||
match opcode:
|
||||
case self.proto.SESSION_INIT:
|
||||
# ПРИВЕТ АНДРЕЙ МАЛАХОВ
|
||||
# не не удаляй этот коммент. пусть останется на релизе аххахаха
|
||||
deviceType, deviceType = await self.processors.process_hello(payload, seq, websocket)
|
||||
case self.proto.PING:
|
||||
await self.processors.process_ping(payload, seq, websocket)
|
||||
case self.proto.LOG:
|
||||
# телеметрия аааа слежка цру фсб фбр
|
||||
# УДАЛЯЕМ MYTRACKER ИЗ TAMTAM ТАМ ВИРУС
|
||||
# майтрекер отправляет все ваши сообщения на сервер барака обамы. немедленно удаляем!!!
|
||||
await self.processors.process_telemetry(payload, seq, websocket)
|
||||
# case self.proto.AUTH_REQUEST:
|
||||
# await self.processors.process_auth_request(payload, seq, websocket)
|
||||
# case self.proto.VERIFY_CODE:
|
||||
# await self.processors.process_verify_code(payload, seq, websocket)
|
||||
# case self.proto.FINAL_AUTH:
|
||||
# await self.processors.process_final_auth(payload, seq, websocket, deviceType, deviceName)
|
||||
|
||||
# лан я пойду. пока
|
||||
# а ок
|
||||
|
||||
async def start(self):
|
||||
self.logger.info(f"Вебсокет запущен на порту {self.port}")
|
||||
|
||||
async with serve(self.handle_client, self.host, self.port):
|
||||
await asyncio.Future()
|
||||
Reference in New Issue
Block a user