Example #1
0
class MessageSyncEvent(ThriftObject):
    # index 1: unknown struct (no fields known)
    message: Message = field(index=2, default=None)
    own_read_receipt: OwnReadReceipt = field(index=4, default=None)
    add_member: AddMember = field(index=8, default=None)
    remove_member: RemoveMember = field(index=9, default=None)
    name_change: NameChange = field(index=10, default=None)
    avatar_change: AvatarChange = field(index=11, default=None)
    thread_change: ThreadChange = field(index=17, default=None)
    read_receipt: ReadReceipt = field(index=19, default=None)
    unknown_receipt_1: UnknownReceipt1 = field(index=25, default=None)
    binary: BinaryData = field(index=42, default=None)

    def get_parts(self) -> List[Any]:
        parts = [
            self.message, self.own_read_receipt, self.add_member,
            self.remove_member, self.name_change, self.avatar_change,
            self.thread_change, self.read_receipt, self.unknown_receipt_1
        ]
        if self.binary:
            for inner_item in self.binary.parse().items:
                parts += [
                    inner_item.reaction, inner_item.extended_message,
                    inner_item.unsend_message, inner_item.extended_add_member
                ]
        return [part for part in parts if part is not None]
Example #2
0
class Reaction(ThriftObject):
    thread: ThreadKey
    message_id: str
    # index 3: unknown int32 (zero)
    reaction_sender_id: int = field(TType.I64, index=4)
    reaction: str = field(default=None)
    message_sender_id: int = field(TType.I64)
Example #3
0
class ThreadChange(ThriftObject):
    metadata: MessageMetadata
    action: ThreadChangeAction = field(TType.BINARY)
    action_data: Dict[str,
                      str] = field(TType.MAP,
                                   key_type=RecursiveType(TType.BINARY,
                                                          python_type=str),
                                   value_type=RecursiveType(TType.BINARY,
                                                            python_type=str))
Example #4
0
class ForegroundStateConfig(ThriftObject):
    in_foreground_app: bool
    in_foreground_device: bool
    keep_alive_timeout: int = field(TType.I32)
    subscribe_topics: List[str]
    subscribe_generic_topics: List[str]
    unsubscribe_topics: List[str]
    unsubscribe_generic_topics: List[str]
    request_id: int = field(TType.I64)
Example #5
0
class MarkReadRequest(ThriftObject):
    receipt_type: str = "read"
    unknown_boolean: bool = True
    # indices 3-5: ???
    group_id: int = field(TType.I64, index=6, default=None)
    user_id: int = field(TType.I64, default=None)
    # index 8: ???
    read_to: int = field(TType.I64, index=9)
    offline_threading_id: int = field(TType.I64, index=13)
Example #6
0
class Attachment(ThriftObject):
    media_id_str: str
    mime_type: str = field(default=None)
    file_name: str = field(default=None)
    media_id: int = field(TType.I64, default=None)
    file_size: int = field(TType.I64, default=None)
    # index 6: ???
    extensible_media: str = field(default=None, index=7)
    # indices 8 and 9: ???
    image_info: ImageInfo = field(default=None, index=10)
    video_info: VideoInfo = field(default=None)
    audio_info: AudioInfo = field(default=None)
    # can contain a dash_manifest key with some XML as the value
    # or fbtype key with a number as value
    extra_metadata: Dict[str, str] = field(factory=lambda: {})

    # index 1007?!: unknown bool

    def parse_extensible(self) -> ExtensibleAttachment:
        if not self.extensible_media:
            raise ValueError(
                "This attachment does not contain an extensible attachment")
        data = json.loads(self.extensible_media)
        raw_media_key = f"extensible_message_attachment:{self.media_id_str}"
        expected_key = base64.b64encode(
            raw_media_key.encode("utf-8")).decode("utf-8").rstrip("=")
        try:
            media_data = data[expected_key]
        except KeyError:
            media_data = list(data.values())[0]
        return ExtensibleAttachment.deserialize(media_data)
Example #7
0
class OpenedThreadRequest(ThriftObject):
    unknown_i64: int = field(TType.I64, default=0)
    _chat_id: bytes = field(default=None)

    @property
    def chat_id(self) -> int:
        return int(ChatIDWrapper.from_thrift(self._chat_id).chat_id)

    @chat_id.setter
    def chat_id(self, value: int) -> None:
        self._chat_id = ChatIDWrapper(str(value)).to_thrift()
Example #8
0
class ThreadKey(ThriftObject):
    other_user_id: int = field(TType.I64, default=None)
    thread_fbid: int = field(TType.I64, default=None)

    @property
    def id(self) -> Optional[int]:
        if self.other_user_id:
            return self.other_user_id
        elif self.thread_fbid:
            return self.thread_fbid
        else:
            return None
Example #9
0
class RegionHintPayload(ThriftObject):
    unknown_int64: int = field(TType.I64)
    region_hint_data: bytes

    @property
    def region_hint(self) -> RegionHint:
        return RegionHint.from_thrift(self.region_hint_data)
