Skip to content

Commit ddad27a

Browse files
authored
rewrite get_messages, again
Closes #150 - Removed occurrence of ChannelPrivate when clicking bot callback button - Fixed conditions for Iterable, in some of the places
1 parent 512dff1 commit ddad27a

File tree

11 files changed

+217
-74
lines changed

11 files changed

+217
-74
lines changed

compiler/docs/compiler.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,9 @@ def get_title_list(s: str) -> list:
210210
get_chat_history_count
211211
read_chat_history
212212
get_messages
213+
get_chat_pinned_message
214+
get_callback_query_message
215+
get_replied_message
213216
view_messages
214217
get_discussion_message
215218
get_discussion_replies

docs/source/releases/changes-in-this-fork.rst

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ Breaking Changes in this Fork
1515
==============================
1616

1717
- In :meth:`~pyrogram.Client.download_media`, if the message is a :obj:`~pyrogram.types.PaidMediaInfo` with more than one ``paid_media`` **and** ``idx`` was not specified, then a list of paths or binary file-like objects is returned.
18-
- Make :meth:`~pyrogram.Client.get_messages` accept only keyword-only arguments. `48d4230 <https://github.com/TelegramPlayGround/pyrogram/commit/48d42304f3ee51034d515919320634935e6b2c83>`_
1918
- PR `#115 <https://github.com/TelegramPlayGround/pyrogram/pull/115>`_ This `change <https://github.com/pyrogram/pyrogram/pull/966#issuecomment-1108858881>`_ breaks some usages with offset-naive and offset-aware datetimes.
2019
- PR from upstream: `#1411 <https://github.com/pyrogram/pyrogram/pull/1411>`_ without attribution.
2120

@@ -32,9 +31,9 @@ Changes in this Fork
3231
| Scheme layer used: 198 |
3332
+------------------------+
3433

34+
- Splitted the :meth:`~pyrogram.Client.get_messages` into :meth:`~pyrogram.Client.get_chat_pinned_message`, :meth:`~pyrogram.Client.get_callback_query_message`, and :meth:`~pyrogram.Client.get_replied_message`.
3535
- Updated :doc:`Message Identifiers <../../topics/text-formatting>`.
3636
- Added ``message.content`` property.
37-
- Added the parameter ``pinned`` and made the parameter ``chat_id`` optional in :meth:`~pyrogram.Client.get_messages`. **NOTE**: Please be aware about using the correct :doc:`Message Identifiers <../../topics/message-identifiers>`, when using this method.
3837
- Added the ``cover`` and ``start_timestamp`` parameters in :meth:`~pyrogram.Client.send_video` and :obj:`~pyrogram.types.InputPaidMediaVideo`.
3938
- Added the ``video_start_timestamp`` and renamed the ``send_copy`` and ``remove_caption`` parameters in :meth:`~pyrogram.Client.forward_messages` and :meth:`~pyrogram.types.Message.forward`.
4039
- Added the ``gift_count`` to the :obj:`~pyrogram.types.Chat`.

pyrogram/methods/chat_topics/get_forum_topic.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
1818

1919
import logging
20-
from typing import Union, Iterable
20+
from collections.abc import Iterable
21+
from typing import Union
2122

