Exemple #1
0
    def decode(cls, message: Msg) -> Optional[Event]:
        """Buddy Message Decoder.

        Note:
            Source:
            com.tencent.mobileqq.service.message.codec.decoder.buddyMessage.BuddyMessageDecoder
        """
        sub_decoders: Dict[int, Callable[[Msg], Optional[Event]]] = {
            11: cls.decode_normal_buddy,
            # 129: OnlineFileDecoder,
            # 131: OnlineFileDecoder,
            # 133: OnlineFileDecoder,
            # 169: OfflineFileDecoder,
            175: cls.decode_normal_buddy,
            # 241: OfflineFileDecoder,
            # 242: OfflineFileDecoder,
            # 243: OfflineFileDecoder,
        }
        Decoder = sub_decoders.get(message.head.c2c_cmd, None)
        if not Decoder:
            logger.debug(
                "MessageSvc.PbGetMsg: BuddyMessageDecoder cannot "
                f"decode message with c2c_cmd {message.head.c2c_cmd}"
            )
            return
        return Decoder(message)
Exemple #2
0
    async def receive(self):
        """Receive data from connection reader and store it in sequence future.

        Note:
            Source: com.tencent.mobileqq.msf.core.auth.n.a
        """
        while self.connected:
            try:
                length: int = (struct.unpack(
                    ">i", await self.connection.read_bytes(4))[0] - 4)
                # FIXME: length < 0 ?
                data = await self.connection.read_bytes(length)
                packet = IncomingPacket.parse(
                    data,
                    self._key,
                    self._siginfo.d2key,
                    self._siginfo.wt_session_ticket_key,
                )
                logger.debug(
                    f"<-- {packet.seq} ({packet.ret_code}): {packet.command_name}"
                )
                # do not block receive
                asyncio.create_task(self._handle_incoming_packet(packet))
            except ConnectionAbortedError:
                logger.debug(f"Client {self.uin} connection closed")
            except Exception as e:
                logger.exception(e)
Exemple #3
0
async def handle_config_push_request(
        client: "Client", packet: IncomingPacket) -> ConfigPushCommand:
    command = ConfigPushCommand.decode_push_req(
        packet.uin,
        packet.seq,
        packet.ret_code,
        packet.command_name,
        packet.data,
    )
    if isinstance(command, SsoServerPushCommand):
        logger.debug(f"ConfigPush: Got new server addresses.")
    elif isinstance(command, FileServerPushCommand):
        client._file_storage_info = command.list

    if isinstance(command, _ConfigPushCommandBase):
        resp_packet = encode_config_push_response(
            client.uin,
            command.seq,
            client._session_id,
            client._siginfo.d2key,
            command.type,
            command.jcebuf,
            command.large_seq,
        )
        await client.send(command.seq, "ConfigPushSvc.PushResp", resp_packet)

    return command
Exemple #4
0
    async def send(self, seq: int, command_name: str,
                   packet: Union[bytes, Packet]) -> None:
        """Send a packet with the given sequence but not wait for the response.

        Args:
            seq (int): Sequence number.
            command_name (str): Command name of the packet.
            packet (Union[bytes, Packet]): Packet to send.

        Returns:
            None.
        """
        logger.debug(f"--> {seq}: {command_name}")
        await self.connection.awrite(packet)
Exemple #5
0
async def handle_get_message(client: "Client",
                             packet: IncomingPacket) -> "GetMessageCommand":
    """Handle Pb Get Message response.

    Note:
        Source: c2c 1002

        com.tencent.imcore.message.C2CMessageProcessor.b

        com.tencent.imcore.message.C2CMessageProcessor.a

        com.tencent.imcore.message.C2CMessageProcessorCallback.a

        com.tencent.imcore.message.DecodeMsg.a
    """
    resp = GetMessageCommand.decode_response(
        packet.uin,
        packet.seq,
        packet.ret_code,
        packet.command_name,
        packet.data,
    )
    if isinstance(resp, GetMessageSuccess):
        # cache last cookie
        if resp.response.rsp_type == 0:
            client._sync_cookie = resp.response.sync_cookie
            client._pubaccount_cookie = resp.response.sync_cookie
        elif resp.response.rsp_type == 1:
            client._sync_cookie = resp.response.sync_cookie
        elif resp.response.rsp_type == 2:
            client._pubaccount_cookie = resp.response.pubaccount_cookie

        delete_msgs: List[PbDeleteMsgReq.MsgItem] = []
        for pair_msgs in resp.response.uin_pair_msgs:
            last_read_time = pair_msgs.last_read_time & 0xFFFFFFFF
            for message in pair_msgs.msg:
                delete_msgs.append(
                    PbDeleteMsgReq.MsgItem(
                        from_uin=message.head.from_uin,
                        to_uin=message.head.to_uin,
                        type=message.head.type,
                        seq=message.head.seq,
                        uid=message.head.uid,
                    ))

                if message.head.to_uin != client.uin:
                    continue
                if message.head.time < last_read_time:
                    continue

                key = (f"{message.head.from_uin}"
                       f"{message.head.type}"
                       f"{message.head.time}")
                if key in client._msg_cache:
                    continue
                client._msg_cache[key] = None

                # drop messages when init
                if client._init_flag:
                    continue

                msg_type = message.head.type
                Decoder = MESSAGE_DECODERS.get(msg_type, None)
                if not Decoder:
                    logger.debug("MessageSvc.PbGetMsg: "
                                 f"Received unknown message type {msg_type}.")
                    continue
                decoded_message = Decoder(message)
                if decoded_message:
                    client.dispatch_event(decoded_message)

        if delete_msgs:
            seq = client.next_seq()
            del_packet = encode_delete_message(
                seq,
                client._session_id,
                client.uin,
                client._siginfo.d2key,
                delete_msgs,
            )
            await client.send(seq, "MessageSvc.PbDeleteMsg", del_packet)

        if resp.response.sync_flag < SyncFlag.STOP:
            seq = client.next_seq()
            continue_packet = encode_get_message(
                seq,
                client._session_id,
                client.uin,
                client._siginfo.d2key,
                request_type=resp.response.rsp_type,
                sync_flag=resp.response.sync_flag,
                sync_cookie=resp.response.rsp_type != 2 and client._sync_cookie
                or None,
                pubaccount_cookie=resp.response.rsp_type == 2
                and client._pubaccount_cookie or None,
            )
            await client.send_and_wait(seq, "MessageSvc.PbGetMsg",
                                       continue_packet)
    return resp