Example #10
0
class RealtimeConfig(ThriftObject):
    client_identifier: str
    will_topic: str = None
    will_message: str = None
    client_info: RealtimeClientInfo
    password: str
    get_diffs_request: List[str] = None
    zero_rating_token_hash: str = None
    # mysterious_struct_list: List[Any] = field(TType.LIST, TType.STRUCT, factory=lambda: [])
    app_specific_info: Dict[str, str] = field(index=9)
Example #11
0
class MessageSyncPayload(ThriftObject):
    items: List[MessageSyncEvent] = field(factory=lambda: [])
    first_seq_id: int = field(TType.I64, default=None)
    last_seq_id: int = field(TType.I64, default=None)
    viewer: int = field(TType.I64, default=None)
    # indices 5-10: ???
    subscribe_ok: str = field(index=11, default=None)
    error: MessageSyncError = field(TType.BINARY, default=None)
Example #12
0
class Message(ThriftObject):
    metadata: MessageMetadata
    text: str = field(default=None)
    # index 3: ???
    sticker: int = field(TType.I64, index=4, default=None)
    attachments: List[Attachment] = field(factory=lambda: [])
    # index 6: some sort of struct:
    #    1: List[BinaryThreadKey]?
    #    2: ???
    #    3: timestamp?
    #    4: timestamp?
    extra_metadata: Dict[str, bytes] = field(index=7, factory=lambda: {})

    # index 1000?!: int64 (ex: 81)
    # index 1017: int64 (ex: 924)
    # index 1003: struct
    #   index 1: struct
    #     index 1: binary, replying to message id
    # index 1012: map<binary, binary>
    #   key apiArgs: binary containing thrift
    #     index 2: binary url, https://www.facebook.com/intern/agent/realtime_delivery/
    #     index 4: int64 (ex: 0)
    #     index 7: binary, empty?
    #     index 5: binary, some sort of uuid
    #     index 8: list<map>
    #       item 1: map<binary, binary>
    #         {"layer": "www", "push_phase": "C3", "www_rev": "1003179603",
    #          "buenopath": "XRealtimeDeliveryThriftServerController:sendRealtimeDeliveryRequest:/ls_req:TASK_LABEL=SEND_MESSAGE_V{N}"}
    #     index 9: binary (ex: www)
    #     index 10: boolean (ex: false)
    # index 1015: list<binary>, some sort of tags

    @property
    def mentions(self) -> List[Mention]:
        return [
            Mention.deserialize(item)
            for item in json.loads(self.extra_metadata.get("prng", "[]"))
        ]
Example #13
0
class Attachment(ThriftObject):
    media_id_str: str
    mime_type: str = field(default=None)
    file_name: str = field(default=None)
    media_id: int = field(TType.I64, default=None)
    file_size: int = field(TType.I64, default=None)
    # index 6: ???
    extensible_media: str = field(default=None, index=7)
    # indices 8 and 9: ???
    image_info: ImageInfo = field(default=None, index=10)
    video_info: VideoInfo = field(default=None)
    audio_info: AudioInfo = field(default=None)
    # can contain a dash_manifest key with some XML as the value
    # or fbtype key with a number as value
    extra_metadata: Dict[str, str] = field(factory=lambda: {})

    # index 1007?!: unknown bool

    def parse_extensible(self) -> ExtensibleAttachment:
        if not self.extensible_media:
            raise ValueError("This attachment does not contain an extensible attachment")
        return ExtensibleAttachment.parse_json(self.extensible_media)
Example #14
0
class ImageInfo(ThriftObject):
    original_width: int = field(TType.I32)
    original_height: int = field(TType.I32)
    previews: Dict[int, str] = field(TType.MAP, key_type=TType.I32, default=None,
                                     value_type=RecursiveType(TType.BINARY, python_type=str))
    # index 4: unknown int32
    # indices 5 and 6: ???
    alt_previews: Dict[int, str] = field(TType.MAP, key_type=TType.I32, default=None, index=7,
                                         value_type=RecursiveType(TType.BINARY, python_type=str))
    image_type: str = field(default=None)
    alt_preview_type: str = field(default=None)
Example #15
0
class MessageMetadata(ThriftObject):
    thread: ThreadKey
    id: str
    offline_threading_id: int = field(TType.I64, default=None)
    sender: int = field(TType.I64)
    timestamp: int = field(TType.I64)
    # index 6: unknown bool (ex: true)
    action_summary: str = field(index=7, default=None)
    tags: List[str] = field(factory=lambda: [])
    # index 9: unknown int32 (ex: 3)
    # index 10: unknown bool (ex: false)
    # index 11: ???
    message_unsendability: Unsendability = field(
        TType.BINARY, index=12, default=Unsendability.DENY_FOR_NON_SENDER)
Example #16
0
class UnknownReceipt1(ThriftObject):
    thread: ThreadKey
    user_id: int = field(TType.I64)
    # indices 3-5: ???
    message_id_list: List[str] = field(index=6)
    timestamp: int = field(TType.I64)
