Migrate resolve_bot_file_id to using tg_file_id as dependency.

This commit is contained in:
luckydonald 2020-11-07 22:03:54 +01:00
parent bd49e2cee5
commit 78a9b7f4d5

View File

@ -15,8 +15,10 @@ import os
import pathlib import pathlib
import re import re
import struct import struct
from tg_file_id.file_id import FileId, DocumentFileId, PhotoFileId
from collections import namedtuple from collections import namedtuple
from mimetypes import guess_extension from mimetypes import guess_extension
from typing import Union
from types import GeneratorType from types import GeneratorType
from .extensions import markdown, html from .extensions import markdown, html
@ -1101,104 +1103,85 @@ def resolve_bot_file_id(file_id):
For thumbnails, the photo ID and hash will always be zero. For thumbnails, the photo ID and hash will always be zero.
""" """
data = _rle_decode(_decode_telegram_base64(file_id)) if not file_id:
if not data:
return None return None
# end if
# This isn't officially documented anywhere, but if isinstance(file_id, str):
# we assume the last byte is some kind of "version". file = FileId.from_file_id(file_id)
data, version = data[:-1], data[-1] elif not isinstance(file_id, FileId):
if version not in (2, 4):
return None return None
# end if
if (version == 2 and len(data) == 24) or (version == 4 and len(data) == 25): if isinstance(file, DocumentFileId):
if version == 2:
file_type, dc_id, media_id, access_hash = struct.unpack('<iiqq', data)
# elif version == 4:
else:
# TODO Figure out what the extra byte means
file_type, dc_id, media_id, access_hash, _ = struct.unpack('<iiqqb', data)
if not (1 <= dc_id <= 5):
# Valid `file_id`'s must have valid DC IDs. Since this method is
# called when sending a file and the user may have entered a path
# they believe is correct but the file doesn't exist, this method
# may detect a path as "valid" bot `file_id` even when it's not.
# By checking the `dc_id`, we greatly reduce the chances of this
# happening.
return None
attributes = [] attributes = []
if file_type == 3 or file_type == 9: if file.type_id in (FileId.TYPE_VOICE, FileId.TYPE_AUDIO):
attributes.append(types.DocumentAttributeAudio( attributes.append(types.DocumentAttributeAudio(
duration=0, duration=0,
voice=file_type == 3 voice=file.type_id == FileId.TYPE_VOICE
)) ))
elif file_type == 4 or file_type == 13: elif file.type_id == FileId.TYPE_VIDEO or file.type_id == FileId.TYPE_VIDEO_NOTE:
attributes.append(types.DocumentAttributeVideo( attributes.append(types.DocumentAttributeVideo(
duration=0, duration=0,
w=0, w=0,
h=0, h=0,
round_message=file_type == 13 round_message=file.type_id == FileId.TYPE_VIDEO_NOTE
)) ))
# elif file_type == 5: # other, cannot know which # elif file.type_id == FieldId.TYPE_DOCUMENT: # other, cannot know which --> no attribute
elif file_type == 8: elif file.type_id == FileId.TYPE_STICKER:
attributes.append(types.DocumentAttributeSticker( attributes.append(types.DocumentAttributeSticker(
alt='', alt='',
stickerset=types.InputStickerSetEmpty() stickerset=types.InputStickerSetEmpty()
)) ))
elif file_type == 10: elif file.type_id == FileId.TYPE_ANIMATION:
attributes.append(types.DocumentAttributeAnimated()) attributes.append(types.DocumentAttributeAnimated())
# end if
return types.Document( return types.Document(
id=media_id, id=file.id,
access_hash=access_hash, access_hash=file.access_hash,
date=None, date=None,
mime_type='', mime_type='',
size=0, size=0,
thumbs=None, thumbs=None,
dc_id=dc_id, dc_id=file.dc_id,
attributes=attributes, attributes=attributes,
file_reference=b'' file_reference=file.file_reference if file.has_reference else b''
) )
elif (version == 2 and len(data) == 44) or (version == 4 and len(data) in (49, 77)): elif not isinstance(file, PhotoFileId): # e.g. WebLocationFileId
if version == 2: return None
(file_type, dc_id, media_id, access_hash, # end if
volume_id, secret, local_id) = struct.unpack('<iiqqqqi', data)
# else version == 4:
elif len(data) == 49:
# TODO Figure out what the extra five bytes mean
(file_type, dc_id, media_id, access_hash,
volume_id, secret, local_id, _) = struct.unpack('<iiqqqqi5s', data)
elif len(data) == 77:
# See #1613.
(file_type, dc_id, _, media_id, access_hash, volume_id, _, local_id, _) = struct.unpack('<ii28sqqq12sib', data)
else:
return None
if not (1 <= dc_id <= 5): # okey, so we're dealing with a photo.
return None assert isinstance(file, PhotoFileId)
photo_size = 's' if file.id or file.access_hash else 'x'
# Thumbnails (small) always have ID 0; otherwise size 'x' foto_size = file.photosize
photo_size = 's' if media_id or access_hash else 'x' if isinstance(foto_size, (PhotoFileId.PhotosizeSourceLegacy, PhotoFileId.PhotosizeSourceThumbnail, PhotoFileId.PhotosizeSourceDialogPhotoSmall, PhotoFileId.PhotosizeSourceDialogPhotoBig, PhotoFileId.PhotosizeSourceStickersetThumbnail)):
return types.Photo( sizes = [
id=media_id, types.PhotoSize(
access_hash=access_hash,
file_reference=b'',
date=None,
sizes=[types.PhotoSize(
type=photo_size, type=photo_size,
location=types.FileLocationToBeDeprecated( location=types.FileLocationToBeDeprecated(
volume_id=volume_id, volume_id=foto_size.volume_id,
local_id=local_id local_id=foto_size.location_local_id,
), ),
w=0, w=0,
h=0, h=0,
size=0 size=0
)], )
dc_id=dc_id, ]
has_stickers=None else:
) sizes = []
# end if
return types.Photo(
id=file.id,
access_hash=file.access_hash,
file_reference=file.file_reference,
date=None,
sizes=sizes,
dc_id=file.dc_id,
has_stickers=None
)
def pack_bot_file_id(file): def pack_bot_file_id(file):