Example #1
0
def encode_register(
    seq: int,
    session_id: bytes,
    ksid: bytes,
    uin: int,
    tgt: bytes,
    d2: bytes,
    d2key: bytes,
    status: Union[int, OnlineStatus],
    reg_push_reason: Union[str, RegPushReason],
) -> Packet:
    """Build status service register packet.

    Called in ``com.tencent.mobileqq.msf.core.push.e.a``.

    command name: ``StatSvc.register``

    Note:
        Source: com.tencent.mobileqq.msf.core.push.e.a

    Args:
        seq (int): Packet sequence.
        session_id (bytes): Session ID.
        ksid (bytes): KSID of client.
        uin (int): User QQ number.
        tgt (bytes): Siginfo tgt.
        d2 (bytes): Siginfo d2.
        d2key (bytes): Siginfo d2 key.
        status (Union[int, OnlineStatus]): Online status.
        reg_push_reason (Union[str, RegPushReason]): Reg push reason.
        battery_status (Optional[int], optional): Battery capacity.
            Defaults to None.
        is_power_connected (bool, optional): Is power connected to phone.
            Defaults to False.

    Returns:
        Packet: Register packet.
    """
    COMMAND_NAME = "StatSvc.register"
    SUB_APP_ID = APK_INFO.sub_app_id

    svc = _encode_svc_request(uin, status, reg_push_reason)
    payload = SvcReqRegister.to_bytes(0, svc)
    req_packet = RequestPacketVersion3(
        servant_name="PushService",
        func_name="SvcReqRegister",
        data=types.MAP({types.STRING("SvcReqRegister"): types.BYTES(payload)}),
    ).encode()
    sso_packet = CSsoBodyPacket.build(
        seq,
        SUB_APP_ID,
        COMMAND_NAME,
        DEVICE.imei,
        session_id,
        ksid,
        body=req_packet,
        extra_data=tgt,
    )
    packet = CSsoDataPacket.build(uin, 1, sso_packet, key=d2key, extra_data=d2)
    return packet
Example #2
0
def encode_force_offline_response(
    seq: int,
    session_id: bytes,
    ksid: bytes,
    uin: int,
    tgt: bytes,
    d2: bytes,
    d2key: bytes,
    req_uin: int,
    seq_no: int,
) -> Packet:
    """Build status service msf offline response packet.

    Called in ``com.tencent.mobileqq.msf.core.af.a``.

    command name: ``StatSvc.RspMSFForceOffline``

    Note:
        Source: com.tencent.mobileqq.msf.core.af.a

    Args:
        seq (int): Packet sequence.
        session_id (bytes): Session ID.
        ksid (bytes): KSID of client.
        uin (int): User QQ number.
        tgt (bytes): Siginfo tgt.
        d2 (bytes): Siginfo d2.
        d2key (bytes): Siginfo d2 key.
        req_uin (int): Request offline uin.
        seq_no (int): Request sequence number.

    Returns:
        Packet: msf force offline response packet.
    """
    COMMAND_NAME = "StatSvc.RspMSFForceOffline"
    SUB_APP_ID = APK_INFO.sub_app_id

    resp = ResponseMSFForceOffline(uin=req_uin, seq_no=seq_no, c=bytes(1))
    payload = ResponseMSFForceOffline.to_bytes(0, resp)
    resp_packet = RequestPacketVersion3(
        servant_name="StatSvc",
        func_name="RspMSFForceOffline",
        data=types.MAP(
            {types.STRING("RspMSFForceOffline"): types.BYTES(payload)}
        ),
    ).encode()
    sso_packet = CSsoBodyPacket.build(
        seq,
        SUB_APP_ID,
        COMMAND_NAME,
        DEVICE.imei,
        session_id,
        ksid,
        body=resp_packet,
        extra_data=tgt,
    )
    packet = CSsoDataPacket.build(uin, 1, sso_packet, key=d2key, extra_data=d2)
    return packet
