openmax-server/src/oneme_tcp/proto.py

251 lines
7.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import lz4.block, msgpack, logging, json
class Proto:
def __init__(self) -> None:
self.logger = logging.getLogger(__name__)
# TODO узнать какие должны быть лимиты и поменять,
# сейчас это больше заглушка
MAX_PAYLOAD_SIZE = 1048576 # 1 MB
MAX_DECOMPRESSED_SIZE = 1048576 # 1 MB
HEADER_SIZE = 10 # 1+2+1+2+4
### Работа с протоколом
def unpack_packet(self, data: bytes) -> dict | None:
# Проверяем минимальный размер пакета
if len(data) < self.HEADER_SIZE:
self.logger.warning(f"Пакет слишком маленький: {len(data)} байт")
return None
# Распаковываем заголовок
ver = int.from_bytes(data[0:1], "big")
cmd = int.from_bytes(data[1:3], "big")
seq = int.from_bytes(data[3:4], "big")
opcode = int.from_bytes(data[4:6], "big")
packed_len = int.from_bytes(data[6:10], "big")
# Флаг упаковки
comp_flag = packed_len >> 24
# Парсим данные пакета
payload_length = packed_len & 0xFFFFFF
# Проверяем размер payload
if payload_length > self.MAX_PAYLOAD_SIZE:
self.logger.warning(f"Payload слишком большой: {payload_length} B (лимит {self.MAX_PAYLOAD_SIZE})")
return None
# Проверяем длину пакета
if len(data) < self.HEADER_SIZE + payload_length:
self.logger.warning(f"Пакет неполный: требуется {self.HEADER_SIZE + payload_length} B, получено {len(data)}")
return None
payload_bytes = data[10 : 10 + payload_length]
payload = None
# Декодируем данные пакета
if payload_bytes:
# Разжимаем данные пакета, если требуется
if comp_flag != 0:
compressed_data = payload_bytes
try:
payload_bytes = lz4.block.decompress(
compressed_data,
uncompressed_size=self.MAX_DECOMPRESSED_SIZE,
)
except lz4.block.LZ4BlockError:
self.logger.warning("Ошибка декомпрессии LZ4")
return None
# Распаковываем msgpack
payload = msgpack.unpackb(payload_bytes, raw=False, strict_map_key=False)
self.logger.debug(f"Распаковал - ver={ver} cmd={cmd} seq={seq} opcode={opcode} payload={payload}")
# Возвращаем
return {
"ver": ver,
"cmd": cmd,
"seq": seq,
"opcode": opcode,
"payload": payload,
}
def pack_packet(self, ver: int = 10, cmd: int = 1, seq: int = 1, opcode: int = 6, payload: dict = None) -> bytes:
# Запаковываем заголовок
ver_b = ver.to_bytes(1, "big")
cmd_b = cmd.to_bytes(2, "big")
seq_b = seq.to_bytes(1, "big")
opcode_b = opcode.to_bytes(2, "big")
# Запаковываем данные пакета
payload_bytes: bytes | None = msgpack.packb(payload)
if payload_bytes is None:
payload_bytes = b""
payload_len = len(payload_bytes) & 0xFFFFFF
payload_len_b = payload_len.to_bytes(4, 'big')
self.logger.debug(f"Упаковал - ver={ver} cmd={cmd} seq={seq} opcode={opcode} payload={payload}")
# Возвращаем пакет
return ver_b + cmd_b + seq_b + opcode_b + payload_len_b + payload_bytes
### Констаты протокола
CMD_OK = 0x100
CMD_NOF = 0x200
CMD_ERR = 0x300
PROTO_VER = 10
### Команды
PING = 1
DEBUG = 2
RECONNECT = 3
LOG = 5
SESSION_INIT = 6
PROFILE = 16
AUTH_REQUEST = 17
AUTH = 18
LOGIN = 19
LOGOUT = 20
SYNC = 21
CONFIG = 22
AUTH_CONFIRM = 23
AUTH_CREATE_TRACK = 112
AUTH_CHECK_PASSWORD = 113
AUTH_LOGIN_CHECK_PASSWORD = 115
AUTH_LOGIN_PROFILE_DELETE = 116
AUTH_LOGIN_RESTORE_PASSWORD = 101
AUTH_VALIDATE_PASSWORD = 107
AUTH_VALIDATE_HINT = 108
AUTH_VERIFY_EMAIL = 109
AUTH_CHECK_EMAIL = 110
AUTH_SET_2FA = 111
AUTH_2FA_DETAILS = 104
ASSETS_GET = 26
ASSETS_UPDATE = 27
ASSETS_GET_BY_IDS = 28
ASSETS_LIST_MODIFY = 261
ASSETS_REMOVE = 259
ASSETS_MOVE = 260
ASSETS_ADD = 29
PRESET_AVATARS = 25
CONTACT_INFO = 32
CONTACT_INFO_BY_PHONE = 46
CONTACT_ADD = 33
CONTACT_UPDATE = 34
CONTACT_PRESENCE = 35
CONTACT_LIST = 36
CONTACT_SEARCH = 37
CONTACT_MUTUAL = 38
CONTACT_PHOTOS = 39
CONTACT_SORT = 40
CONTACT_VERIFY = 42
REMOVE_CONTACT_PHOTO = 43
CHAT_INFO = 48
CHAT_HISTORY = 49
CHAT_MARK = 50
CHAT_MEDIA = 51
CHAT_DELETE = 52
CHATS_LIST = 53
CHAT_CLEAR = 54
CHAT_UPDATE = 55
CHAT_CHECK_LINK = 56
CHAT_JOIN = 57
CHAT_LEAVE = 58
CHAT_MEMBERS = 59
PUBLIC_SEARCH = 60
CHAT_PERSONAL_CONFIG = 61
CHAT_CREATE = 63
REACTIONS_SETTINGS_GET_BY_CHAT_ID = 258
CHAT_REACTIONS_SETTINGS_SET = 257
MSG_SEND = 64
MSG_TYPING = 65
MSG_DELETE = 66
MSG_EDIT = 67
MSG_DELETE_RANGE = 92
MSG_REACTION = 178
MSG_CANCEL_REACTION = 179
MSG_GET_REACTIONS = 180
MSG_GET_DETAILED_REACTIONS = 181
CHAT_SEARCH = 68
MSG_SHARE_PREVIEW = 70
MSG_GET = 71
MSG_SEARCH_TOUCH = 72
MSG_SEARCH = 73
MSG_GET_STAT = 74
CHAT_SUBSCRIBE = 75
VIDEO_CHAT_START = 76
VIDEO_CHAT_START_ACTIVE = 78
CHAT_MEMBERS_UPDATE = 77
VIDEO_CHAT_HISTORY = 79
PHOTO_UPLOAD = 80
STICKER_UPLOAD = 81
VIDEO_UPLOAD = 82
VIDEO_PLAY = 83
VIDEO_CHAT_CREATE_JOIN_LINK = 84
CHAT_PIN_SET_VISIBILITY = 86
FILE_UPLOAD = 87
FILE_DOWNLOAD = 88
LINK_INFO = 89
SESSIONS_INFO = 96
SESSIONS_CLOSE = 97
PHONE_BIND_REQUEST = 98
PHONE_BIND_CONFIRM = 99
GET_INBOUND_CALLS = 103
EXTERNAL_CALLBACK = 105
OK_TOKEN = 158
CHAT_COMPLAIN = 117
MSG_SEND_CALLBACK = 118
SUSPEND_BOT = 119
LOCATION_STOP = 124
GET_LAST_MENTIONS = 127
STICKER_CREATE = 193
STICKER_SUGGEST = 194
VIDEO_CHAT_MEMBERS = 195
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_CALL_START = 137
NOTIF_CONTACT_SORT = 139
NOTIF_MSG_DELETE_RANGE = 140
NOTIF_MSG_DELETE = 142
NOTIF_MSG_REACTIONS_CHANGED = 155
NOTIF_MSG_YOU_REACTED = 156
NOTIF_CALLBACK_ANSWER = 143
CHAT_BOT_COMMANDS = 144
BOT_INFO = 145
NOTIF_LOCATION = 147
NOTIF_LOCATION_REQUEST = 148
NOTIF_ASSETS_UPDATE = 150
NOTIF_DRAFT = 152
NOTIF_DRAFT_DISCARD = 153
DRAFT_SAVE = 176
DRAFT_DISCARD = 177
CHAT_HIDE = 196
CHAT_SEARCH_COMMON_PARTICIPANTS = 198
NOTIF_MSG_DELAYED = 154
NOTIF_PROFILE = 159
PROFILE_DELETE = 199
PROFILE_DELETE_TIME = 200
WEB_APP_INIT_DATA = 160
COMPLAIN = 161
COMPLAIN_REASONS_GET = 162
FOLDERS_GET = 272
FOLDERS_GET_BY_ID = 273
FOLDERS_UPDATE = 274
FOLDERS_REORDER = 275
FOLDERS_DELETE = 276
NOTIF_FOLDERS = 277
AUTH_QR_APPROVE = 290
NOTIF_BANNERS = 292
CHAT_SUGGEST = 300
AUDIO_PLAY = 301
SEND_VOTE = 304
VOTERS_LIST_BY_ANSWER = 305
GET_POLL_UPDATES = 306