diff --git a/compiler/docs/compiler.py b/compiler/docs/compiler.py index 3cdf311f9..e9a81a085 100644 --- a/compiler/docs/compiler.py +++ b/compiler/docs/compiler.py @@ -208,6 +208,8 @@ def get_title_list(s: str) -> list: search_messages_count search_global search_global_count + search_global_hashtag_messages + search_global_hashtag_messages_count download_media stream_media get_discussion_message diff --git a/pyrogram/methods/messages/__init__.py b/pyrogram/methods/messages/__init__.py index 5314d93be..ed2a352a9 100644 --- a/pyrogram/methods/messages/__init__.py +++ b/pyrogram/methods/messages/__init__.py @@ -43,6 +43,8 @@ from .retract_vote import RetractVote from .search_global import SearchGlobal from .search_global_count import SearchGlobalCount +from .search_global_hashtag_messages import SearchGlobalHashtagMessages +from .search_global_hashtag_messages_count import SearchGlobalHashtagMessagesCount from .search_messages import SearchMessages from .search_messages_count import SearchMessagesCount from .send_animation import SendAnimation @@ -110,10 +112,12 @@ class Messages( SendDice, SearchMessages, SearchGlobal, + SearchGlobalHashtagMessages, CopyMessage, CopyMediaGroup, SearchMessagesCount, SearchGlobalCount, + SearchGlobalHashtagMessagesCount, GetDiscussionMessage, SendReaction, GetDiscussionReplies, diff --git a/pyrogram/methods/messages/search_global_hashtag_messages.py b/pyrogram/methods/messages/search_global_hashtag_messages.py new file mode 100644 index 000000000..ae9112e3c --- /dev/null +++ b/pyrogram/methods/messages/search_global_hashtag_messages.py @@ -0,0 +1,102 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-present 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 datetime import datetime +from typing import AsyncGenerator + +import pyrogram +from pyrogram import raw, types, utils + + +class SearchGlobalHashtagMessages: + async def search_global_hashtag_messages( + self: "pyrogram.Client", + hashtag: str = "", + offset_id: int = 0, + offset_date: datetime = utils.zero_datetime(), + limit: int = 0, + ) -> AsyncGenerator["types.Message", None]: + """Searches for public channel posts with the given hashtag. For optimal performance, the number of returned messages is chosen by Telegram Server and can be smaller than the specified limit. + + If you want to get the posts count only, see :meth:`~pyrogram.Client.search_public_hashtag_messages_count`. + + .. include:: /_includes/usable-by/users.rst + + Parameters: + hashtag (``str``, *optional*): + Hashtag to search for. + + offset_id (``int``, *optional*): + Offset of the first entry to return as received from the previous request; use empty string to get the first chunk of results. + + offset_date (:py:obj:`~datetime.datetime`, *optional*): + Pass a date as offset to retrieve only older messages starting from that date. + + limit (``int``, *optional*): + The maximum number of messages to be returned. + By default, no limit is applied and all posts are returned. + + Returns: + ``Generator``: A generator yielding :obj:`~pyrogram.types.Message` objects. + + Example: + .. code-block:: python + + # Search for "#pyrogram". Get the first 50 results + async for message in app.search_public_hashtag_messages("#pyrogram"): + print(message.text) + + """ + current = 0 + total = abs(limit) or (1 << 31) + limit = min(100, total) + + offset_peer = raw.types.InputPeerEmpty() + + while True: + messages = await utils.parse_messages( + self, + await self.invoke( + raw.functions.channels.SearchPosts( + hashtag=hashtag, + offset_rate=utils.datetime_to_timestamp(offset_date), + offset_peer=offset_peer, + offset_id=offset_id, + limit=limit + ), + sleep_threshold=60 + ), + replies=0 + ) + + if not messages: + return + + last = messages[-1] + + offset_date = utils.datetime_to_timestamp(last.date) + offset_peer = await self.resolve_peer(last.chat.id) + offset_id = last.id + + for message in messages: + yield message + + current += 1 + + if current >= total: + return diff --git a/pyrogram/methods/messages/search_global_hashtag_messages_count.py b/pyrogram/methods/messages/search_global_hashtag_messages_count.py new file mode 100644 index 000000000..b953e4c44 --- /dev/null +++ b/pyrogram/methods/messages/search_global_hashtag_messages_count.py @@ -0,0 +1,55 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-present 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 . + +import pyrogram +from pyrogram import raw + + +class SearchGlobalHashtagMessagesCount: + async def search_golbal_hashtag_messages_count( + self: "pyrogram.Client", + hashtag: str = "", + ) -> int: + """Get the count of messages with the provided hashtag. + + If you want to get the actual messages, see :meth:`~pyrogram.Client.search_public_hashtag_messages`. + + .. include:: /_includes/usable-by/users.rst + + Parameters: + hashtag (``str``, *optional*): + Hashtag to search for. + + Returns: + ``int``: On success, the messages count is returned. + + """ + r = await self.invoke( + raw.functions.channels.SearchPosts( + hashtag=hashtag, + offset_rate=0, + offset_peer=raw.types.InputPeerEmpty(), + offset_id=0, + limit=1 + ) + ) + + if hasattr(r, "count"): + return r.count + else: + return len(r.messages)