Skip to content

Commit

Permalink
fix: send_msg
Browse files Browse the repository at this point in the history
  • Loading branch information
lumina37 committed Feb 4, 2023
1 parent d0902f8 commit d7c82ce
Show file tree
Hide file tree
Showing 21 changed files with 271 additions and 32 deletions.
2 changes: 1 addition & 1 deletion aiotieba/__version__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "3.1.5a1"
__version__ = "3.1.5a2"
5 changes: 3 additions & 2 deletions aiotieba/client/_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -2059,11 +2059,12 @@ async def send_msg(self, _id: Union[str, int], content: str) -> bool:

try:
await self.websocket.init_websocket()
self.websocket._record_id += 1

from . import send_msg

proto = send_msg.pack_proto(user_id, content)
body = await self.websocket.send(proto, 205001, timeout=5.0)
proto = send_msg.pack_proto(user_id, content, self.websocket._record_id)
body = await self.websocket.send(proto, send_msg.CMD, encrypt=False, timeout=5.0)
send_msg.parse_body(body)

except Exception as err:
Expand Down
8 changes: 4 additions & 4 deletions aiotieba/client/_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,9 @@ class TbCore(object):
'_loop',
]

main_version: str = "12.35.1.2" # 最新版本
# no_fold_version: str = "12.12.1.0" # 最后一个回复列表不发生折叠的版本
post_version: str = "9.1.0.0" # 极速版
main_version = "12.36.0.1" # 最新版本
# no_fold_version = "12.12.1.0" # 最后一个回复列表不发生折叠的版本
post_version = "9.1.0.0" # 极速版

