mirror of
https://github.com/LonamiWebs/Telethon.git
synced 2024-11-10 19:46:36 +03:00
Added ability to download media
Now you can also download any message media, exactly the same way you can upload any media
This commit is contained in:
parent
7e78b1b6dc
commit
1293d3be1c
3
main.py
3
main.py
|
@ -78,8 +78,7 @@ if __name__ == '__main__':
|
||||||
# and print them in "[hh:mm] Sender: Message" text format
|
# and print them in "[hh:mm] Sender: Message" text format
|
||||||
for msg, sender in zip(reversed(messages), reversed(senders)):
|
for msg, sender in zip(reversed(messages), reversed(senders)):
|
||||||
name = sender.first_name if sender else '???'
|
name = sender.first_name if sender else '???'
|
||||||
date = datetime.fromtimestamp(msg.date)
|
print('[{}:{}] {}: {}'.format(msg.date.hour, msg.date.minute, name, msg.message))
|
||||||
print('[{}:{}] {}: {}'.format(date.hour, date.minute, name, msg.message))
|
|
||||||
|
|
||||||
# Send photo
|
# Send photo
|
||||||
elif msg.startswith('!p '):
|
elif msg.startswith('!p '):
|
||||||
|
|
|
@ -20,12 +20,12 @@ from tl import Session
|
||||||
from tl.types import \
|
from tl.types import \
|
||||||
PeerUser, PeerChat, PeerChannel, \
|
PeerUser, PeerChat, PeerChannel, \
|
||||||
InputPeerUser, InputPeerChat, InputPeerChannel, InputPeerEmpty, \
|
InputPeerUser, InputPeerChat, InputPeerChannel, InputPeerEmpty, \
|
||||||
InputFile, InputMediaUploadedPhoto
|
InputFile, InputFileLocation, InputMediaUploadedPhoto
|
||||||
|
|
||||||
from tl.functions import InvokeWithLayerRequest, InitConnectionRequest
|
from tl.functions import InvokeWithLayerRequest, InitConnectionRequest
|
||||||
from tl.functions.help import GetConfigRequest
|
from tl.functions.help import GetConfigRequest
|
||||||
from tl.functions.auth import SendCodeRequest, SignInRequest
|
from tl.functions.auth import SendCodeRequest, SignInRequest
|
||||||
from tl.functions.upload import SaveFilePartRequest
|
from tl.functions.upload import SaveFilePartRequest, GetFileRequest
|
||||||
from tl.functions.messages import GetDialogsRequest, GetHistoryRequest, SendMessageRequest, SendMediaRequest
|
from tl.functions.messages import GetDialogsRequest, GetHistoryRequest, SendMessageRequest, SendMediaRequest
|
||||||
|
|
||||||
|
|
||||||
|
@ -110,6 +110,18 @@ class TelegramClient:
|
||||||
|
|
||||||
# region Telegram requests functions
|
# region Telegram requests functions
|
||||||
|
|
||||||
|
def invoke(self, request):
|
||||||
|
"""Invokes a MTProtoRequest (sends and receives it) and returns its result"""
|
||||||
|
if not issubclass(type(request), MTProtoRequest):
|
||||||
|
raise ValueError('You can only invoke MtProtoRequests')
|
||||||
|
|
||||||
|
self.sender.send(request)
|
||||||
|
self.sender.receive(request)
|
||||||
|
|
||||||
|
return request.result
|
||||||
|
|
||||||
|
# region Authorization requests
|
||||||
|
|
||||||
def is_user_authorized(self):
|
def is_user_authorized(self):
|
||||||
"""Has the user been authorized yet (code request sent and confirmed)?
|
"""Has the user been authorized yet (code request sent and confirmed)?
|
||||||
Note that this will NOT yield the correct result if the session was revoked by another client!"""
|
Note that this will NOT yield the correct result if the session was revoked by another client!"""
|
||||||
|
@ -147,6 +159,10 @@ class TelegramClient:
|
||||||
|
|
||||||
return self.session.user
|
return self.session.user
|
||||||
|
|
||||||
|
# endregion
|
||||||
|
|
||||||
|
# region Dialogs ("chats") requests
|
||||||
|
|
||||||
def get_dialogs(self, count=10, offset_date=None, offset_id=0, offset_peer=InputPeerEmpty()):
|
def get_dialogs(self, count=10, offset_date=None, offset_id=0, offset_peer=InputPeerEmpty()):
|
||||||
"""Returns a tuple of lists ([dialogs], [displays], [input_peers]) with 'count' items each"""
|
"""Returns a tuple of lists ([dialogs], [displays], [input_peers]) with 'count' items each"""
|
||||||
|
|
||||||
|
@ -159,6 +175,10 @@ class TelegramClient:
|
||||||
[self.find_display_name(d.peer, r.users, r.chats) for d in r.dialogs],
|
[self.find_display_name(d.peer, r.users, r.chats) for d in r.dialogs],
|
||||||
[self.find_input_peer(d.peer, r.users, r.chats) for d in r.dialogs])
|
[self.find_input_peer(d.peer, r.users, r.chats) for d in r.dialogs])
|
||||||
|
|
||||||
|
# endregion
|
||||||
|
|
||||||
|
# region Message requests
|
||||||
|
|
||||||
def send_message(self, input_peer, message, markdown=False, no_web_page=False):
|
def send_message(self, input_peer, message, markdown=False, no_web_page=False):
|
||||||
"""Sends a message to the given input peer"""
|
"""Sends a message to the given input peer"""
|
||||||
if markdown:
|
if markdown:
|
||||||
|
@ -208,7 +228,11 @@ class TelegramClient:
|
||||||
for msg in result.messages # ...from all the messages...
|
for msg in result.messages # ...from all the messages...
|
||||||
for usr in result.users]) # ...from all of the available users
|
for usr in result.users]) # ...from all of the available users
|
||||||
|
|
||||||
# TODO Handle media downloading/uploading in a different session:
|
# endregion
|
||||||
|
|
||||||
|
# region Uploading/downloading media requests
|
||||||
|
|
||||||
|
# TODO Handle media downloading/uploading in a different session?
|
||||||
# "It is recommended that large queries (upload.getFile, upload.saveFilePart)
|
# "It is recommended that large queries (upload.getFile, upload.saveFilePart)
|
||||||
# be handled through a separate session and a separate connection"
|
# be handled through a separate session and a separate connection"
|
||||||
def upload_file(self, file_path, part_size_kb=64, file_name=None):
|
def upload_file(self, file_path, part_size_kb=64, file_name=None):
|
||||||
|
@ -231,8 +255,6 @@ class TelegramClient:
|
||||||
# Read the file by in chunks of size part_size
|
# Read the file by in chunks of size part_size
|
||||||
part = file.read(part_size)
|
part = file.read(part_size)
|
||||||
|
|
||||||
print('Sending {}'.format(len(part)))
|
|
||||||
|
|
||||||
# If we have read no data (0 bytes), the file is over
|
# If we have read no data (0 bytes), the file is over
|
||||||
# So there is nothing left to upload
|
# So there is nothing left to upload
|
||||||
if not part:
|
if not part:
|
||||||
|
@ -252,7 +274,7 @@ class TelegramClient:
|
||||||
|
|
||||||
# After the file has been uploaded, we can return a handle pointing to it
|
# After the file has been uploaded, we can return a handle pointing to it
|
||||||
return InputFile(id=file_id,
|
return InputFile(id=file_id,
|
||||||
parts = part_index,
|
parts=part_index,
|
||||||
name=file_name,
|
name=file_name,
|
||||||
md5_checksum=hash_md5.hexdigest())
|
md5_checksum=hash_md5.hexdigest())
|
||||||
|
|
||||||
|
@ -268,15 +290,41 @@ class TelegramClient:
|
||||||
media=input_media,
|
media=input_media,
|
||||||
random_id=utils.generate_random_long()))
|
random_id=utils.generate_random_long()))
|
||||||
|
|
||||||
def invoke(self, request):
|
def download_photo(self, message_media_photo, file_path):
|
||||||
"""Invokes an MTProtoRequest and returns its results"""
|
"""Downloads a message_media_photo largest size into the desired file_path"""
|
||||||
if not issubclass(type(request), MTProtoRequest):
|
# Determine the photo and its largest size
|
||||||
raise ValueError('You can only invoke MtProtoRequests')
|
photo = message_media_photo.photo
|
||||||
|
largest_size = photo.sizes[-1].location
|
||||||
|
|
||||||
self.sender.send(request)
|
# Download the media with the largest size input file location
|
||||||
self.sender.receive(request)
|
self.download_media(InputFileLocation(volume_id=largest_size.volume_id,
|
||||||
|
local_id=largest_size.local_id,
|
||||||
|
secret=largest_size.secret), file_path)
|
||||||
|
|
||||||
return request.result
|
def download_media(self, input_file_location, file_path, part_size_kb=64):
|
||||||
|
"""Downloads media from the given input_file_location to the specified file_path"""
|
||||||
|
|
||||||
|
part_size = int(part_size_kb * 1024)
|
||||||
|
if part_size % 1024 != 0:
|
||||||
|
raise ValueError('The part size must be evenly divisible by 1024')
|
||||||
|
|
||||||
|
# Start with an offset index of 0
|
||||||
|
offset_index = 0
|
||||||
|
with open(file_path, 'wb') as file:
|
||||||
|
while True:
|
||||||
|
# The current offset equals the offset_index multiplied by the part size
|
||||||
|
offset = offset_index * part_size
|
||||||
|
result = self.invoke(GetFileRequest(input_file_location, offset, part_size))
|
||||||
|
offset_index += 1
|
||||||
|
|
||||||
|
# If we have received no data (0 bytes), the file is over
|
||||||
|
# So there is nothing left to download and write
|
||||||
|
if not result.bytes:
|
||||||
|
return result.type # Return some extra information
|
||||||
|
|
||||||
|
file.write(result.bytes)
|
||||||
|
|
||||||
|
# endregion
|
||||||
|
|
||||||
# endregion
|
# endregion
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user