redzedbot 1.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,167 @@
1
+ """
2
+ TCP connection management for online and chat
3
+ """
4
+
5
+ import asyncio
6
+ from typing import Callable, Optional, Dict, Any
7
+ from .proto import ParaHex_pb2
8
+ from .utils import create_message_packet, decode_whisper_message
9
+
10
+
11
+ class OnlineConnection:
12
+ """Manages the online/presence TCP connection"""
13
+
14
+ def __init__(self, ip: str, port: str, key: bytes, iv: bytes):
15
+ self.ip = ip
16
+ self.port = int(port)
17
+ self.key = key
18
+ self.iv = iv
19
+ self.is_connected = False
20
+ self._writer = None
21
+ self._reader = None
22
+
23
+ async def connect(self, auth_packet: str, reconnect_delay: float = 0.5):
24
+ """Connect and maintain online connection"""
25
+ while True:
26
+ try:
27
+ self._reader, self._writer = await asyncio.open_connection(self.ip, self.port)
28
+
29
+ auth = bytes.fromhex(auth_packet)
30
+ self._writer.write(auth)
31
+ await self._writer.drain()
32
+
33
+ self.is_connected = True
34
+
35
+ while True:
36
+ data = await self._reader.read(9999)
37
+ if not data:
38
+ break
39
+
40
+ except Exception as e:
41
+ print(f"Online connection error: {e}")
42
+ self.is_connected = False
43
+
44
+ finally:
45
+ await self.close()
46
+ await asyncio.sleep(reconnect_delay)
47
+
48
+ async def send_packet(self, packet: bytes):
49
+ """Send packet through online connection"""
50
+ if self._writer and not self._writer.is_closing():
51
+ self._writer.write(packet)
52
+ await self._writer.drain()
53
+
54
+ async def close(self):
55
+ """Close connection"""
56
+ if self._writer and not self._writer.is_closing():
57
+ self._writer.close()
58
+ await self._writer.wait_closed()
59
+
60
+ self.is_connected = False
61
+
62
+
63
+ class ChatConnection:
64
+ """Manages the chat TCP connection"""
65
+
66
+ def __init__(self, ip: str, port: str, key: bytes, iv: bytes, message_callback: Callable):
67
+ self.ip = ip
68
+ self.port = int(port)
69
+ self.key = key
70
+ self.iv = iv
71
+ self.is_connected = False
72
+ self._writer = None
73
+ self._reader = None
74
+ self._message_callback = message_callback
75
+
76
+ async def connect(self, auth_packet: str, reconnect_delay: float = 0.5):
77
+ """Connect and handle chat messages"""
78
+ while True:
79
+ try:
80
+ self._reader, self._writer = await asyncio.open_connection(self.ip, self.port)
81
+
82
+ auth = bytes.fromhex(auth_packet)
83
+ self._writer.write(auth)
84
+ await self._writer.drain()
85
+
86
+ self.is_connected = True
87
+
88
+ while True:
89
+ data = await self._reader.read(9999)
90
+ if not data:
91
+ break
92
+
93
+ await self._process_packet(data)
94
+
95
+ except Exception as e:
96
+ print(f"Chat connection error: {e}")
97
+ self.is_connected = False
98
+
99
+ finally:
100
+ await self.close()
101
+ await asyncio.sleep(reconnect_delay)
102
+
103
+ async def _process_packet(self, data: bytes):
104
+ """Process incoming packet"""
105
+ try:
106
+ hex_data = data.hex()
107
+
108
+ if hex_data.startswith("120000"):
109
+ message_data = await decode_whisper_message(hex_data[10:])
110
+
111
+ if message_data:
112
+ await self._message_callback(message_data)
113
+
114
+ except Exception as e:
115
+ print(f"Packet processing error: {e}")
116
+
117
+ async def send_packet(self, packet: bytes):
118
+ """Send packet through chat connection"""
119
+ if self._writer and not self._writer.is_closing():
120
+ self._writer.write(packet)
121
+ await self._writer.drain()
122
+
123
+ async def send_dm(self, message: str, user_id: int, key: bytes, iv: bytes):
124
+ packet = await create_message_packet(
125
+ message=message,
126
+ chat_type=2,
127
+ target_id=user_id,
128
+ chat_id=user_id,
129
+ key=key,
130
+ iv=iv
131
+ )
132
+
133
+ await self.send_packet(packet)
134
+
135
+ async def send_squad(self, message: str, chat_id: int, key: bytes, iv: bytes):
136
+ """Send squad message"""
137
+ packet = await create_message_packet(
138
+ message=message,
139
+ chat_type=0,
140
+ target_id=chat_id,
141
+ chat_id=chat_id,
142
+ key=key,
143
+ iv=iv
144
+ )
145
+ await self.send_packet(packet)
146
+
147
+ async def send_guild(self, message: str, chat_id: int, key: bytes, iv: bytes):
148
+ """Send guild message"""
149
+ packet = await create_message_packet(
150
+ message=message,
151
+ chat_type=1,
152
+ target_id=chat_id,
153
+ chat_id=chat_id,
154
+ key=key,
155
+ iv=iv
156
+ )
157
+ await self.send_packet(packet)
158
+
159
+ async def close(self):
160
+ """Close connection"""
161
+ if self._writer and not self._writer.is_closing():
162
+ try:
163
+ self._writer.close()
164
+ await self._writer.wait_closed()
165
+ except:
166
+ pass
167
+ self.is_connected = False
redzedbot/guest.py ADDED
@@ -0,0 +1,37 @@
1
+ """
2
+ Guest login module for redzedbot
3
+ """
4
+
5
+ import asyncio
6
+ from .client import redzedbot
7
+
8
+
9
+ async def login(uid: str, password: str) -> redzedbot:
10
+ """
11
+ Login as a guest user and return a redzedbot instance.
12
+
13
+ Args:
14
+ uid: User ID
15
+ password: User password
16
+
17
+ Returns:
18
+ redzedbot instance if successful, None if login failed
19
+
20
+ Example:
21
+ >>> bot = await guest.login('4243232438', 'x7aMa-HGQXIFXLNx7m')
22
+ >>> if bot:
23
+ >>> await bot.online_loop()
24
+ """
25
+ try:
26
+ bot = redzedbot(uid, password)
27
+ success = await bot._authenticate()
28
+
29
+ if success:
30
+ return bot
31
+ else:
32
+ print("Login failed: Invalid credentials or account banned")
33
+ return None
34
+
35
+ except Exception as e:
36
+ print(f"Login error: {e}")
37
+ return None
redzedbot/message.py ADDED
@@ -0,0 +1,51 @@
1
+ """
2
+ Message class for handling incoming messages
3
+ """
4
+
5
+ from typing import Optional, Dict, Any
6
+
7
+
8
+ class Message:
9
+ """Represents an incoming message"""
10
+
11
+ def __init__(self, data: Dict[str, Any]):
12
+ self._data = data
13
+
14
+ self.user_id = data.get('uid')
15
+ self.chat_id = data.get('chat_id')
16
+ self.chat_type = data.get('chat_type')
17
+ self.text = data.get('message', '')
18
+
19
+ self.nickname = data.get('nickname')
20
+ self.profile_pic = data.get('profile_pic')
21
+
22
+ self._determine_type()
23
+
24
+ def _determine_type(self):
25
+ """Determine message type from chat_type"""
26
+ if self.chat_type == 0:
27
+ self.type = 'squad'
28
+ elif self.chat_type == 1:
29
+ self.type = 'guild'
30
+ elif self.chat_type == 2:
31
+ self.type = 'dm'
32
+ else:
33
+ self.type = 'unknown'
34
+
35
+ @property
36
+ def is_dm(self) -> bool:
37
+ """Check if message is a direct message"""
38
+ return self.type == 'dm'
39
+
40
+ @property
41
+ def is_squad(self) -> bool:
42
+ """Check if message is from squad chat"""
43
+ return self.type == 'squad'
44
+
45
+ @property
46
+ def is_guild(self) -> bool:
47
+ """Check if message is from guild chat"""
48
+ return self.type == 'guild'
49
+
50
+ def __repr__(self):
51
+ return f"Message(user_id={self.user_id}, type={self.type}, text='{self.text}')"
@@ -0,0 +1,54 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Generated by the protocol buffer compiler. DO NOT EDIT!
3
+ # NO CHECKED-IN PROTOBUF GENCODE
4
+ # source: ParaHex.proto
5
+ # Protobuf Python Version: 6.33.0
6
+ """Generated protocol buffer code."""
7
+ from google.protobuf import descriptor as _descriptor
8
+ from google.protobuf import descriptor_pool as _descriptor_pool
9
+ from google.protobuf import runtime_version as _runtime_version
10
+ from google.protobuf import symbol_database as _symbol_database
11
+ from google.protobuf.internal import builder as _builder
12
+ _runtime_version.ValidateProtobufRuntimeVersion(
13
+ _runtime_version.Domain.PUBLIC,
14
+ 6,
15
+ 33,
16
+ 0,
17
+ '',
18
+ 'ParaHex.proto'
19
+ )
20
+ # @@protoc_insertion_point(imports)
21
+
22
+ _sym_db = _symbol_database.Default()
23
+
24
+
25
+
26
+
27
+ DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\rParaHex.proto\"5\n\x0cGameSecurity\x12\x0f\n\x07version\x18\x06 \x01(\r\x12\x14\n\x0chidden_value\x18\x08 \x01(\x04\"\xfa\n\n\nMajorLogin\x12\x12\n\nevent_time\x18\x03 \x01(\t\x12\x11\n\tgame_name\x18\x04 \x01(\t\x12\x13\n\x0bplatform_id\x18\x05 \x01(\x05\x12\x16\n\x0e\x63lient_version\x18\x07 \x01(\t\x12\x17\n\x0fsystem_software\x18\x08 \x01(\t\x12\x17\n\x0fsystem_hardware\x18\t \x01(\t\x12\x18\n\x10telecom_operator\x18\n \x01(\t\x12\x14\n\x0cnetwork_type\x18\x0b \x01(\t\x12\x14\n\x0cscreen_width\x18\x0c \x01(\r\x12\x15\n\rscreen_height\x18\r \x01(\r\x12\x12\n\nscreen_dpi\x18\x0e \x01(\t\x12\x19\n\x11processor_details\x18\x0f \x01(\t\x12\x0e\n\x06memory\x18\x10 \x01(\r\x12\x14\n\x0cgpu_renderer\x18\x11 \x01(\t\x12\x13\n\x0bgpu_version\x18\x12 \x01(\t\x12\x18\n\x10unique_device_id\x18\x13 \x01(\t\x12\x11\n\tclient_ip\x18\x14 \x01(\t\x12\x10\n\x08language\x18\x15 \x01(\t\x12\x0f\n\x07open_id\x18\x16 \x01(\t\x12\x14\n\x0copen_id_type\x18\x17 \x01(\t\x12\x13\n\x0b\x64\x65vice_type\x18\x18 \x01(\t\x12\'\n\x10memory_available\x18\x19 \x01(\x0b\x32\r.GameSecurity\x12\x14\n\x0c\x61\x63\x63\x65ss_token\x18\x1d \x01(\t\x12\x17\n\x0fplatform_sdk_id\x18\x1e \x01(\x05\x12\x1a\n\x12network_operator_a\x18) \x01(\t\x12\x16\n\x0enetwork_type_a\x18* \x01(\t\x12\x1c\n\x14\x63lient_using_version\x18\x39 \x01(\t\x12\x1e\n\x16\x65xternal_storage_total\x18< \x01(\x05\x12\"\n\x1a\x65xternal_storage_available\x18= \x01(\x05\x12\x1e\n\x16internal_storage_total\x18> \x01(\x05\x12\"\n\x1ainternal_storage_available\x18? \x01(\x05\x12#\n\x1bgame_disk_storage_available\x18@ \x01(\x05\x12\x1f\n\x17game_disk_storage_total\x18\x41 \x01(\x05\x12%\n\x1d\x65xternal_sdcard_avail_storage\x18\x42 \x01(\x05\x12%\n\x1d\x65xternal_sdcard_total_storage\x18\x43 \x01(\x05\x12\x10\n\x08login_by\x18I \x01(\x05\x12\x14\n\x0clibrary_path\x18J \x01(\t\x12\x12\n\nreg_avatar\x18L \x01(\x05\x12\x15\n\rlibrary_token\x18M \x01(\t\x12\x14\n\x0c\x63hannel_type\x18N \x01(\x05\x12\x10\n\x08\x63pu_type\x18O \x01(\x05\x12\x18\n\x10\x63pu_architecture\x18Q \x01(\t\x12\x1b\n\x13\x63lient_version_code\x18S \x01(\t\x12\x14\n\x0cgraphics_api\x18V \x01(\t\x12\x1d\n\x15supported_astc_bitset\x18W \x01(\r\x12\x1a\n\x12login_open_id_type\x18X \x01(\x05\x12\x18\n\x10\x61nalytics_detail\x18Y \x01(\x0c\x12\x14\n\x0cloading_time\x18\\ \x01(\r\x12\x17\n\x0frelease_channel\x18] \x01(\t\x12\x12\n\nextra_info\x18^ \x01(\t\x12 \n\x18\x61ndroid_engine_init_flag\x18_ \x01(\r\x12\x0f\n\x07if_push\x18\x61 \x01(\x05\x12\x0e\n\x06is_vpn\x18\x62 \x01(\x05\x12\x1c\n\x14origin_platform_type\x18\x63 \x01(\t\x12\x1d\n\x15primary_platform_type\x18\x64 \x01(\t\"|\n\rMajorLoginRes\x12\x13\n\x0b\x61\x63\x63ount_uid\x18\x01 \x01(\x04\x12\x0e\n\x06region\x18\x02 \x01(\t\x12\r\n\x05token\x18\x08 \x01(\t\x12\x0b\n\x03url\x18\n \x01(\t\x12\x11\n\ttimestamp\x18\x15 \x01(\x03\x12\x0b\n\x03key\x18\x16 \x01(\x0c\x12\n\n\x02iv\x18\x17 \x01(\x0c\"\xa4\x01\n\x0cGetLoginData\x12\x12\n\nAccountUID\x18\x01 \x01(\x04\x12\x0e\n\x06Region\x18\x03 \x01(\t\x12\x13\n\x0b\x41\x63\x63ountName\x18\x04 \x01(\t\x12\x16\n\x0eOnline_IP_Port\x18\x0e \x01(\t\x12\x0f\n\x07\x43lan_ID\x18\x14 \x01(\x03\x12\x16\n\x0e\x41\x63\x63ountIP_Port\x18 \x01(\t\x12\x1a\n\x12\x43lan_Compiled_Data\x18\x37 \x01(\x0c\"\xa8\x02\n\rDecodeWhisper\x12$\n\x04\x44\x61ta\x18\x05 \x01(\x0b\x32\x16.DecodeWhisper.Nested1\x1a\xf0\x01\n\x07Nested1\x12\x0b\n\x03uid\x18\x01 \x01(\x04\x12\x0f\n\x07\x43hat_ID\x18\x02 \x01(\x04\x12\x11\n\tchat_type\x18\x03 \x01(\x05\x12\x0b\n\x03msg\x18\x04 \x01(\t\x12/\n\x07\x44\x65tails\x18\t \x01(\x0b\x32\x1e.DecodeWhisper.Nested1.Nested2\x12\x35\n\rPlatform_Info\x18\r \x01(\x0b\x32\x1e.DecodeWhisper.Nested1.Nested3\x1a\x1b\n\x07Nested2\x12\x10\n\x08Nickname\x18\x01 \x01(\t\x1a\"\n\x07Nested3\x12\x17\n\x0fprofile_pic_url\x18\x01 \x01(\t\"\x80\x01\n\rrecieved_chat\x12\x13\n\x0bpacket_type\x18\x04 \x01(\x03\x12&\n\x07\x64\x65tails\x18\x05 \x01(\x0b\x32\x15.recieved_chat.nested\x1a\x32\n\x06nested\x12\x12\n\nplayer_uid\x18\x01 \x01(\x03\x12\x14\n\x0cteam_session\x18\x0e \x01(\x0c\x62\x06proto3')
28
+
29
+ _globals = globals()
30
+ _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
31
+ _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'ParaHex_pb2', _globals)
32
+ if not _descriptor._USE_C_DESCRIPTORS:
33
+ DESCRIPTOR._loaded_options = None
34
+ _globals['_GAMESECURITY']._serialized_start=17
35
+ _globals['_GAMESECURITY']._serialized_end=70
36
+ _globals['_MAJORLOGIN']._serialized_start=73
37
+ _globals['_MAJORLOGIN']._serialized_end=1475
38
+ _globals['_MAJORLOGINRES']._serialized_start=1477
39
+ _globals['_MAJORLOGINRES']._serialized_end=1601
40
+ _globals['_GETLOGINDATA']._serialized_start=1604
41
+ _globals['_GETLOGINDATA']._serialized_end=1768
42
+ _globals['_DECODEWHISPER']._serialized_start=1771
43
+ _globals['_DECODEWHISPER']._serialized_end=2067
44
+ _globals['_DECODEWHISPER_NESTED1']._serialized_start=1827
45
+ _globals['_DECODEWHISPER_NESTED1']._serialized_end=2067
46
+ _globals['_DECODEWHISPER_NESTED1_NESTED2']._serialized_start=2004
47
+ _globals['_DECODEWHISPER_NESTED1_NESTED2']._serialized_end=2031
48
+ _globals['_DECODEWHISPER_NESTED1_NESTED3']._serialized_start=2033
49
+ _globals['_DECODEWHISPER_NESTED1_NESTED3']._serialized_end=2067
50
+ _globals['_RECIEVED_CHAT']._serialized_start=2070
51
+ _globals['_RECIEVED_CHAT']._serialized_end=2198
52
+ _globals['_RECIEVED_CHAT_NESTED']._serialized_start=2148
53
+ _globals['_RECIEVED_CHAT_NESTED']._serialized_end=2198
54
+ # @@protoc_insertion_point(module_scope)
@@ -0,0 +1,7 @@
1
+ """
2
+ Protobuf definitions
3
+ """
4
+
5
+ from . import ParaHex_pb2
6
+
7
+ __all__ = ['ParaHex_pb2']
redzedbot/utils.py ADDED
@@ -0,0 +1,191 @@
1
+ """
2
+ Utility functions for ParaHex
3
+ """
4
+
5
+ import random
6
+ from typing import Dict, Any, Optional
7
+ from Crypto.Cipher import AES
8
+ from Crypto.Util.Padding import pad
9
+ from .proto import ParaHex_pb2
10
+
11
+
12
+ async def get_random_user_agent() -> str:
13
+ """Generate random user agent"""
14
+ versions = [
15
+ '4.0.18P6', '4.0.19P7', '4.0.20P1', '4.1.0P3', '4.1.5P2', '4.2.1P8',
16
+ '4.2.3P1', '5.0.1B2', '5.0.2P4', '5.1.0P1', '5.2.0B1', '5.2.5P3',
17
+ '5.3.0B1', '5.3.2P2', '5.4.0P1', '5.4.3B2', '5.5.0P1', '5.5.2P3'
18
+ ]
19
+ models = [
20
+ 'SM-A125F', 'SM-A225F', 'SM-A325M', 'SM-A515F', 'SM-A725F', 'SM-M215F', 'SM-M325FV',
21
+ 'Redmi 9A', 'Redmi 9C', 'POCO M3', 'POCO M4 Pro', 'RMX2185', 'RMX3085',
22
+ 'moto g(9) play', 'CPH2239', 'V2027', 'OnePlus Nord', 'ASUS_Z01QD',
23
+ ]
24
+ android_versions = ['9', '10', '11', '12', '13', '14']
25
+ languages = ['en-US', 'es-MX', 'pt-BR', 'id-ID', 'ru-RU', 'hi-IN']
26
+ countries = ['USA', 'MEX', 'BRA', 'IDN', 'RUS', 'IND']
27
+
28
+ version = random.choice(versions)
29
+ model = random.choice(models)
30
+ android = random.choice(android_versions)
31
+ lang = random.choice(languages)
32
+ country = random.choice(countries)
33
+
34
+ return f"GarenaMSDK/{version}({model};Android {android};{lang};{country};)"
35
+
36
+
37
+ async def get_random_banner() -> int:
38
+ """Get random banner ID"""
39
+ banners = [
40
+ 902000306, 902000305, 902000003, 902000016, 902000017, 902000019,
41
+ 902031010, 902043025, 902043024, 902000020, 902000021, 902000023,
42
+ 902000070, 902000087, 902000108, 902000011, 902049020, 902049018,
43
+ 902049017, 902049016, 902049015, 902049003, 902033016, 902033017,
44
+ 902033018, 902048018, 902000306, 902000305, 902000079
45
+ ]
46
+ return random.choice(banners)
47
+
48
+
49
+ async def encrypt_proto(data: bytes) -> bytes:
50
+ """Encrypt protobuf data"""
51
+ key = b'Yg&tc%DEuh6%Zc^8'
52
+ iv = b'6oyZDr22E3ychjM%'
53
+ cipher = AES.new(key, AES.MODE_CBC, iv)
54
+ padded_message = pad(data, AES.block_size)
55
+ encrypted_payload = cipher.encrypt(padded_message)
56
+ return encrypted_payload
57
+
58
+
59
+ async def encrypt_packet(hex_data: str, key: bytes, iv: bytes) -> str:
60
+ """Encrypt packet data"""
61
+ cipher = AES.new(key, AES.MODE_CBC, iv)
62
+ encrypted = cipher.encrypt(pad(bytes.fromhex(hex_data), 16))
63
+ return encrypted.hex()
64
+
65
+
66
+ async def encode_hex(value: int) -> str:
67
+ """Encode integer to hex"""
68
+ result = hex(value)[2:]
69
+ if len(result) == 1:
70
+ result = "0" + result
71
+ return result
72
+
73
+
74
+ async def encode_uid(uid: int) -> str:
75
+ """Encode UID for protobuf"""
76
+ encoded = []
77
+ while uid:
78
+ encoded.append((uid & 0x7F) | (0x80 if uid > 0x7F else 0))
79
+ uid >>= 7
80
+ return bytes(encoded).hex()
81
+
82
+
83
+ async def encode_varint(value: int) -> bytes:
84
+ """Encode varint"""
85
+ if value < 0:
86
+ return b''
87
+
88
+ result = []
89
+ while True:
90
+ byte = value & 0x7F
91
+ value >>= 7
92
+ if value:
93
+ byte |= 0x80
94
+ result.append(byte)
95
+ if not value:
96
+ break
97
+
98
+ return bytes(result)
99
+
100
+
101
+ async def create_variant_field(field_number: int, value: int) -> bytes:
102
+ """Create variant field"""
103
+ field_header = (field_number << 3) | 0
104
+ return await encode_varint(field_header) + await encode_varint(value)
105
+
106
+
107
+ async def create_length_field(field_number: int, value) -> bytes:
108
+ """Create length-delimited field"""
109
+ field_header = (field_number << 3) | 2
110
+ encoded_value = value.encode() if isinstance(value, str) else value
111
+ return await encode_varint(field_header) + await encode_varint(len(encoded_value)) + encoded_value
112
+
113
+ async def E_AEs(Pc):
114
+ Z = bytes.fromhex(Pc)
115
+ key = bytes([89, 103, 38, 116, 99, 37, 68, 69, 117, 104, 54, 37, 90, 99, 94, 56])
116
+ iv = bytes([54, 111, 121, 90, 68, 114, 50, 50, 69, 51, 121, 99, 104, 106, 77, 37])
117
+ K = AES.new(key , AES.MODE_CBC , iv)
118
+ R = K.encrypt(pad(Z , AES.block_size))
119
+ return bytes.fromhex(R.hex())
120
+
121
+ async def create_proto(fields: Dict) -> bytearray:
122
+ """Create protobuf packet from fields"""
123
+ packet = bytearray()
124
+
125
+ for field, value in fields.items():
126
+ if isinstance(value, dict):
127
+ nested_packet = await create_proto(value)
128
+ packet.extend(await create_length_field(field, nested_packet))
129
+ elif isinstance(value, int):
130
+ packet.extend(await create_variant_field(field, value))
131
+ elif isinstance(value, str) or isinstance(value, bytes):
132
+ packet.extend(await create_length_field(field, value))
133
+
134
+ return packet
135
+
136
+
137
+ async def generate_packet(packet_hex: str, header: str, key: bytes, iv: bytes) -> bytes:
138
+ """Generate final packet with header"""
139
+ encrypted = await encrypt_packet(packet_hex, key, iv)
140
+ length_hex = await encode_hex(len(encrypted) // 2)
141
+
142
+ if len(length_hex) == 2:
143
+ header_prefix = header + "000000"
144
+ elif len(length_hex) == 3:
145
+ header_prefix = header + "00000"
146
+ elif len(length_hex) == 4:
147
+ header_prefix = header + "0000"
148
+ elif len(length_hex) == 5:
149
+ header_prefix = header + "000"
150
+ else:
151
+ header_prefix = header + "00"
152
+
153
+ return bytes.fromhex(header_prefix + length_hex + encrypted)
154
+
155
+ async def xBanner():
156
+ bN = [902000306 , 902000305 , 902000003 , 902000016 , 902000017 , 902000019 , 902031010 , 902043025 , 902043024 , 902000020 , 902000021 , 902000023 , 902000070 , 902000087 , 902000108 , 902000011 , 902049020 , 902049018 , 902049017 , 902049016 , 902049015 , 902049003 , 902033016 , 902033017 , 902033018 , 902048018 , 902000306 , 902000305 , 902000079]
157
+ return random.choice(bN)
158
+
159
+ async def create_message_packet(message: str, chat_type: int, target_id: int, chat_id: int, key: bytes, iv: bytes) -> bytes:
160
+ """Create message packet"""
161
+ try:
162
+ fields = {1: target_id , 2: target_id , 3: 2, 4: message, 5: 1735129800, 7: 2, 9: {1: "RedZedTOP1", 2: int(await xBanner()), 3: 901048018, 4: 330, 5: 909034009, 8: "RedZedTOP1", 10: 1, 11: 1, 13: {1: 2}, 14: {1: 12484827014, 2: 8, 3: "\u0010\u0015\b\n\u000b\u0013\f\u000f\u0011\u0004\u0007\u0002\u0003\r\u000e\u0012\u0001\u0005\u0006"}, 12: 0}, 10: "en", 13: {3: 1}}
163
+
164
+ packet = (await create_proto(fields)).hex()
165
+ packet = "080112" + await encode_uid(len(packet) // 2) + packet
166
+
167
+ return await generate_packet(packet, '1215', key, iv)
168
+ except Exception as e:
169
+ print(e)
170
+
171
+
172
+
173
+
174
+ async def decode_whisper_message(hex_packet: str) -> Optional[Dict[str, Any]]:
175
+ """Decode whisper message"""
176
+ try:
177
+ packet = bytes.fromhex(hex_packet)
178
+ proto = ParaHex_pb2.DecodeWhisper()
179
+ proto.ParseFromString(packet)
180
+
181
+ return {
182
+ 'uid': proto.Data.uid,
183
+ 'chat_id': proto.Data.Chat_ID,
184
+ 'chat_type': proto.Data.chat_type,
185
+ 'message': proto.Data.msg,
186
+ 'nickname': proto.Data.Details.Nickname if proto.Data.HasField('Details') else None,
187
+ 'profile_pic': proto.Data.Platform_Info.profile_pic_url if proto.Data.HasField('Platform_Info') else None
188
+ }
189
+ except Exception as e:
190
+ print(f"Decode error: {e}")
191
+ return None