Example #3
0
def encode_set_status(
    seq: int,
    session_id: bytes,
    uin: int,
    d2key: bytes,
    status: Union[int, OnlineStatus],
    battery_status: Optional[int] = None,
    is_power_connected: bool = False,
) -> Packet:
    """Build status service register packet.

    Called in ``com.tencent.mobileqq.msf.core.push.e.a``.

    command name: ``StatSvc.SetStatusFromClient``

    Note:
        Source: com.tencent.mobileqq.msf.core.push.e.a

    Args:
        seq (int): Packet sequence.
        session_id (bytes): Session ID.
        uin (int): User QQ number.
        d2key (bytes): Siginfo d2 key.
        status (Union[int, OnlineStatus]): Online status.
        reg_push_reason (Union[str, RegPushReason]): Reg push reason.
        battery_status (Optional[int], optional): Battery capacity.
            Only works when status is :obj:`.OnlineStatus.Battery`. Defaults to None.
        is_power_connected (bool, optional): Is power connected to phone.
            Only works when status is :obj:`.OnlineStatus.Battery`. Defaults to False.

    Returns:
        Packet: Register packet.
    """
    COMMAND_NAME = "StatSvc.SetStatusFromClient"
    SUB_APP_ID = APK_INFO.sub_app_id

    svc = _encode_svc_request(
        uin,
        status,
        RegPushReason.SetOnlineStatus,
        ((status == OnlineStatus.Battery) or None) and battery_status,
        (status == OnlineStatus.Battery) and is_power_connected,
    )
    payload = SvcReqRegister.to_bytes(0, svc)
    req_packet = RequestPacketVersion3(
        servant_name="PushService",
        func_name="SvcReqRegister",
        data=types.MAP({types.STRING("SvcReqRegister"): types.BYTES(payload)}),
    ).encode()
    packet = UniPacket.build(
        uin, seq, COMMAND_NAME, session_id, 1, req_packet, d2key
    )
    return packet
Example #4
0
def encode_get_troop_member_list(
    seq: int,
    session_id: bytes,
    uin: int,
    d2key: bytes,
    group_uin: int,
    group_code: int,
    next_uin: int = 0,
) -> Packet:
    """Build get troop member list packet.

    Called in ``com.tencent.mobileqq.troop.handler.TroopMemberInfoHandler.a``.

    command name: ``friendlist.GetTroopMemberListReq``

    Note:
        Source: com.tencent.mobileqq.service.troop.TroopSender.c

    Args:
        seq (int): Packet sequence.
        session_id (bytes): Session ID.
        uin (int): User QQ number.
        d2key (bytes): Siginfo d2 key.
        group_uin (int): Group uin number.
        group_code (int): Group code number.
        next_uin (int, optional): Next uin number. Defaults to 0.

    Returns:
        Packet: getTroopMemberList simplified packet.
    """
    COMMAND_NAME = "friendlist.GetTroopMemberListReq"

    req = TroopMemberListReq(
        uin=uin,
        group_code=group_code,
        next_uin=next_uin,
        group_uin=group_uin,
        version=3,
    )
    payload = TroopMemberListReq.to_bytes(0, req)
    req_packet = RequestPacketVersion3(
        servant_name="mqq.IMService.FriendListServiceServantObj",
        func_name="GetTroopMemberListReq",
        data=types.MAP({types.STRING("GTML"): types.BYTES(payload)}),
    ).encode()
    packet = UniPacket.build(uin, seq, COMMAND_NAME, session_id, 1, req_packet,
                             d2key)
    return packet
Example #5
0
    def test_map_encode(self):
        raw: Dict[types.JceType, types.JceType] = {
            types.STRING1("one"): types.STRING1("foo"),
            types.STRING1("two"): types.STRING1("bar")
        }
        encoded = bytes.fromhex("18 00 02 06 03 6F 6E 65 16 03 66 "
                                "6F 6F 06 03 74 77 6F 16 03 62 61 72")
        self.assertEqual(types.MAP.to_bytes(1, raw), encoded)

        raw: Dict[types.JceType, types.JceType] = {
            types.STRING1("one"):
            types.MAP({types.STRING1("two"): types.BYTES("foo".encode())})
        }
        encoded = bytes.fromhex("18 00 01 06 03 6F 6E 65 18 00 01 "
                                "06 03 74 77 6F 1D 00 00 03 66 6F 6F")
        self.assertEqual(types.MAP.to_bytes(1, raw), encoded)
