diff --git a/compiler/docs/compiler.py b/compiler/docs/compiler.py index 6b596b2f..8afd99f8 100644 --- a/compiler/docs/compiler.py +++ b/compiler/docs/compiler.py @@ -176,6 +176,7 @@ def pyrogram_api(): retract_vote send_dice search_messages + search_global download_media """, chats=""" diff --git a/pyrogram/client/methods/messages/__init__.py b/pyrogram/client/methods/messages/__init__.py index 3df4e7ce..e78d2bc5 100644 --- a/pyrogram/client/methods/messages/__init__.py +++ b/pyrogram/client/methods/messages/__init__.py @@ -33,11 +33,14 @@ from .get_messages import GetMessages from .iter_history import IterHistory from .read_history import ReadHistory from .retract_vote import RetractVote +from .search_global import SearchGlobal +from .search_messages import SearchMessages from .send_animation import SendAnimation from .send_audio import SendAudio from .send_cached_media import SendCachedMedia from .send_chat_action import SendChatAction from .send_contact import SendContact +from .send_dice import SendDice from .send_document import SendDocument from .send_location import SendLocation from .send_media_group import SendMediaGroup @@ -51,8 +54,6 @@ from .send_video_note import SendVideoNote from .send_voice import SendVoice from .stop_poll import StopPoll from .vote_poll import VotePoll -from .send_dice import SendDice -from .search_messages import SearchMessages class Messages( @@ -92,6 +93,7 @@ class Messages( EditInlineMedia, EditInlineReplyMarkup, SendDice, - SearchMessages + SearchMessages, + SearchGlobal ): pass diff --git a/pyrogram/client/methods/messages/search_global.py b/pyrogram/client/methods/messages/search_global.py new file mode 100644 index 00000000..45262d78 --- /dev/null +++ b/pyrogram/client/methods/messages/search_global.py @@ -0,0 +1,96 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-2020 Dan +# +# 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 Generator + +import pyrogram +from pyrogram.api import functions, types +from pyrogram.client.ext import BaseClient, utils + + +class SearchGlobal(BaseClient): + def search_global( + self, + query: str, + limit: int = 0, + ) -> Generator["pyrogram.Message", None, None]: + """Search messages globally from all of your chats. + + .. note:: + + Due to server-side limitations, you can only get up to around ~10,000 messages and each message + retrieved will not have any *reply_to_message* field. + + Parameters: + query (``str``): + Text query string. + + limit (``int``, *optional*): + Limits the number of messages to be retrieved. + By default, no limit is applied and all messages are returned. + + Returns: + ``Generator``: A generator yielding :obj:`Message` objects. + + Example: + .. code-block:: python + + # Search for "pyrogram". Get the first 420 results + for message in app.search_global("pyrogram", limit=420): + print(message.text) + """ + current = 0 + # There seems to be an hard limit of 10k, beyond which Telegram starts spitting one message at a time. + total = abs(limit) or (1 << 31) + limit = min(100, total) + + offset_date = 0 + offset_peer = types.InputPeerEmpty() + offset_id = 0 + + while True: + messages = utils.parse_messages( + self, + self.send( + functions.messages.SearchGlobal( + q=query, + offset_rate=offset_date, + offset_peer=offset_peer, + offset_id=offset_id, + limit=limit + ) + ), + replies=0 + ) + + if not messages: + return + + last = messages[-1] + + offset_date = last.date + offset_peer = self.resolve_peer(last.chat.id) + offset_id = last.message_id + + for message in messages: + yield message + + current += 1 + + if current >= total: + return