diff --git a/docs/source/pyrogram/Client.rst b/docs/source/pyrogram/Client.rst index 14796ef2..78b5a32b 100644 --- a/docs/source/pyrogram/Client.rst +++ b/docs/source/pyrogram/Client.rst @@ -62,6 +62,7 @@ Messages delete_messages get_messages get_history + iter_history send_poll vote_poll retract_vote diff --git a/pyrogram/client/methods/messages/__init__.py b/pyrogram/client/methods/messages/__init__.py index 237b6493..d5d81044 100644 --- a/pyrogram/client/methods/messages/__init__.py +++ b/pyrogram/client/methods/messages/__init__.py @@ -25,6 +25,7 @@ from .edit_message_text import EditMessageText from .forward_messages import ForwardMessages from .get_history import GetHistory from .get_messages import GetMessages +from .iter_history import IterHistory from .retract_vote import RetractVote from .send_animation import SendAnimation from .send_audio import SendAudio @@ -70,6 +71,7 @@ class Messages( SendPoll, VotePoll, RetractVote, - DownloadMedia + DownloadMedia, + IterHistory ): pass diff --git a/pyrogram/client/methods/messages/iter_history.py b/pyrogram/client/methods/messages/iter_history.py new file mode 100644 index 00000000..ab587988 --- /dev/null +++ b/pyrogram/client/methods/messages/iter_history.py @@ -0,0 +1,93 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-2019 Dan Tès +# +# This file is part of Pyrogram. +# +# Pyrogram is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pyrogram is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Pyrogram. If not, see . + +from typing import Union, Generator + +import pyrogram +from ...ext import BaseClient + + +class IterHistory(BaseClient): + def iter_history(self, + chat_id: Union[int, str], + limit: int = 0, + offset: int = 0, + offset_id: int = 0, + offset_date: int = 0, + reverse: bool = False) -> Generator["pyrogram.Message", None, None]: + """Use this method to iterate through a chat history sequentially. + + This convenience method does the same as repeatedly calling :meth:`get_history` in a loop, thus saving you from + the hassle of setting up boilerplate code. It is useful for getting the whole chat history with a single call. + + Args: + chat_id (``int`` | ``str``): + Unique identifier (int) or username (str) of the target chat. + For your personal cloud (Saved Messages) you can simply use "me" or "self". + For a contact that exists in your Telegram address book you can use his phone number (str). + + limit (``int``, *optional*): + Limits the number of messages to be retrieved. + By default, no limit is applied and all messages are returned. + + offset (``int``, *optional*): + Sequential number of the first message to be returned.. + Negative values are also accepted and become useful in case you set offset_id or offset_date. + + offset_id (``int``, *optional*): + Identifier of the first message to be returned. + + offset_date (``int``, *optional*): + Pass a date in Unix time as offset to retrieve only older messages starting from that date. + + reverse (``bool``, *optional*): + Pass True to retrieve the messages in reversed order (from older to most recent). + + Returns: + A generator yielding :obj:`Message ` objects. + + Raises: + :class:`Error ` in case of a Telegram RPC error. + """ + offset_id = offset_id or (1 if reverse else 0) + current = 0 + total = limit or (1 << 31) - 1 + limit = min(100, total) + + while True: + messages = self.get_history( + chat_id=chat_id, + limit=limit, + offset=offset, + offset_id=offset_id, + offset_date=offset_date, + reverse=reverse + ).messages + + if not messages: + return + + offset_id = messages[-1].message_id + (1 if reverse else 0) + + for message in messages: + yield message + + current += 1 + + if current >= total: + return