diff --git a/lagrange/client/events/group.py b/lagrange/client/events/group.py index 4bdee02..480ffe4 100644 --- a/lagrange/client/events/group.py +++ b/lagrange/client/events/group.py @@ -142,3 +142,8 @@ class GroupAlbumUpdate(GroupEvent): timestamp: int image_id: str + + +@dataclass +class GroupInvite(GroupEvent): + invitor_uid: str diff --git a/lagrange/client/message/decoder.py b/lagrange/client/message/decoder.py index 9dde5e8..4b9051c 100644 --- a/lagrange/client/message/decoder.py +++ b/lagrange/client/message/decoder.py @@ -38,8 +38,9 @@ def parse_friend_info(pkg: MsgPushBody) -> tuple[int, str, int, str]: return from_uin, from_uid, to_uin, to_uid -async def parse_msg_new(client: "Client", pkg: MsgPushBody, - fri_id: Union[str, None] = None, grp_id: Union[int, None] = None) -> Sequence[Element]: +async def parse_msg_new( + client: "Client", pkg: MsgPushBody, fri_id: Union[str, None] = None, grp_id: Union[int, None] = None +) -> Sequence[Element]: if not pkg.message or not pkg.message.body: if pkg.content_head.sub_type == 4: data = FileExtra.decode(pkg.message.buf2) @@ -66,7 +67,7 @@ async def parse_msg_new(client: "Client", pkg: MsgPushBody, time=ptt.time, file_key=ptt.group_file_key if ptt.group_file_key else ptt.friend_file_key, qmsg=None, - url=await client.fetch_audio_url(file_key, uid=fri_id, gid=grp_id) + url=await client.fetch_audio_url(file_key, uid=fri_id, gid=grp_id), ) ] el: list[Elems] = rich.content @@ -174,9 +175,7 @@ async def parse_msg_new(client: "Client", pkg: MsgPushBody, size=index.info.size, id=0, md5=bytes.fromhex(index.info.hash), - text=extra.biz_info.pic.summary - if extra.biz_info.pic.summary - else "[图片]", + text=extra.biz_info.pic.summary if extra.biz_info.pic.summary else "[图片]", width=index.info.width, height=index.info.height, url=url, @@ -196,7 +195,7 @@ async def parse_msg_new(client: "Client", pkg: MsgPushBody, file_size=file_extra.inner.info.file_size, file_name=file_extra.inner.info.file_name, file_md5=file_extra.inner.info.file_md5, - file_id=file_extra.inner.info.file_id + file_id=file_extra.inner.info.file_id, ) ) elif raw.rich_msg: @@ -208,16 +207,10 @@ async def parse_msg_new(client: "Client", pkg: MsgPushBody, content = zlib.decompress(jr[1:]) else: content = jr[1:] - msg_chain.append( - elems.Service(id=sid, raw=content, text=f"[service:{sid}]") - ) + msg_chain.append(elems.Service(id=sid, raw=content, text=f"[service:{sid}]")) ignore_next = True elif raw.open_data: - msg_chain.append( - elems.Raw( - text=f"[raw:{len(raw.open_data.data)}]", data=raw.open_data.data - ) - ) + msg_chain.append(elems.Raw(text=f"[raw:{len(raw.open_data.data)}]", data=raw.open_data.data)) elif raw.src_msg: # msg source info src = raw.src_msg msg_text = "" @@ -284,7 +277,7 @@ async def parse_msg_new(client: "Client", pkg: MsgPushBody, width=video.width, height=video.height, qmsg=None, - url="" # TODO: fetch video url + url="", # TODO: fetch video url ) ) else: diff --git a/lagrange/client/server_push/msg.py b/lagrange/client/server_push/msg.py index 8d9bdf7..1c9f8d1 100644 --- a/lagrange/client/server_push/msg.py +++ b/lagrange/client/server_push/msg.py @@ -15,12 +15,14 @@ MemberRecallMsg, GroupSub20Head, PBGroupAlbumUpdate, + PBGroupInvite, ) from lagrange.utils.binary.protobuf import proto_decode, ProtoStruct, proto_encode from lagrange.utils.binary.reader import Reader from lagrange.utils.operator import unpack_dict, timestamp from ..events.group import ( + GroupInvite, GroupMemberGotSpecialTitle, GroupMemberJoined, GroupMemberJoinRequest, @@ -58,7 +60,8 @@ async def msg_push_handler(client: "Client", sso: SSOPacket): if typ == 82: # grp msg return await parse_grp_msg(client, pkg) elif typ in [166, 208, 529]: # frd msg - return await parse_friend_msg(client, pkg) + if pkg.message: + return await parse_friend_msg(client, pkg) elif typ == 33: # member joined pb = MemberChanged.decode(pkg.message.buf2) return GroupMemberJoined( @@ -78,16 +81,15 @@ async def msg_push_handler(client: "Client", sso: SSOPacket): ) elif typ == 84: pb = MemberJoinRequest.decode(pkg.message.buf2) - return GroupMemberJoinRequest( - grp_id=pb.grp_id, uid=pb.uid, answer=pb.request_field - ) + return GroupMemberJoinRequest(grp_id=pb.grp_id, uid=pb.uid, answer=pb.request_field) + elif typ == 87: + pb = PBGroupInvite.decode(pkg.message.buf2) + return GroupInvite(grp_id=pb.gid, invitor_uid=pb.invitor_uid) elif typ == 525: pb = MemberInviteRequest.decode(pkg.message.buf2) if pb.cmd == 87: inn = pb.info.inner - return GroupMemberJoinRequest( - grp_id=inn.grp_id, uid=inn.uid, invitor_uid=inn.invitor_uid - ) + return GroupMemberJoinRequest(grp_id=inn.grp_id, uid=inn.uid, invitor_uid=inn.invitor_uid) elif typ == 0x210: # friend event / group file upload notice event logger.debug(f"unhandled friend event / group file upload notice event: {pkg}") # TODO: paste elif typ == 0x2DC: # grp event, 732 @@ -109,9 +111,7 @@ async def msg_push_handler(client: "Client", sso: SSOPacket): grp_id, attrs["uin_str1"], attrs["uin_str2"], - attrs["action_str"] - if "action_str" in attrs - else attrs["alt_str1"], # ? + attrs["action_str"] if "action_str" in attrs else attrs["alt_str1"], # ? attrs["suffix_str"], attrs, pb.body.attrs_xml, @@ -126,9 +126,7 @@ async def msg_push_handler(client: "Client", sso: SSOPacket): pb.body.attrs_xml, ) else: - raise ValueError( - f"unknown type({pb.body.type}) on GroupSub20: {attrs}" - ) + raise ValueError(f"unknown type({pb.body.type}) on GroupSub20: {attrs}") else: # print(pkg.encode().hex(), 2) return @@ -174,9 +172,7 @@ async def msg_push_handler(client: "Client", sso: SSOPacket): elif pb.flag == 23: # 群幸运字符? pass elif pb.flag == 37: # 群相册上传(手Q专用:() - _, pb = unpack( - pkg.message.buf2, PBGroupAlbumUpdate - ) # 塞 就硬塞,可以把你的顾辉盒也给塞进来 + _, pb = unpack(pkg.message.buf2, PBGroupAlbumUpdate) # 塞 就硬塞,可以把你的顾辉盒也给塞进来 q = dict(parse_qsl(pb.body.args)) return GroupAlbumUpdate( grp_id=pb.grp_id, @@ -184,9 +180,7 @@ async def msg_push_handler(client: "Client", sso: SSOPacket): image_id=q["i"], ) else: - raise ValueError( - f"Unknown subtype_12 flag: {pb.flag}: {pb.body.hex() if pb.body else pb}" - ) + raise ValueError(f"Unknown subtype_12 flag: {pb.flag}: {pb.body.hex() if pb.body else pb}") elif sub_typ == 17: # recall grp_id, pb = unpack(pkg.message.buf2, MemberRecallMsg) @@ -214,9 +208,7 @@ async def msg_push_handler(client: "Client", sso: SSOPacket): "unknown sub_type %d: %s" % ( sub_typ, - pkg.message.buf2.hex() - if getattr(pkg.message, "buf2", None) - else pkg, + pkg.message.buf2.hex() if getattr(pkg.message, "buf2", None) else pkg, ) ) else: diff --git a/lagrange/pb/status/group.py b/lagrange/pb/status/group.py index 7885075..fb7d59c 100644 --- a/lagrange/pb/status/group.py +++ b/lagrange/pb/status/group.py @@ -106,9 +106,7 @@ class GroupSub16Head(ProtoStruct): timestamp: int = proto_field(2, default=0) uin: Optional[int] = proto_field(4, default=None) body: Optional[bytes] = proto_field(5, default=None) - flag: int = proto_field( - 13 - ) # 12: renamed, 6: set special_title, 13: unknown, 35: set reaction + flag: int = proto_field(13) # 12: renamed, 6: set special_title, 13: unknown, 35: set reaction operator_uid: str = proto_field(21, default="") f44: Optional[PBGroupReaction] = proto_field(44, default=None) # set reaction only @@ -141,3 +139,24 @@ class PBGroupAlbumUpdate(ProtoStruct): grp_id: int = proto_field(4) # f13: 37 body: PBGroupAlbumUpdateBody = proto_field(46) + + +# class InviteInner_what(ProtoStruct): +# f1: int = proto_field(1) # 0 +# f3: int = proto_field(3) # 32 +# f4: bytes = proto_field(4) +# f5: int = proto_field(5) +# f6: str = proto_field(6) + + +# class InviteInfo_what(ProtoStruct): +# inner: InviteInner_what = proto_field(1) + + +class PBGroupInvite(ProtoStruct): + gid: int = proto_field(1) + f2: int = proto_field(2) # 1 + f3: int = proto_field(3) # 4 + f4: int = proto_field(4) # 0 + invitor_uid: str = proto_field(5) + invite_info: bytes = proto_field(6)