Example #6
0
def encode_get_troop_list(
    seq: int,
    session_id: bytes,
    uin: int,
    d2key: bytes,
    cookies: Optional[bytes] = None,
) -> Packet:
    """Build get troop list v2 simplified packet.

    Called in ``com.tencent.mobileqq.troop.handler.TroopListHandler.a``.

    command name: ``friendlist.GetTroopListReqV2``

    Note:
        Source: com.tencent.mobileqq.service.troop.TroopSender.b

    Args:
        seq (int): Packet sequence.
        session_id (bytes): Session ID.
        uin (int): User QQ number.
        d2key (bytes): Siginfo d2 key.
        cookies (Optional[bytes], optional): Cookie vector. Defaults to None.

    Returns:
        Packet: GetTroopListReqV2 simplified packet.
    """
    COMMAND_NAME = "friendlist.GetTroopListReqV2"

    req = TroopListReqV2Simplify(
        uin=uin,
        get_msf_msg_flag=False,
        cookies=cookies,
        group_flag_ext=bytes([1]),
        version=9,
        version_num=1,
        get_long_group_name=True,
    )
    payload = TroopListReqV2Simplify.to_bytes(0, req)
    req_packet = RequestPacketVersion3(
        servant_name="mqq.IMService.FriendListServiceServantObj",
        func_name="GetTroopListReqV2Simplify",
        data=types.MAP(
            {types.STRING("GetTroopListReqV2Simplify"): types.BYTES(payload)}),
    ).encode()
    packet = UniPacket.build(uin, seq, COMMAND_NAME, session_id, 1, req_packet,
                             d2key)
    return packet
Example #7
0
    def test_map_decode(self):
        raw: Dict[types.JceType, types.JceType] = {
            types.STRING1("one"): types.STRING1("foo"),
            types.STRING1("two"): types.STRING1("bar")
        }
        encoded = bytes.fromhex("18 00 02 06 03 6F 6E 65 16 03 66 "
                                "6F 6F 06 03 74 77 6F 16 03 62 61 72")
        _, decoded, _ = JceDecoder.decode_single(encoded)
        self.assertEqual(types.MAP.validate(decoded), raw)

        raw: Dict[types.JceType, types.JceType] = {
            types.STRING1("one"):
            types.MAP({types.STRING1("two"): types.BYTES("foo".encode())})
        }
        encoded = bytes.fromhex("18 00 01 06 03 6F 6E 65 18 00 01 "
                                "06 03 74 77 6F 1D 00 00 03 66 6F 6F")
        _, decoded, _ = JceDecoder.decode_single(encoded)
        self.assertEqual(types.MAP.validate(decoded), raw)
Example #8
0
def encode_config_push_response(
    uin: int,
    seq: int,
    session_id: bytes,
    d2key: bytes,
    type: int,
    jcebuf: bytes,
    large_seq: int,
) -> Packet:
    """Build config push response packet.

    command name: ``ConfigPushSvc.PushResp``

    Note:
        Source: com.tencent.mobileqq.msf.core.a.c.b

    Args:
        uin (int): User QQ number.
        seq (int): Packet sequence.
        session_id (bytes): Session ID.
        d2key (bytes): Siginfo d2 key.
        type (int): ConfigPushSvc request type.
        jcebuf (bytes): ConfigPushSvc request jcebuf.
        large_seq (int): ConfigPushSvc request large_seq.
    """
    COMMAND_NAME = "ConfigPushSvc.PushResp"

    resp = PushResp(type=type,
                    jcebuf=jcebuf if type == 3 else None,
                    large_seq=large_seq)
    payload = PushResp.to_bytes(0, resp)
    resp_packet = RequestPacketVersion3(
        servant_name="QQService.ConfigPushSvc.MainServant",
        func_name="PushResp",
        data=types.MAP({types.STRING("PushResp"): types.BYTES(payload)}),
    ).encode()
    packet = UniPacket.build(uin, seq, COMMAND_NAME, session_id, 1,
                             resp_packet, d2key)
    return packet