Example #17
0
class RealtimeClientInfo(ThriftObject):
    user_id: int = field(TType.I64)
    user_agent: str
    client_capabilities: int = field(TType.I64)
    endpoint_capabilities: int = field(TType.I64)
    # 0 = no zlib?, 1 = always zlib, 2 = optional zlib
    publish_format: int = field(TType.I32)
    no_automatic_foreground: bool
    make_user_available_in_foreground: bool
    device_id: str
    is_initially_foreground: bool
    network_type: int = field(TType.I32)
    network_subtype: int = field(TType.I32)
    client_mqtt_session_id: int = field(TType.I64)
    client_ip_address: str = None
    subscribe_topics: List[int] = field(TType.LIST, item_type=TType.I32)
    client_type: str
    app_id: int = field(TType.I64)
    override_nectar_logging: bool = None
    connect_token_hash: str = None
    region_preference: str
    device_secret: str
    client_stack: int = field(TType.BYTE)
    fbns_connection_key: int = field(TType.I64, default=None)
    fbns_connection_secret: str = None
    fbns_device_id: str = None
    fbns_device_secret: str = None
    another_unknown: int = field(TType.I64, default=None)
    yet_another_unknown: int = field(TType.I32, default=None)
Example #18
0
class SendMessageRequest(ThriftObject):
    # tfbid_<groupid> for groups, plain user id for users
    chat_id: str
    message: str
    offline_threading_id: int = field(TType.I64)
    # index 4: ???
    # Example values:
    #   'is_in_chatheads': 'false'
    #   'ld': '{"u":1674434.........}'
    #   'entrypoint': 'messenger_inbox:in_thread'
    #   'trigger': '2:thread_list:thread' or 'thread_view_messages_fragment_unknown'
    #   'active_now': '{"is_online":"false","last_active_seconds":"1431"}'
    #
    #   'media_camera_mode': 'VIDEO'
    #   'trigger': 'thread_view_messages_fragment_unknown'
    #   'entry_point': 'THREAD_CAMERA_COMPOSER_BUTTON'
    flags: Dict[str, str] = field(index=5, factory=lambda: {})
    # 369239263222822 = "like"
    sticker: str = field(default=None)
    # indices 7 and 8: ???
    media_ids: List[str] = field(default=None)
    # indices 10 and 11: ???
    sender_id: int = field(TType.I64, index=12)
    # indices 13-17: ???
    unknown_int32: int = field(TType.I32, index=18, default=0)
    # index 19: ???
    extra_metadata: Dict[str, str] = field(index=20, default=None)
    unknown_int64: int = field(TType.I64, index=21, default=0)
    # index 22: ???
    unknown_bool: bool = field(TType.BOOL, index=23, default=False)
    # this is weird int64 that looks like offline_threading_id, but isn't quite the same
    tid2: int = field(TType.I64, index=24)
    # indices 25-27: ???
    reply_to: str = field(index=28)
Example #19
0
class VideoInfo(ThriftObject):
    original_width: int = field(TType.I32)
    original_height: int = field(TType.I32)
    duration_ms: int = field(TType.I32)
    thumbnail_url: str
    download_url: str
Example #20
0
class ExtendedAddMemberParticipant(ThriftObject):
    addee_user_id: int = field(TType.I64)
    adder_user_id: int = field(TType.I64)
    # index 3: unknown int32 (ex: 0)
    timestamp: int = field(TType.I64, index=4)
Example #21
0
class SendMessageResponse(ThriftObject):
    offline_threading_id: int = field(TType.I64)
    success: bool
    # index 3: unknown i32 present for errors
    error_message: str = field(default=None, index=4)
Example #22
0
class MessageSyncInnerEvent(ThriftObject):
    reaction: Reaction = field(index=10, default=None)
    extended_add_member: ExtendedAddMember = field(index=42, default=None)
    extended_message: ExtendedMessage = field(index=55, default=None)
    unsend_message: UnsendMessage = field(index=67, default=None)
Example #23
0
class ReadReceipt(ThriftObject):
    thread: ThreadKey
    user_id: int = field(TType.I64)
    read_at: int = field(TType.I64)
    read_to: int = field(TType.I64)
Example #24
0
class UnsendMessage(ThriftObject):
    thread: ThreadKey
    message_id: str
    timestamp: int = field(TType.I64)
    user_id: int = field(TType.I64)
Example #25
0
class RemoveMember(ThriftObject):
    metadata: MessageMetadata
    user_id: int = field(TType.I64)
Example #26
0
class AddMemberParticipant(ThriftObject):
    id: int = field(TType.I64)
    first_name: str
    name: str
Example #27
0
class AudioInfo(ThriftObject):
    # index 1: mysterious boolean (true)
    # index 2: mysterious binary (empty)
    url: str = field(index=3)
    duration_ms: int = field(TType.I32)
Example #28
0
class OwnReadReceipt(ThriftObject):
    threads: List[ThreadKey]
    # index 2: ???
    read_to: int = field(TType.I64, index=3)
    read_at: int = field(TType.I64)