mirror of
https://github.com/LonamiWebs/Telethon.git
synced 2024-11-25 10:53:44 +03:00
Added ability to download profile photos, changes to get_dialogs()
The `get_dialogs()` method now returns dialogs and "entities", which can be an User, a Chat or even a Channel. In order to use them you may want to make use of .get_input_peer() and .get_display_name() methods
This commit is contained in:
parent
7399bfacd1
commit
2a666f7ee0
|
@ -58,7 +58,10 @@ class InteractiveTelegramClient(TelegramClient):
|
|||
while True:
|
||||
# Retrieve the top dialogs
|
||||
dialog_count = 10
|
||||
dialogs, displays, inputs = self.get_dialogs(dialog_count)
|
||||
|
||||
# Entities represent the user, chat or channel
|
||||
# corresponding to the dialog on the same index
|
||||
dialogs, entities = self.get_dialogs(dialog_count)
|
||||
|
||||
i = None
|
||||
while i is None:
|
||||
|
@ -66,9 +69,9 @@ class InteractiveTelegramClient(TelegramClient):
|
|||
print_title('Dialogs window')
|
||||
|
||||
# Display them so the user can choose
|
||||
for i, display in enumerate(displays):
|
||||
for i, entity in enumerate(entities):
|
||||
i += 1 # 1-based index for normies
|
||||
print('{}. {}'.format(i, display))
|
||||
print('{}. {}'.format(i, self.get_display_name(entity)))
|
||||
|
||||
# Let the user decide who they want to talk to
|
||||
print()
|
||||
|
@ -92,19 +95,20 @@ class InteractiveTelegramClient(TelegramClient):
|
|||
except ValueError:
|
||||
pass
|
||||
|
||||
# Retrieve the selected user
|
||||
display = displays[i]
|
||||
input_peer = inputs[i]
|
||||
# Retrieve the selected user (or chat, or channel)
|
||||
entity = entities[i]
|
||||
input_peer = self.get_input_peer(entity)
|
||||
|
||||
# Show some information
|
||||
print_title('Chat with "{}"'.format(display))
|
||||
print_title('Chat with "{}"'.format(self.get_display_name(entity)))
|
||||
print('Available commands:')
|
||||
print(' !q: Quits the current chat.')
|
||||
print(' !Q: Quits the current chat and exits.')
|
||||
print(' !h: prints the latest messages (message History) of the chat.')
|
||||
print(' !p <path>: sends a Photo located at the given path.')
|
||||
print(' !f <path>: sends a File document located at the given path.')
|
||||
print(' !d <msg-id>: Downloads the given message media (if any).')
|
||||
print(' !up <path>: Uploads and sends a Photo located at the given path.')
|
||||
print(' !uf <path>: Uploads and sends a File document located at the given path.')
|
||||
print(' !dm <msg-id>: Downloads the given message Media (if any).')
|
||||
print(' !dp: Downloads the current dialog Profile picture.')
|
||||
print()
|
||||
|
||||
# And start a while loop to chat
|
||||
|
@ -139,20 +143,31 @@ class InteractiveTelegramClient(TelegramClient):
|
|||
msg.date.hour, msg.date.minute, msg.id, name, content))
|
||||
|
||||
# Send photo
|
||||
elif msg.startswith('!p '):
|
||||
elif msg.startswith('!up '):
|
||||
# Slice the message to get the path
|
||||
self.send_photo(path=msg[len('!p '):], peer=input_peer)
|
||||
|
||||
# Send file (document)
|
||||
elif msg.startswith('!f '):
|
||||
elif msg.startswith('!uf '):
|
||||
# Slice the message to get the path
|
||||
self.send_document(path=msg[len('!f '):], peer=input_peer)
|
||||
|
||||
# Download media
|
||||
elif msg.startswith('!d '):
|
||||
elif msg.startswith('!dm '):
|
||||
# Slice the message to get message ID
|
||||
self.download_media(msg[len('!d '):])
|
||||
|
||||
# Download profile photo
|
||||
elif msg == '!dp':
|
||||
output = str('usermedia/propic_{}'.format(entity.id))
|
||||
print('Downloading profile picture...')
|
||||
success = self.download_profile_photo(entity.photo, output)
|
||||
if success:
|
||||
print('Profile picture downloaded to {}'.format(output))
|
||||
else:
|
||||
print('"{}" does not seem to have a profile picture.'
|
||||
.format(self.get_display_name(entity)))
|
||||
|
||||
# Send chat message (if any)
|
||||
elif msg:
|
||||
self.send_message(input_peer, msg, markdown=True, no_web_page=True)
|
||||
|
|
|
@ -11,8 +11,10 @@ from telethon.tl import Session
|
|||
# The Requests and types that we'll be using
|
||||
from telethon.tl.functions.upload import SaveBigFilePartRequest
|
||||
from telethon.tl.types import \
|
||||
User, Chat, Channel, \
|
||||
PeerUser, PeerChat, PeerChannel, \
|
||||
InputPeerUser, InputPeerChat, InputPeerChannel, InputPeerEmpty, \
|
||||
UserProfilePhotoEmpty, ChatPhotoEmpty, \
|
||||
InputFile, InputFileLocation, InputMediaUploadedPhoto, InputMediaUploadedDocument, \
|
||||
MessageMediaContact, MessageMediaDocument, MessageMediaPhoto, \
|
||||
DocumentAttributeAudio, DocumentAttributeFilename, InputDocumentFileLocation
|
||||
|
@ -217,33 +219,34 @@ class TelegramClient:
|
|||
# region Dialogs ("chats") requests
|
||||
|
||||
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], [entities]) with 'count' items each.
|
||||
The `entity` represents the user, chat or channel corresponding to that dialog"""
|
||||
|
||||
r = self.invoke(GetDialogsRequest(offset_date=offset_date,
|
||||
offset_id=offset_id,
|
||||
offset_peer=offset_peer,
|
||||
limit=count))
|
||||
|
||||
return (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_user_or_chat(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):
|
||||
"""Sends a message to the given input peer"""
|
||||
"""Sends a message to the given input peer and returns the sent message ID"""
|
||||
if markdown:
|
||||
msg, entities = parse_message_entities(message)
|
||||
else:
|
||||
msg, entities = message, []
|
||||
|
||||
msg_id = utils.generate_random_long()
|
||||
self.invoke(SendMessageRequest(peer=input_peer,
|
||||
message=msg,
|
||||
random_id=utils.generate_random_long(),
|
||||
random_id=msg_id,
|
||||
entities=entities,
|
||||
no_webpage=no_web_page))
|
||||
return msg_id
|
||||
|
||||
def get_message_history(self, input_peer, limit=20,
|
||||
offset_date=None, offset_id=0, max_id=0, min_id=0, add_offset=0):
|
||||
|
@ -409,6 +412,32 @@ class TelegramClient:
|
|||
|
||||
# region Downloading media requests
|
||||
|
||||
def download_profile_photo(self, profile_photo, file_path,
|
||||
add_extension=True, download_big=True):
|
||||
"""Downloads the profile photo for an user or a chat (including channels).
|
||||
Returns False if no photo was providen, or if it was Empty"""
|
||||
|
||||
if (not profile_photo or
|
||||
isinstance(profile_photo, UserProfilePhotoEmpty) or
|
||||
isinstance(profile_photo, ChatPhotoEmpty)):
|
||||
return False
|
||||
|
||||
# Photos are always compressed into a .jpg by Telegram
|
||||
if add_extension:
|
||||
file_path += '.jpg'
|
||||
|
||||
if download_big:
|
||||
photo_location = profile_photo.photo_big
|
||||
else:
|
||||
photo_location = profile_photo.photo_small
|
||||
|
||||
# Download the media with the largest size input file location
|
||||
self.download_file_loc(InputFileLocation(volume_id=photo_location.volume_id,
|
||||
local_id=photo_location.local_id,
|
||||
secret=photo_location.secret),
|
||||
file_path)
|
||||
return True
|
||||
|
||||
def download_msg_media(self, message_media, file_path, add_extension=True, progress_callback=None):
|
||||
"""Downloads the given MessageMedia (Photo, Document or Contact)
|
||||
into the desired file_path, optionally finding its extension automatically
|
||||
|
@ -556,43 +585,44 @@ class TelegramClient:
|
|||
# region Utilities
|
||||
|
||||
@staticmethod
|
||||
def find_display_name(peer, users, chats):
|
||||
"""Searches the display name for peer in both users and chats.
|
||||
def get_display_name(entity):
|
||||
"""Gets the input peer for the given "entity" (user, chat or channel)
|
||||
Returns None if it was not found"""
|
||||
try:
|
||||
if type(peer) is PeerUser:
|
||||
user = next(u for u in users if u.id == peer.user_id)
|
||||
if user.last_name is not None:
|
||||
return '{} {}'.format(user.first_name, user.last_name)
|
||||
return user.first_name
|
||||
if isinstance(entity, User):
|
||||
if entity.last_name is not None:
|
||||
return '{} {}'.format(entity.first_name, entity.last_name)
|
||||
return entity.first_name
|
||||
|
||||
elif type(peer) is PeerChat:
|
||||
return next(c for c in chats if c.id == peer.chat_id).title
|
||||
|
||||
elif type(peer) is PeerChannel:
|
||||
return next(c for c in chats if c.id == peer.channel_id).title
|
||||
|
||||
except StopIteration:
|
||||
pass
|
||||
|
||||
return None
|
||||
if isinstance(entity, Chat) or isinstance(entity, Channel):
|
||||
return entity.title
|
||||
|
||||
@staticmethod
|
||||
def find_input_peer(peer, users, chats):
|
||||
"""Searches the given peer in both users and chats and returns an InputPeer for it.
|
||||
def get_input_peer(entity):
|
||||
"""Gets the input peer for the given "entity" (user, chat or channel).
|
||||
Returns None if it was not found"""
|
||||
if isinstance(entity, User):
|
||||
return InputPeerUser(entity.id, entity.access_hash)
|
||||
if isinstance(entity, Chat):
|
||||
return InputPeerChat(entity.id)
|
||||
if isinstance(entity, Channel):
|
||||
return InputPeerChannel(entity.id, entity.access_hash)
|
||||
|
||||
@staticmethod
|
||||
def find_user_or_chat(peer, users, chats):
|
||||
"""Finds the corresponding user or chat given a peer.
|
||||
Returns None if it was not found"""
|
||||
try:
|
||||
if type(peer) is PeerUser:
|
||||
if isinstance(peer, PeerUser):
|
||||
user = next(u for u in users if u.id == peer.user_id)
|
||||
return InputPeerUser(user.id, user.access_hash)
|
||||
return user
|
||||
|
||||
elif type(peer) is PeerChat:
|
||||
elif isinstance(peer, PeerChat):
|
||||
chat = next(c for c in chats if c.id == peer.chat_id)
|
||||
return InputPeerChat(chat.id)
|
||||
return chat
|
||||
|
||||
elif type(peer) is PeerChannel:
|
||||
elif isinstance(peer, PeerChannel):
|
||||
channel = next(c for c in chats if c.id == peer.channel_id)
|
||||
return InputPeerChannel(channel.id, channel.access_hash)
|
||||
return channel
|
||||
|
||||
except StopIteration:
|
||||
return None
|
||||
|
|
Loading…
Reference in New Issue
Block a user