Add support to get all dialogs at once

This commit is contained in:
Lonami Exo 2017-10-01 10:50:37 +02:00
parent 06bb09b95c
commit 68e7d481f4
2 changed files with 62 additions and 23 deletions

View File

@ -41,6 +41,7 @@ from .tl.types import (
InputUserSelf, UserProfilePhoto, ChatPhoto, UpdateMessageID, InputUserSelf, UserProfilePhoto, ChatPhoto, UpdateMessageID,
UpdateNewMessage, UpdateShortSentMessage UpdateNewMessage, UpdateShortSentMessage
) )
from .tl.types.messages import DialogsSlice
from .utils import find_user_or_chat, get_extension from .utils import find_user_or_chat, get_extension
@ -224,22 +225,61 @@ class TelegramClient(TelegramBareClient):
offset_id=0, offset_id=0,
offset_peer=InputPeerEmpty()): offset_peer=InputPeerEmpty()):
"""Returns a tuple of lists ([dialogs], [entities]) """Returns a tuple of lists ([dialogs], [entities])
with at least 'limit' items each. with at least 'limit' items each unless all dialogs were consumed.
If `limit` is None, all dialogs will be retrieved (from the given
offset) will be retrieved.
If `limit` is 0, all dialogs will (should) retrieved.
The `entities` represent the user, chat or channel The `entities` represent the user, chat or channel
corresponding to that dialog. corresponding to that dialog. If it's an integer, not
all dialogs may be retrieved at once.
""" """
if limit is None:
limit = float('inf')
r = self( dialogs = {} # Use Dialog.top_message as identifier to avoid dupes
GetDialogsRequest( messages = {} # Used later for sorting TODO also return these?
entities = {}
while len(dialogs) < limit:
r = self(GetDialogsRequest(
offset_date=offset_date, offset_date=offset_date,
offset_id=offset_id, offset_id=offset_id,
offset_peer=offset_peer, offset_peer=offset_peer,
limit=limit)) limit=0 # limit 0 often means "as much as possible"
))
if not r.dialogs:
break
for d in r.dialogs:
dialogs[d.top_message] = d
for m in r.messages:
messages[m.id] = m
# We assume users can't have the same ID as a chat
for u in r.users:
entities[u.id] = u
for c in r.chats:
entities[c.id] = c
if isinstance(r, DialogsSlice):
# Don't enter next iteration if we already got all
break
offset_date = r.messages[-1].date
offset_peer = find_user_or_chat(r.dialogs[-1].peer, entities,
entities)
offset_id = r.messages[-1].id & 4294967296 # Telegram/danog magic
# Sort by message date
no_date = datetime.fromtimestamp(0)
dialogs = sorted(
list(dialogs.values()),
key=lambda d: getattr(messages[d.top_message], 'date', no_date)
)
return ( return (
r.dialogs, dialogs,
[find_user_or_chat(d.peer, r.users, r.chats) for d in r.dialogs]) [find_user_or_chat(d.peer, entities, entities) for d in dialogs]
)
# endregion # endregion

View File

@ -302,24 +302,23 @@ def get_input_media(media, user_caption=None, is_photo=False):
def find_user_or_chat(peer, users, chats): def find_user_or_chat(peer, users, chats):
"""Finds the corresponding user or chat given a peer. """Finds the corresponding user or chat given a peer.
Returns None if it was not found""" Returns None if it was not found"""
try: if isinstance(peer, PeerUser):
if isinstance(peer, PeerUser): peer, where = peer.user_id, users
return next(u for u in users if u.id == peer.user_id) else:
where = chats
elif isinstance(peer, PeerChat): if isinstance(peer, PeerChat):
return next(c for c in chats if c.id == peer.chat_id) peer = peer.chat_id
elif isinstance(peer, PeerChannel): elif isinstance(peer, PeerChannel):
return next(c for c in chats if c.id == peer.channel_id) peer = peer.channel_id
except StopIteration: return
if isinstance(peer, int): if isinstance(peer, int):
try: return next(u for u in users if u.id == peer) if isinstance(where, dict):
except StopIteration: pass return where.get(peer)
else:
try: return next(c for c in chats if c.id == peer) try:
except StopIteration: pass return next(x for x in where if x.id == peer)
except StopIteration:
pass
def get_appropriated_part_size(file_size): def get_appropriated_part_size(file_size):