Fix a dialog's message could be wrong in rare cases

This commit is contained in:
Lonami Exo 2019-07-23 12:44:19 +02:00
parent eb44c6634b
commit 5a225d1668
2 changed files with 20 additions and 11 deletions

View File

@ -12,6 +12,17 @@ if typing.TYPE_CHECKING:
from .telegramclient import TelegramClient from .telegramclient import TelegramClient
def _dialog_message_key(peer, message_id):
"""
Get the key to get messages from a dialog.
We cannot just use the message ID because channels share message IDs,
and the peer ID is required to distinguish between them. But it is not
necessary in small group chats and private chats.
"""
return (peer.channel_id if isinstance(peer, types.PeerChannel) else None), message_id
class _DialogsIter(RequestIter): class _DialogsIter(RequestIter):
async def _init( async def _init(
self, offset_date, offset_id, offset_peer, ignore_pinned, ignore_migrated, folder self, offset_date, offset_id, offset_peer, ignore_pinned, ignore_migrated, folder
@ -48,21 +59,20 @@ class _DialogsIter(RequestIter):
messages = {} messages = {}
for m in r.messages: for m in r.messages:
m._finish_init(self.client, entities, None) m._finish_init(self.client, entities, None)
messages[m.id] = m messages[_dialog_message_key(m.to_id, m.id)] = m
for d in r.dialogs: for d in r.dialogs:
# We check the offset date here because Telegram may ignore it # We check the offset date here because Telegram may ignore it
message = messages.get(_dialog_message_key(d.peer, d.top_message))
if self.offset_date: if self.offset_date:
date = getattr(messages.get( date = getattr(message, 'date', None)
d.top_message, None), 'date', None)
if not date or date.timestamp() > self.offset_date.timestamp(): if not date or date.timestamp() > self.offset_date.timestamp():
continue continue
peer_id = utils.get_peer_id(d.peer) peer_id = utils.get_peer_id(d.peer)
if peer_id not in self.seen: if peer_id not in self.seen:
self.seen.add(peer_id) self.seen.add(peer_id)
cd = custom.Dialog(self.client, d, entities, messages) cd = custom.Dialog(self.client, d, entities, message)
if cd.dialog.pts: if cd.dialog.pts:
self.client._channel_pts[cd.id] = cd.dialog.pts self.client._channel_pts[cd.id] = cd.dialog.pts
@ -80,11 +90,10 @@ class _DialogsIter(RequestIter):
# Why? Because pinned dialogs will mess with the order # Why? Because pinned dialogs will mess with the order
# in this list. Instead, we find the last dialog which # in this list. Instead, we find the last dialog which
# has a message, and use it as an offset. # has a message, and use it as an offset.
last_message = next(( last_message = next(filter(None, (
messages[d.top_message] messages.get(_dialog_message_key(d.peer, d.top_message))
for d in reversed(r.dialogs) for d in reversed(r.dialogs)
if d.top_message in messages )), None)
), None)
self.request.exclude_pinned = True self.request.exclude_pinned = True
self.request.offset_id = last_message.id if last_message else 0 self.request.offset_id = last_message.id if last_message else 0

View File

@ -69,14 +69,14 @@ class Dialog:
is_channel (`bool`): is_channel (`bool`):
`True` if the `entity` is a :tl:`Channel`. `True` if the `entity` is a :tl:`Channel`.
""" """
def __init__(self, client, dialog, entities, messages): def __init__(self, client, dialog, entities, message):
# Both entities and messages being dicts {ID: item} # Both entities and messages being dicts {ID: item}
self._client = client self._client = client
self.dialog = dialog self.dialog = dialog
self.pinned = bool(dialog.pinned) self.pinned = bool(dialog.pinned)
self.folder_id = dialog.folder_id self.folder_id = dialog.folder_id
self.archived = dialog.folder_id is not None self.archived = dialog.folder_id is not None
self.message = messages.get(dialog.top_message, None) self.message = message
self.date = getattr(self.message, 'date', None) self.date = getattr(self.message, 'date', None)
self.entity = entities[utils.get_peer_id(dialog.peer)] self.entity = entities[utils.get_peer_id(dialog.peer)]