Beispiel #1
0
    def encode(self, *, major: int = None, minor: int = None):
        major = major if major is not None else self.MAJOR
        minor = minor if minor is not None else self.MINOR

        buffer = BytesIO()

        file_type = self.file_type

        if self.url:
            file_type |= WEB_LOCATION_FLAG

        if self.file_reference:
            file_type |= FILE_REFERENCE_FLAG

        buffer.write(struct.pack("<ii", file_type, self.dc_id))

        if self.url:
            buffer.write(String(self.url))

        if self.file_reference:
            buffer.write(Bytes(self.file_reference))

        buffer.write(struct.pack("<qq", self.media_id, self.access_hash))

        if self.file_type in PHOTO_TYPES:
            buffer.write(struct.pack("<q", self.volume_id))

            if major >= 4:
                buffer.write(struct.pack("<i", self.thumbnail_source))

            if self.thumbnail_source == ThumbnailSource.LEGACY:
                buffer.write(struct.pack("<qi", self.secret, self.local_id))
            elif self.thumbnail_source == ThumbnailSource.THUMBNAIL:
                buffer.write(struct.pack(
                    "<iii",
                    self.thumbnail_file_type,
                    ord(self.thumbnail_size),
                    self.local_id
                ))
            elif self.thumbnail_source in (ThumbnailSource.CHAT_PHOTO_SMALL, ThumbnailSource.CHAT_PHOTO_BIG):
                buffer.write(struct.pack(
                    "<qqi",
                    self.chat_id,
                    self.chat_access_hash,
                    self.local_id
                ))
            elif self.thumbnail_source == ThumbnailSource.STICKER_SET_THUMBNAIL:
                buffer.write(struct.pack(
                    "<qqi",
                    self.sticker_set_id,
                    self.sticker_set_access_hash,
                    self.local_id
                ))
        elif file_type in DOCUMENT_TYPES:
            buffer.write(struct.pack("<ii", minor, major))

        buffer.write(struct.pack("<bb", minor, major))

        return b64_encode(rle_encode(buffer.getvalue()))
Beispiel #2
0
    def decode(file_id: str):
        decoded = rle_decode(b64_decode(file_id))

        # region read version
        # File id versioning. Major versions lower than 4 don't have a minor version
        major = decoded[-1]

        if major < 4:
            minor = 0
            buffer = BytesIO(decoded[:-1])
        else:
            minor = decoded[-2]
            buffer = BytesIO(decoded[:-2])
        # endregion

        file_type, dc_id = struct.unpack("<ii", buffer.read(8))

        # region media type flags
        # Check for flags existence
        has_web_location = bool(file_type & WEB_LOCATION_FLAG)
        has_file_reference = bool(file_type & FILE_REFERENCE_FLAG)

        # Remove flags to restore the actual type id value
        file_type &= ~WEB_LOCATION_FLAG
        file_type &= ~FILE_REFERENCE_FLAG
        # endregion

        try:
            file_type = FileType(file_type)
        except ValueError:
            raise ValueError(
                f"Unknown file_type {file_type} of file_id {file_id}")

        if has_web_location:
            url = String.read(buffer)
            access_hash, = struct.unpack("<q", buffer.read(8))

            return FileId(major=major,
                          minor=minor,
                          file_type=file_type,
                          dc_id=dc_id,
                          url=url,
                          access_hash=access_hash)

        file_reference = Bytes.read(buffer) if has_file_reference else b""
        media_id, access_hash = struct.unpack("<qq", buffer.read(16))

        if file_type in PHOTO_TYPES:
            volume_id, = struct.unpack("<q", buffer.read(8))
            thumbnail_source, = (0, ) if major < 4 else struct.unpack(
                "<i", buffer.read(4))

            try:
                thumbnail_source = ThumbnailSource(thumbnail_source)
            except ValueError:
                raise ValueError(
                    f"Unknown thumbnail_source {thumbnail_source} of file_id {file_id}"
                )

            if thumbnail_source == ThumbnailSource.LEGACY:
                secret, local_id = struct.unpack("<qi", buffer.read(12))

                return FileId(major=major,
                              minor=minor,
                              file_type=file_type,
                              dc_id=dc_id,
                              file_reference=file_reference,
                              media_id=media_id,
                              access_hash=access_hash,
                              volume_id=volume_id,
                              thumbnail_source=thumbnail_source,
                              secret=secret,
                              local_id=local_id)

            if thumbnail_source == ThumbnailSource.THUMBNAIL:
                thumbnail_file_type, thumbnail_size, local_id = struct.unpack(
                    "<iii", buffer.read(12))
                thumbnail_size = chr(thumbnail_size)

                return FileId(major=major,
                              minor=minor,
                              file_type=file_type,
                              dc_id=dc_id,
                              file_reference=file_reference,
                              media_id=media_id,
                              access_hash=access_hash,
                              volume_id=volume_id,
                              thumbnail_source=thumbnail_source,
                              thumbnail_file_type=thumbnail_file_type,
                              thumbnail_size=thumbnail_size,
                              local_id=local_id)

            if thumbnail_source in (ThumbnailSource.CHAT_PHOTO_SMALL,
                                    ThumbnailSource.CHAT_PHOTO_BIG):
                chat_id, chat_access_hash, local_id = struct.unpack(
                    "<qqi", buffer.read(20))

                return FileId(major=major,
                              minor=minor,
                              file_type=file_type,
                              dc_id=dc_id,
                              file_reference=file_reference,
                              media_id=media_id,
                              access_hash=access_hash,
                              volume_id=volume_id,
                              thumbnail_source=thumbnail_source,
                              chat_id=chat_id,
                              chat_access_hash=chat_access_hash,
                              local_id=local_id)

            if thumbnail_source == ThumbnailSource.STICKER_SET_THUMBNAIL:
                sticker_set_id, sticker_set_access_hash, local_id = struct.unpack(
                    "<qqi", buffer.read(20))

                return FileId(major=major,
                              minor=minor,
                              file_type=file_type,
                              dc_id=dc_id,
                              file_reference=file_reference,
                              media_id=media_id,
                              access_hash=access_hash,
                              volume_id=volume_id,
                              thumbnail_source=thumbnail_source,
                              sticker_set_id=sticker_set_id,
                              sticker_set_access_hash=sticker_set_access_hash,
                              local_id=local_id)

        if file_type in DOCUMENT_TYPES:
            return FileId(major=major,
                          minor=minor,
                          file_type=file_type,
                          dc_id=dc_id,
                          file_reference=file_reference,
                          media_id=media_id,
                          access_hash=access_hash)