def __init__(
self,
Expand Down Expand Up @@ -394,7 +394,7 @@ def aes_ecb_chiper(self):
"""

if self._aes_ecb_chiper is None:
salt = b'\xa4\x0b\xc84\xd6\x95\xf3\x13'
salt = b'\xa4\x0b\xc8\x34\xd6\x95\xf3\x13'
ws_secret_key = hashlib.pbkdf2_hmac('sha1', b"0123456789abcdefghyjklmnopqrstu", salt, 5, 32)
self._aes_ecb_chiper = AES.new(ws_secret_key, AES.MODE_ECB)

Expand Down
10 changes: 9 additions & 1 deletion aiotieba/client/_websocket/_api.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
import time
from typing import List

from .._core import TbCore
from .._exception import TiebaServerError
from .._helper import jsonlib
from ..get_group_msg import MsgGroup
from .protobuf import UpdateClientInfoReqIdl_pb2, UpdateClientInfoResIdl_pb2

CMD = 1001


def pack_proto(core: TbCore, secret_key: str) -> bytes:
req_proto = UpdateClientInfoReqIdl_pb2.UpdateClientInfoReqIdl()
Expand All @@ -27,9 +31,13 @@ def pack_proto(core: TbCore, secret_key: str) -> bytes:
return req_proto.SerializeToString()


def parse_body(body: bytes) -> None:
def parse_body(body: bytes) -> List[MsgGroup]:
res_proto = UpdateClientInfoResIdl_pb2.UpdateClientInfoResIdl()
res_proto.ParseFromString(body)

if code := res_proto.error.errorno:
raise TiebaServerError(code, res_proto.error.errmsg)

groups = [MsgGroup(g.groupType, g.lastMsgId) for g in res_proto.data.groupInfo]

return groups
28 changes: 22 additions & 6 deletions aiotieba/client/_websocket/_classdef.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ class Websocket(object):

__slots__ = [
'_core',
'_record_id',
'_res_waiter',
'_callback',
'_client_ws',
Expand All @@ -49,6 +50,7 @@ class Websocket(object):

def __init__(self, connector: aiohttp.TCPConnector, core: TbCore) -> None:
self._core = core
self._record_id = None
self._res_waiter = weakref.WeakValueDictionary()
self._callback: Dict[int, TypeWebsocketCallback] = {}

Expand Down Expand Up @@ -130,7 +132,7 @@ async def init_websocket(self) -> None:
if not self.is_aviliable:
await self.__create_websocket(heartbeat=None)

from ._api import pack_proto, parse_body
from . import _api

pub_key = binascii.a2b_base64(
b"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwQpwBZxXJV/JVRF/uNfyMSdu7YWwRNLM8+2xbniGp2iIQHOikPpTYQjlQgMi1uvq1kZpJ32rHo3hkwjy2l0lFwr3u4Hk2Wk7vnsqYQjAlYlK0TCzjpmiI+OiPOUNVtbWHQiLiVqFtzvpvi4AU7C1iKGvc/4IS45WjHxeScHhnZZ7njS4S1UgNP/GflRIbzgbBhyZ9kEW5/OO5YfG1fy6r4KSlDJw4o/mw5XhftyIpL+5ZBVBC6E1EIiP/dd9AbK62VV1PByfPMHMixpxI3GM2qwcmFsXcCcgvUXJBa9k6zP8dDQ3csCM2QNT+CQAOxthjtp/TFWaD7MzOdsIYb3THwIDAQAB"
Expand All @@ -139,10 +141,13 @@ async def init_websocket(self) -> None:
rsa_chiper = PKCS1_v1_5.new(pub_key)
secret_key = rsa_chiper.encrypt(self._core.aes_ecb_sec_key)

proto = pack_proto(self._core, secret_key)
proto = _api.pack_proto(self._core, secret_key)
body = await self.send(proto, cmd=_api.CMD, compress=False, encrypt=False, timeout=5.0)
groups = _api.parse_body(body)

body = await self.send(proto, cmd=1001, compress=False, encrypt=False, timeout=5.0)
parse_body(body)
for group in groups:
if group._group_type == 6: # 私信组别类型为6
self._record_id = group._last_msg_id * 100

@property
def is_aviliable(self) -> bool:
Expand All @@ -155,8 +160,19 @@ def is_aviliable(self) -> bool:

return not (self._websocket is None or self._websocket.closed or self._websocket._writer.transport.is_closing())

@property
def record_id(self) -> int:
"""
用作请求参数的记录id
Returns:
int
"""

return self._record_id

async def send(
self, data: bytes, cmd: int, *, compress: bool = True, encrypt: bool = True, timeout: float
self, data: bytes, cmd: int, *, compress: bool = False, encrypt: bool = True, timeout: float
) -> bytes:
"""
将protobuf序列化结果打包发送
Expand All @@ -165,7 +181,7 @@ async def send(
data (bytes): 待发送的数据
cmd (int): 请求的cmd类型
compress (bool, optional): 是否需要gzip压缩. Defaults to False.
encrypt (bool, optional): 是否需要aes加密. Defaults to False.
encrypt (bool, optional): 是否需要aes加密. Defaults to True.
Returns:
bytes: 响应
Expand Down
21 changes: 9 additions & 12 deletions aiotieba/client/_websocket/_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@


def pack_ws_bytes(
core: TbCore, data: bytes, cmd: int, req_id: int, compress: bool = True, encrypt: bool = True
core: TbCore, data: bytes, cmd: int, req_id: int, compress: bool = False, encrypt: bool = True
) -> bytes:
"""
打包数据并添加9字节头部
Expand All @@ -19,7 +19,7 @@ def pack_ws_bytes(
cmd (int): 请求的cmd类型
req_id (int): 请求的id
compress (bool, optional): 是否需要gzip压缩. Defaults to False.
encrypt (bool, optional): 是否需要aes加密. Defaults to False.
encrypt (bool, optional): 是否需要aes加密. Defaults to True.
Returns:
bytes: 打包后的websocket数据
Expand All @@ -28,10 +28,10 @@ def pack_ws_bytes(
flag = 0x08

if compress:
flag |= 0b10000000
flag |= 0b01000000
data = gzip.compress(data, compresslevel=-1, mtime=0)
if encrypt:
flag |= 0b01000000
flag |= 0b10000000
data = pad(data, AES.block_size)
data = core.aes_ecb_chiper.encrypt(data)

Expand Down Expand Up @@ -61,15 +61,12 @@ def parse_ws_bytes(core: TbCore, data: bytes) -> Tuple[bytes, int, int]:
int: 对应请求的id
"""

if len(data) < 9:
return data, 0, 0

ws_view = memoryview(data)
flag = ws_view[0]
cmd = int.from_bytes(ws_view[1:5], 'big')
req_id = int.from_bytes(ws_view[5:9], 'big')
data_view = memoryview(data)
flag = data_view[0]
cmd = int.from_bytes(data_view[1:5], 'big')
req_id = int.from_bytes(data_view[5:9], 'big')

data = ws_view[9:].tobytes()
data = data_view[9:].tobytes()
if flag & 0b10000000:
data = core.aes_ecb_chiper.decrypt(data)
data = unpad(data, AES.block_size)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,12 @@ import "Error.proto";

message UpdateClientInfoResIdl {
Error error = 1;
message DataRes {
message GroupInfo {
int32 groupType = 20;
int64 lastMsgId = 21;
}
repeated GroupInfo groupInfo = 1;
}
DataRes data = 2;
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions aiotieba/client/get_group_msg/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from ._api import CMD, pack_proto, parse_body
from ._classdef import MsgGroup
28 changes: 28 additions & 0 deletions aiotieba/client/get_group_msg/_api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
from typing import List

from .._core import TbCore
from .._exception import TiebaServerError
from ._classdef import MsgGroup
from .protobuf import GetGroupMsgReqIdl_pb2, GetGroupMsgResIdl_pb2

CMD = 202003


def pack_proto(core: TbCore, groups: List[MsgGroup], get_type: int) -> bytes:
req_proto = GetGroupMsgReqIdl_pb2.GetGroupMsgReqIdl()
for group in groups:
group_proto = req_proto.data.groupMids.add()
group_proto.groupId = group._group_type
group_proto.lastMsgId = group._last_msg_id
req_proto.data.gettype = str(get_type)
req_proto.cuid = f"{core.cuid}|com.baidu.tieba_mini{core.post_version}"

return req_proto.SerializeToString()


def parse_body(body: bytes) -> None:
res_proto = GetGroupMsgResIdl_pb2.GetGroupMsgResIdl()
res_proto.ParseFromString(body)

if code := res_proto.error.errorno:
raise TiebaServerError(code, res_proto.error.errmsg)
38 changes: 38 additions & 0 deletions aiotieba/client/get_group_msg/_classdef.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
class MsgGroup(object):

__slots__ = [
'_group_type',
'_last_msg_id',
]

def __init__(self, group_type: int, last_msg_id: int) -> None:
self._group_type = group_type
self._last_msg_id = last_msg_id

def __repr__(self) -> str:
return str(
{
'group_type': self._group_type,
'last_msg_id': self._last_msg_id,
}
)

def group_type(self) -> int:
"""
消息组类别
Returns:
int
"""

return self._group_type

def last_msg_id(self) -> int:
"""
最后一条消息的id
Returns:
int
"""

return self._last_msg_id
15 changes: 15 additions & 0 deletions aiotieba/client/get_group_msg/protobuf/GetGroupMsgReqIdl.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// protobuf.CommitPersonalMsg.CommitPersonalMsgReqIdl
syntax = "proto3";

message GetGroupMsgReqIdl {
string cuid = 1;
message DataReq {
message GroupLastId {
int64 groupId = 1;
int64 lastMsgId = 2;
}
repeated GroupLastId groupMids = 6;
string gettype = 7;
}
DataReq data = 2;
}
29 changes: 29 additions & 0 deletions aiotieba/client/get_group_msg/protobuf/GetGroupMsgReqIdl_pb2.py

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// protobuf.CommitPersonalMsg.CommitPersonalMsgResIdl
syntax = "proto3";

import "Error.proto";

message GetGroupMsgResIdl {
Error error = 1;
}
26 changes: 26 additions & 0 deletions aiotieba/client/get_group_msg/protobuf/GetGroupMsgResIdl_pb2.py

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions aiotieba/client/push_notify/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from ._api import CMD, parse_body
14 changes: 14 additions & 0 deletions aiotieba/client/push_notify/_api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from ..get_group_msg import MsgGroup
from .protobuf import PushNotifyResIdl_pb2

CMD = 202006


def parse_body(body: bytes) -> MsgGroup:
res_proto = PushNotifyResIdl_pb2.PushNotifyResIdl()
res_proto.ParseFromString(body)

group_proto = res_proto.multiMsg[0].data
group = MsgGroup(group_proto.groupId, group_proto.msgId)

return group
Loading

0 comments on commit d7c82ce

Please sign in to comment.