2223
import pyrogram
2324
from pyrogram import raw
@@ -59,7 +60,8 @@ async def get_forum_topic(
5960
Raises:
6061
ValueError: In case of invalid arguments.
6162
"""
62-
is_iterable = not isinstance(message_thread_ids, int)
63+
64+
is_iterable = isinstance(message_thread_ids, Iterable)
6365
ids = list(message_thread_ids) if is_iterable else [message_thread_ids]
6466

6567
r = await self.invoke(

pyrogram/methods/messages/forward_messages.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,9 @@
1616
# You should have received a copy of the GNU Lesser General Public License
1717
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
1818

19+
from collections.abc import Iterable
1920
from datetime import datetime
20-
from typing import Union, Iterable
21+
from typing import Union
2122

2223
import pyrogram
2324
from pyrogram import raw, utils
@@ -104,7 +105,7 @@ async def forward_messages(
104105
await app.forward_messages(to_chat, from_chat, [1, 2, 3])
105106
"""
106107

107-
is_iterable = not isinstance(message_ids, int)
108+
is_iterable = isinstance(message_ids, Iterable)
108109
message_ids = list(message_ids) if is_iterable else [message_ids]
109110

110111
r = await self.invoke(

pyrogram/methods/messages/get_messages.py

Lines changed: 152 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
1818

1919
import logging
20-
from typing import Union, Iterable
20+
from collections.abc import Iterable
21+
from typing import Optional, Union
2122

2223
import pyrogram
2324
from pyrogram import raw, types, utils
@@ -29,11 +30,8 @@
2930
class GetMessages:
3031
async def get_messages(
3132
self: "pyrogram.Client",
32-
*,
3333
chat_id: Union[int, str] = None,
3434
message_ids: Union[int, Iterable[int]] = None,
35-
reply_to_message_ids: Union[int, Iterable[int]] = None,
36-
pinned: bool = False,
3735
replies: int = 1,
3836
is_scheduled: bool = False,
3937
link: str = None,
@@ -46,7 +44,7 @@ async def get_messages(
4644
4745
.. include:: /_includes/usable-by/users-bots.rst
4846
49-
You must use exactly one of ``message_ids`` OR ``reply_to_message_ids`` OR (``chat_id``, ``message_ids``) OR (``chat_id``, ``reply_to_message_ids``) OR (``chat_id``, ``pinned``) OR ``link``.
47+
You must use exactly one of ``message_ids`` OR (``chat_id``, ``message_ids``) OR ``link``.
5048
5149
Parameters:
5250
chat_id (``int`` | ``str``, *optional*):
@@ -58,14 +56,6 @@ async def get_messages(
5856
Pass a single message identifier or an iterable of message ids (as integers) to get the content of the
5957
message themselves.
6058
61-
reply_to_message_ids (``int`` | Iterable of ``int``, *optional*):
62-
Pass a single message identifier or an iterable of message ids (as integers) to get the content of
63-
the previous message you replied to using this message.
64-
65-
pinned (``bool``, *optional*):
66-
Returns information about the newest pinned message in the specified ``chat_id``. Other parameters are ignored when this is set.
67-
Use :meth:`~pyrogram.Client.search_messages` to return all the pinned messages.
68-
6959
replies (``int``, *optional*):
7060
The number of subsequent replies to get for each message.
7161
Pass 0 for no reply at all or -1 for unlimited replies.
@@ -98,22 +88,13 @@ async def get_messages(
9888
# Get message with all chained replied-to messages
9989
await app.get_messages(chat_id=chat_id, message_ids=message_id, replies=-1)
10090
101-
# Get the replied-to message of a message
102-
await app.get_messages(chat_id=chat_id, reply_to_message_ids=message_id)
103-
10491
Raises:
10592
ValueError: In case of invalid arguments.
10693
"""
10794

108-
if message_ids or reply_to_message_ids:
109-
ids, ids_type = (
110-
(message_ids, raw.types.InputMessageID) if message_ids
111-
else (reply_to_message_ids, raw.types.InputMessageReplyTo) if reply_to_message_ids
112-
else (None, None)
113-
)
114-
115-
is_iterable = not isinstance(ids, int)
116-
ids = list(ids) if is_iterable else [ids]
95+
if message_ids:
96+
is_iterable = isinstance(message_ids, Iterable)
97+
ids = list(message_ids) if is_iterable else [message_ids]
11798

11899
if replies < 0:
119100
replies = (1 << 31) - 1
@@ -126,7 +107,7 @@ async def get_messages(
126107
id=ids
127108
)
128109
else:
129-
ids = [ids_type(id=i) for i in ids]
110+
ids = [raw.types.InputMessageID(id=i) for i in ids]
130111
if chat_id and isinstance(peer, raw.types.InputPeerChannel):
131112
rpc = raw.functions.channels.GetMessages(channel=peer, id=ids)
132113
else:
@@ -143,18 +124,6 @@ async def get_messages(
143124

144125
return messages if is_iterable else messages[0] if messages else None
145126

146-
if chat_id and pinned:
147-
peer = await self.resolve_peer(chat_id)
148-
rpc = raw.functions.channels.GetMessages(channel=peer, id=[raw.types.InputMessagePinned()])
149-
r = await self.invoke(rpc, sleep_threshold=-1)
150-
messages = await utils.parse_messages(
151-
self,
152-
r,
153-
is_scheduled=False,
154-
replies=replies
155-
)
156-
return messages[0] if messages else None
157-
158127
if link:
159128
linkps = link.split("/")
160129
raw_chat_id, message_thread_id, message_id = None, None, None
@@ -234,3 +203,148 @@ async def get_messages(
234203
)
235204

236205
raise ValueError("No valid argument supplied. https://telegramplayground.github.io/pyrogram/api/methods/get_messages")
206+
207+
208+
async def get_chat_pinned_message(
209+
self: "pyrogram.Client",
210+
chat_id: Union[int, str],
211+
replies: int = 1
212+
) -> Optional["types.Message"]:
213+
"""Returns information about a newest pinned message in the chat.
214+
Use :meth:`~pyrogram.Client.search_messages` to return all the pinned messages.
215+
216+
.. include:: /_includes/usable-by/users-bots.rst
217+
218+
Parameters:
219+
chat_id (``int`` | ``str``):
220+
Unique identifier (int) or username (str) of the target chat.
221+
For your personal cloud (Saved Messages) you can simply use "me" or "self".
222+
For a contact that exists in your Telegram address book you can use his phone number (str).
223+
224+
replies (``int``, *optional*):
225+
The number of subsequent replies to get for each message.
226+
Pass 0 for no reply at all or -1 for unlimited replies.
227+
Defaults to 1.
228+
229+
"""
230+
231+
peer = await self.resolve_peer(chat_id)
232+
if not isinstance(peer, raw.types.InputPeerChannel):
233+
raise ValueError("chat_id must belong to a supergroup or channel.")
234+
rpc = raw.functions.channels.GetMessages(channel=peer, id=[raw.types.InputMessagePinned()])
235+
r = await self.invoke(rpc, sleep_threshold=-1)
236+
if replies < 0:
237+
replies = (1 << 31) - 1
238+
messages = await utils.parse_messages(
239+
self,
240+
r,
241+
is_scheduled=False,
242+
replies=replies
243+
)
244+
return messages[0] if messages else None
245+
246+
247+
async def get_callback_query_message(
248+
self: "pyrogram.Client",
249+
chat_id: Union[int, str],
250+
message_id: int,
251+
callback_query_id: int,
252+
replies: int = 1
253+
) -> Optional["types.Message"]:
254+
"""Returns information about a message with the callback button that originated a callback query.
255+
256+
.. include:: /_includes/usable-by/bots.rst
257+
258+
Parameters:
259+
chat_id (``int`` | ``str``, *optional*):
260+
Unique identifier (int) or username (str) of the target chat.
261+
For your personal cloud (Saved Messages) you can simply use "me" or "self".
262+
For a contact that exists in your Telegram address book you can use his phone number (str).
263+
264+
message_id (``int``):
265+
Message identifier.
266+
267+
callback_query_id (``int``):
268+
Identifier of the callback query.
269+
270+
replies (``int``, *optional*):
271+
The number of subsequent replies to get for each message.
272+
Pass 0 for no reply at all or -1 for unlimited replies.
273+
Defaults to 1.
274+
275+
"""
276+
277+
peer = await self.resolve_peer(chat_id)
278+
ids = [raw.types.InputMessageCallbackQuery(id=message_id, query_id=callback_query_id)]
279+
if isinstance(peer, raw.types.InputPeerChannel):
280+
rpc = raw.functions.channels.GetMessages(channel=peer, id=ids)
281+
else:
282+
rpc = raw.functions.messages.GetMessages(id=ids)
283+
r = await self.invoke(rpc, sleep_threshold=-1)
284+
if replies < 0:
285+
replies = (1 << 31) - 1
286+
messages = await utils.parse_messages(
287+
self,
288+
r,
289+
is_scheduled=False,
290+
replies=replies
291+
)
292+
return messages[0] if messages else None
293+
294+
295+
async def get_replied_message(
296+
self: "pyrogram.Client",
297+
chat_id: Union[int, str],
298+
message_ids: Union[int, Iterable[int]],
299+
replies: int = 1
300+
) -> Optional["types.Message"]:
301+
"""Returns information about a non-bundled message that is replied by a given message.
302+
303+
.. include:: /_includes/usable-by/users-bots.rst
304+
305+
Also, returns the pinned message, the game message, the invoice message,
306+
the message with a previously set same background, the giveaway message, and the topic creation message for messages of the types
307+
messagePinMessage, messageGameScore, messagePaymentSuccessful, messageChatSetBackground, messageGiveawayCompleted and topic messages
308+
without non-bundled replied message respectively.
309+
310+
Parameters:
311+
chat_id (``int`` | ``str``):
312+
Unique identifier (int) or username (str) of the target chat.
313+
For your personal cloud (Saved Messages) you can simply use "me" or "self".
314+
For a contact that exists in your Telegram address book you can use his phone number (str).
315+
316+
message_ids (``int`` | Iterable of ``int``):
317+
Pass a single message identifier or an iterable of message ids (as integers) to get the content of
318+
the previous message you replied to using this message.
319+
320+
replies (``int``, *optional*):
321+
The number of subsequent replies to get for each message.
322+
Pass 0 for no reply at all or -1 for unlimited replies.
323+
Defaults to 1.
324+
325+
Example:
326+
.. code-block:: python
327+
328+
# Get the replied-to message of a message
329+
await app.get_replied_message(chat_id=chat_id, message_ids=message_id)
330+
331+
"""
332+
333+
peer = await self.resolve_peer(chat_id)
334+
is_iterable = isinstance(message_ids, Iterable)
335+
ids = list(message_ids) if is_iterable else [message_ids]
336+
ids = [raw.types.InputMessageReplyTo(id=i) for i in ids]
337+
if isinstance(peer, raw.types.InputPeerChannel):
338+
rpc = raw.functions.channels.GetMessages(channel=peer, id=ids)
339+
else:
340+
rpc = raw.functions.messages.GetMessages(id=ids)
341+
r = await self.invoke(rpc, sleep_threshold=-1)
342+
if replies < 0:
343+
replies = (1 << 31) - 1
344+
messages = await utils.parse_messages(
345+
self,
346+
r,
347+
is_scheduled=False,
348+
replies=replies
349+
)
350+
return messages if is_iterable else messages[0] if messages else None

pyrogram/methods/stories/get_stories.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@
1616
# You should have received a copy of the GNU Lesser General Public License
1717
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
1818

19-
from typing import Union, Iterable
19+
from collections.abc import Iterable
20+
from typing import Union
2021

2122
import pyrogram
2223
from pyrogram import raw, types
@@ -56,7 +57,8 @@ async def get_stories(
5657
for story in stories:
5758
print(story)
5859
"""
59-
is_iterable = not isinstance(story_ids, int)
60+
61+
is_iterable = isinstance(story_ids, Iterable)
6062
ids = list(story_ids) if is_iterable else [story_ids]
6163

6264
peer = await self.resolve_peer(story_sender_chat_id)

pyrogram/methods/users/get_users.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
1818

1919
import asyncio
20-
from typing import Union, Iterable
20+
from collections.abc import Iterable
21+
from typing import Union
2122

2223
import pyrogram
2324
from pyrogram import raw
@@ -53,7 +54,7 @@ async def get_users(
5354
await app.get_users([user_id1, user_id2, user_id3])
5455
"""
5556

56-
is_iterable = not isinstance(user_ids, (int, str))
57+
is_iterable = isinstance(user_ids, Iterable)
5758
user_ids = list(user_ids) if is_iterable else [user_ids]
5859
user_ids = await asyncio.gather(*[self.resolve_peer(i) for i in user_ids])
5960

pyrogram/types/bots_and_keyboards/callback_query.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
# You should have received a copy of the GNU Lesser General Public License
1717
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
1818

19+
1920
import re
2021
from typing import Union, Optional
2122

@@ -98,14 +99,13 @@ async def _parse(client: "pyrogram.Client", callback_query, users, chats) -> "Ca
9899
message_id = callback_query.msg_id
99100

100101
message = client.message_cache[(chat_id, message_id)]
101-
102102
if not message:
103-
try:
104-
message = await client.get_messages(
105-
chat_id=chat_id,
106-
message_ids=message_id
107-
)
108-
except ChannelPrivate:
103+
message = await client.get_callback_query_message(
104+
chat_id=chat_id,
105+
message_id=message_id,
106+
callback_query_id=callback_query.query_id
107+
)
108+
if not message:
109109
channel = chats.get(peer_id, None)
110110
if channel:
111111
message = types.Message(

0 commit comments

Comments
 (0)