Example #9
0
async def get_sso_list() -> SsoServerResponse:
    """Do sso server list request and return the response.

    Note:
        Source: com.tencent.mobileqq.msf.core.a.f.run

    Returns:
        SsoServerResponse: Sso server list response

    Raises:
        SsoServerException: Get sso server list failed.
    """
    device = get_device()
    protocol = get_protocol()
    key = bytes([
        0xF0,
        0x44,
        0x1F,
        0x5F,
        0xF4,
        0x2D,
        0xA5,
        0x8F,
        0xDC,
        0xF7,
        0x94,
        0x9A,
        0xBA,
        0x62,
        0xD4,
        0x11,
    ])
    payload = SsoServerRequest.to_bytes(
        0, SsoServerRequest(app_id=protocol.app_id, imei=device.imei))
    req_packet = RequestPacketVersion3(
        servant_name="HttpServerListReq",
        func_name="HttpServerListReq",
        data=types.MAP(
            {types.STRING("HttpServerListReq"): types.BYTES(payload)}),
    ).encode(with_length=True)
    buffer: bytes = qqtea_encrypt(req_packet, key)
    async with connect("configsvr.msf.3g.qq.com", 443, ssl=True) as conn:
        query = (b"POST /configsvr/serverlist.jsp HTTP/1.1\r\n"
                 b"Host: configsvr.msf.3g.qq.com\r\n"
                 b"User-Agent: QQ/8.4.1.2703 CFNetwork/1126\r\n"
                 b"Net-Type: Wifi\r\n"
                 b"Accept: */*\r\n"
                 b"Connection: close\r\n"
                 b"Content-Type: application/octet-stream\r\n"
                 b"Content-Length: " + str(len(buffer)).encode() + b"\r\n"
                 b"\r\n" + buffer)
        conn.write(query)
        conn.write_eof()
        resp_bytes = await conn.read_all()
        response = http.client.HTTPResponse(
            _FakeSocket(resp_bytes)  # type: ignore
        )
        response.begin()

    if response.status != 200:
        raise SsoServerException(
            f"Get sso server list failed with response code {response.status}")
    data: bytes = qqtea_decrypt(response.read(), key)
    resp_packet = RequestPacketVersion3.decode(data)
    server_info = SsoServerResponse.decode(
        resp_packet.data["HttpServerListRes"][1:-1]  # type: ignore
    )
    return server_info
Example #10
0
def encode_get_friend_list(
    seq: int,
    session_id: bytes,
    uin: int,
    d2key: bytes,
    friend_index: int = 0,
    friend_count: int = 0,
    group_index: int = 0,
    group_count: int = 0,
) -> Packet:
    """Build get friend list packet.

    Called in ``com.tencent.mobileqq.service.friendlist.FriendListService.k``.

    command name: ``friendlist.GetFriendListReq``

    Note:
        Source: com.tencent.mobileqq.service.friendlist.FriendListService.m

    Args:
        seq (int): Packet sequence.
        session_id (bytes): Session ID.
        uin (int): User QQ number.
        d2key (bytes): Siginfo d2 key.
        friend_index (int): Start index of friend list.
        friend_count (int): Number of friends to list.
        group_index (int): Start index of group list.
        group_count (int): Number of groups to list.

    Returns:
        Packet: GetFriendListReq packet.
    """
    COMMAND_NAME = "friendlist.GetFriendListReq"

    req = FriendListReq(
        request_type=3,
        if_reflush=friend_index <= 0,
        uin=uin,
        start_index=friend_index,
        friend_count=friend_count,
        group_id=bytes(1),
        if_get_group_info=group_count > 0,
        group_start_index=group_index,
        group_count=group_count,
        if_get_msf_group=False,
        if_show_term_type=True,
        version=31,
        d50_req=ReqBody(
            appid=1002,
            req_music_switch=1,
            req_mutualmark_alienation=1,
            req_ksing_switch=1,
            req_mutualmark_lbsshare=1,
            req_aio_quick_app=1,
        ).SerializeToString(),
        sns_type_list=[13580, 13581, 13582],
    )
    payload = FriendListReq.to_bytes(0, req)
    req_packet = RequestPacketVersion3(
        servant_name="mqq.IMService.FriendListServiceServantObj",
        func_name="GetFriendListReq",
        data=types.MAP({types.STRING("FL"): types.BYTES(payload)}),
    ).encode()
    packet = UniPacket.build(uin, seq, COMMAND_NAME, session_id, 1, req_packet,
                             d2key)
    return packet