pyroflow 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pyroflow/__init__.py +14 -0
- pyroflow/__meta__.py +1 -0
- pyroflow/client.py +413 -0
- pyroflow/dispatcher.py +503 -0
- pyroflow/enums.py +10 -0
- pyroflow/errors.py +20 -0
- pyroflow/listener_coordinator/__init__.py +11 -0
- pyroflow/listener_coordinator/listener_coordinator.py +151 -0
- pyroflow/listener_coordinator/memory_listener_coordinator.py +74 -0
- pyroflow/listener_coordinator/redis_listener_coordinator.py +280 -0
- pyroflow/models.py +64 -0
- pyroflow/types.py +304 -0
- pyroflow/typings.py +15 -0
- pyroflow/update_coordinated/__init__.py +11 -0
- pyroflow/update_coordinated/callback_query_coordinated.py +31 -0
- pyroflow/update_coordinated/message_coordinated.py +38 -0
- pyroflow/update_coordinated/update_coordinated.py +204 -0
- pyroflow/update_coordinator/__init__.py +11 -0
- pyroflow/update_coordinator/memory_update_coordinator.py +43 -0
- pyroflow/update_coordinator/redis_update_coordinator.py +54 -0
- pyroflow/update_coordinator/update_coordinator.py +118 -0
- pyroflow/update_history/__init__.py +12 -0
- pyroflow/update_history/callback_query_history.py +56 -0
- pyroflow/update_history/message_history.py +6 -0
- pyroflow/update_history/update_history.py +306 -0
- pyroflow/update_history_store/__init__.py +9 -0
- pyroflow/update_history_store/memory_update_history_store.py +117 -0
- pyroflow/update_history_store/update_history_store.py +93 -0
- pyroflow/update_listener/__init__.py +11 -0
- pyroflow/update_listener/callback_query_listener.py +82 -0
- pyroflow/update_listener/message_listener.py +48 -0
- pyroflow/update_listener/update_listener.py +391 -0
- pyroflow/utils/__init__.py +19 -0
- pyroflow/utils/async_tools.py +220 -0
- pyroflow/utils/classes.py +100 -0
- pyroflow/utils/enums.py +15 -0
- pyroflow/utils/iter_tools.py +30 -0
- pyroflow/utils/misc_tools.py +67 -0
- pyroflow/utils/typings.py +88 -0
- pyroflow/utils/validate_tools.py +30 -0
- pyroflow-0.1.0.dist-info/METADATA +271 -0
- pyroflow-0.1.0.dist-info/RECORD +44 -0
- pyroflow-0.1.0.dist-info/WHEEL +4 -0
- pyroflow-0.1.0.dist-info/licenses/LICENSE +21 -0
pyroflow/__init__.py
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from .listener_coordinator import *
|
|
2
|
+
from .update_coordinated import *
|
|
3
|
+
from .update_coordinator import *
|
|
4
|
+
from .update_history import *
|
|
5
|
+
from .update_history_store import *
|
|
6
|
+
from .update_listener import *
|
|
7
|
+
|
|
8
|
+
from .client import Client
|
|
9
|
+
from .dispatcher import Dispatcher
|
|
10
|
+
|
|
11
|
+
from .types import Message, CallbackQuery
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
pyroflow/__meta__.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.1.0"
|
pyroflow/client.py
ADDED
|
@@ -0,0 +1,413 @@
|
|
|
1
|
+
from typing import TYPE_CHECKING, Type, Dict, List, Optional, Union, overload
|
|
2
|
+
from datetime import datetime
|
|
3
|
+
|
|
4
|
+
from pyrogram import (
|
|
5
|
+
Client as PyroClient,
|
|
6
|
+
enums as pyro_enums,
|
|
7
|
+
types as pyro_types,
|
|
8
|
+
utils as pyro_ut
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
from .utils.typings import Number, JsonValueT, UpdateType
|
|
12
|
+
from .utils import patch_cls
|
|
13
|
+
|
|
14
|
+
from .types import Message, CallbackQuery
|
|
15
|
+
|
|
16
|
+
from .dispatcher import Dispatcher
|
|
17
|
+
from .update_listener import UpdateListener
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@patch_cls
|
|
22
|
+
class Client(PyroClient):
|
|
23
|
+
"""
|
|
24
|
+
The main entry point of the library and the only class you need to
|
|
25
|
+
interact with directly.
|
|
26
|
+
|
|
27
|
+
Extends :class:`pyrogram.Client` with a conversation-oriented API that
|
|
28
|
+
lets you ``await`` a specific reply from a specific user rather than
|
|
29
|
+
wiring up global handlers for every possible update.
|
|
30
|
+
|
|
31
|
+
Why this exists
|
|
32
|
+
---------------
|
|
33
|
+
Pyrogram's built-in model is handler-based: you register a function and
|
|
34
|
+
it fires for *every* incoming update of that type. That works well for
|
|
35
|
+
broadcast-style bots, but breaks down the moment you need a back-and-forth
|
|
36
|
+
conversation — you end up managing state machines by hand just to know
|
|
37
|
+
whose answer you are waiting for.
|
|
38
|
+
|
|
39
|
+
This client solves that by integrating three systems from :class:`Dispatcher`
|
|
40
|
+
and exposing them through a single, convenient interface:
|
|
41
|
+
|
|
42
|
+
- **Listeners** — typed queues that let any coroutine ``await`` the next
|
|
43
|
+
update from a particular user/chat. An update claimed by a listener never
|
|
44
|
+
reaches the normal handler pipeline.
|
|
45
|
+
|
|
46
|
+
- **Coordinators** — distributed locks attached per update type that ensure
|
|
47
|
+
an update is processed by exactly one session when the bot runs on multiple
|
|
48
|
+
servers simultaneously.
|
|
49
|
+
|
|
50
|
+
- **Histories** — per-update-type records of which handlers ran successfully,
|
|
51
|
+
enabling features like ``back`` buttons that replay previous steps.
|
|
52
|
+
|
|
53
|
+
What this class provides
|
|
54
|
+
------------------------
|
|
55
|
+
**Registration** — attach the above systems to the client before it starts:
|
|
56
|
+
|
|
57
|
+
.. code-block:: python
|
|
58
|
+
|
|
59
|
+
client.register_listener(MyMessageListener())
|
|
60
|
+
client.register_coordinated(MyCoordinated())
|
|
61
|
+
client.register_history(MyHistory())
|
|
62
|
+
|
|
63
|
+
**Shortcuts** — read-only properties for the two most common listeners:
|
|
64
|
+
|
|
65
|
+
.. code-block:: python
|
|
66
|
+
|
|
67
|
+
client.message_listen # UpdateListener[Message]
|
|
68
|
+
client.callback_listen # UpdateListener[CallbackQuery]
|
|
69
|
+
|
|
70
|
+
**``ask()``** — the core high-level method. Sends (or edits) a message and
|
|
71
|
+
then suspends until a matching reply arrives, all in one ``await``:
|
|
72
|
+
|
|
73
|
+
.. code-block:: python
|
|
74
|
+
|
|
75
|
+
answer = await client.ask(chat_id, "What is your name?",
|
|
76
|
+
listen_user_id=user_id, timeout=30)
|
|
77
|
+
|
|
78
|
+
Under the hood ``ask()`` calls :meth:`send_message` (or
|
|
79
|
+
:meth:`edit_message_text` when ``message_id`` is supplied), registers a
|
|
80
|
+
one-shot wait on the appropriate :class:`UpdateListener`, and returns the
|
|
81
|
+
matching update. A :exc:`ListenerTimeout` is raised if no reply arrives
|
|
82
|
+
within ``timeout`` seconds.
|
|
83
|
+
|
|
84
|
+
Note on ``@patch_cls``
|
|
85
|
+
------------------
|
|
86
|
+
The class is decorated with ``@patch_cls``, which passes every ``async`` method
|
|
87
|
+
through ``async_to_sync``. This means all methods can also be called
|
|
88
|
+
synchronously from outside an event loop, matching the behaviour of the
|
|
89
|
+
standard :class:`pyrogram.Client`.
|
|
90
|
+
|
|
91
|
+
Examples
|
|
92
|
+
--------
|
|
93
|
+
**Using ``ask()``** — send a question and wait for the reply in one step:
|
|
94
|
+
|
|
95
|
+
.. code-block:: python
|
|
96
|
+
|
|
97
|
+
from pyroflow import Client, MessageListener
|
|
98
|
+
|
|
99
|
+
client = Client("my_session")
|
|
100
|
+
client.register_listener(MessageListener())
|
|
101
|
+
|
|
102
|
+
@client.on_message()
|
|
103
|
+
async def on_start(client, message):
|
|
104
|
+
if message.text != "/start":
|
|
105
|
+
return
|
|
106
|
+
|
|
107
|
+
answer = await message.ask(
|
|
108
|
+
text="What is your name?",
|
|
109
|
+
listen_user_id=message.from_user.id,
|
|
110
|
+
timeout=60,
|
|
111
|
+
)
|
|
112
|
+
await answer.reply(f"Hello, {answer.text}!")
|
|
113
|
+
|
|
114
|
+
client.run()
|
|
115
|
+
|
|
116
|
+
**Using ``listen`` directly** — wait for an update anywhere in your code
|
|
117
|
+
without sending a message first:
|
|
118
|
+
|
|
119
|
+
.. code-block:: python
|
|
120
|
+
|
|
121
|
+
from pyroflow import Client, MessageListener
|
|
122
|
+
from pyroflow.errors import ListenerTimeout
|
|
123
|
+
|
|
124
|
+
client = Client("my_session")
|
|
125
|
+
client.register_listener(MessageListener())
|
|
126
|
+
|
|
127
|
+
@client.on_message()
|
|
128
|
+
async def on_confirm(client, message):
|
|
129
|
+
if message.text != "/confirm":
|
|
130
|
+
return
|
|
131
|
+
|
|
132
|
+
await message.reply("Please send your confirmation code:")
|
|
133
|
+
|
|
134
|
+
try:
|
|
135
|
+
code_msg = await client.message_listen(
|
|
136
|
+
chat_id=message.chat.id,
|
|
137
|
+
user_id=message.from_user.id,
|
|
138
|
+
timeout=120,
|
|
139
|
+
)
|
|
140
|
+
except ListenerTimeout:
|
|
141
|
+
await message.reply("Timed out. Please try again.")
|
|
142
|
+
return
|
|
143
|
+
|
|
144
|
+
await code_msg.reply(f"Code received: {code_msg.text}")
|
|
145
|
+
|
|
146
|
+
client.run()
|
|
147
|
+
"""
|
|
148
|
+
|
|
149
|
+
dispatcher: Dispatcher
|
|
150
|
+
|
|
151
|
+
@property
|
|
152
|
+
def listeners(self) -> Dict[Type[UpdateType], UpdateListener[UpdateType]]:
|
|
153
|
+
"""
|
|
154
|
+
Mapping from each update type to its registered :class:`UpdateListener`.
|
|
155
|
+
|
|
156
|
+
The key is the update type (e.g. ``Message`` or ``CallbackQuery``),
|
|
157
|
+
and the value is the listener responsible for awaiting that type.
|
|
158
|
+
"""
|
|
159
|
+
return self.dispatcher.listeners
|
|
160
|
+
|
|
161
|
+
@property
|
|
162
|
+
def message_listen(self) -> UpdateListener[Message]:
|
|
163
|
+
"""Shortcut to the :class:`UpdateListener` registered for :class:`Message` updates."""
|
|
164
|
+
return self.listeners[Message]
|
|
165
|
+
|
|
166
|
+
@property
|
|
167
|
+
def callback_listen(self) -> UpdateListener[CallbackQuery]:
|
|
168
|
+
"""Shortcut to the :class:`UpdateListener` registered for :class:`CallbackQuery` updates."""
|
|
169
|
+
return self.listeners[CallbackQuery]
|
|
170
|
+
|
|
171
|
+
if TYPE_CHECKING:
|
|
172
|
+
register_listener = Dispatcher.register_listener
|
|
173
|
+
register_coordinated = Dispatcher.register_coordinated
|
|
174
|
+
register_history = Dispatcher.register_history
|
|
175
|
+
|
|
176
|
+
unregister_listener = Dispatcher.unregister_listener
|
|
177
|
+
unregister_coordinated = Dispatcher.unregister_coordinated
|
|
178
|
+
unregister_history = Dispatcher.unregister_history
|
|
179
|
+
|
|
180
|
+
else:
|
|
181
|
+
def register_listener(self, value):
|
|
182
|
+
return self.dispatcher.register_listener(value)
|
|
183
|
+
|
|
184
|
+
def register_coordinated(self, value):
|
|
185
|
+
return self.dispatcher.register_coordinated(value)
|
|
186
|
+
|
|
187
|
+
def register_history(self, value):
|
|
188
|
+
return self.dispatcher.register_history(value)
|
|
189
|
+
|
|
190
|
+
async def unregister_listener(self, value):
|
|
191
|
+
return await self.dispatcher.unregister_listener(value)
|
|
192
|
+
|
|
193
|
+
async def unregister_coordinated(self, value):
|
|
194
|
+
return await self.dispatcher.unregister_coordinated(value)
|
|
195
|
+
|
|
196
|
+
async def unregister_history(self, value):
|
|
197
|
+
return await self.dispatcher.unregister_history(value)
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
@overload
|
|
201
|
+
async def ask(
|
|
202
|
+
self,
|
|
203
|
+
chat_id: Union[int, str],
|
|
204
|
+
text: str,
|
|
205
|
+
*,
|
|
206
|
+
parse_mode: Optional[pyro_enums.ParseMode] = None,
|
|
207
|
+
entities: Optional[List[pyro_types.MessageEntity]] = None,
|
|
208
|
+
link_preview_options: Optional[pyro_types.LinkPreviewOptions] = None,
|
|
209
|
+
reply_parameters: Optional[pyro_types.ReplyParameters] = None,
|
|
210
|
+
disable_notification: Optional[bool] = None,
|
|
211
|
+
message_thread_id: Optional[int] = None,
|
|
212
|
+
direct_messages_topic_id: Optional[int] = None,
|
|
213
|
+
effect_id: Optional[int] = None,
|
|
214
|
+
schedule_date: Optional[datetime] = None,
|
|
215
|
+
repeat_period: Optional[int] = None,
|
|
216
|
+
protect_content: Optional[bool] = None,
|
|
217
|
+
business_connection_id: Optional[str] = None,
|
|
218
|
+
allow_paid_broadcast: Optional[bool] = None,
|
|
219
|
+
paid_message_star_count: Optional[int] = None,
|
|
220
|
+
suggested_post_parameters: Optional[pyro_types.SuggestedPostParameters] = None,
|
|
221
|
+
reply_markup: Optional[Union[
|
|
222
|
+
pyro_types.InlineKeyboardMarkup,
|
|
223
|
+
pyro_types.ReplyKeyboardMarkup,
|
|
224
|
+
pyro_types.ReplyKeyboardRemove,
|
|
225
|
+
pyro_types.ForceReply,
|
|
226
|
+
]] = None,
|
|
227
|
+
# listen params
|
|
228
|
+
listen_user_id: Optional[int] = None,
|
|
229
|
+
listen_message_id: Optional[int] = None,
|
|
230
|
+
meta: Optional[JsonValueT] = None,
|
|
231
|
+
timeout: Optional[Number] = None,
|
|
232
|
+
update_type: Type[UpdateType] = Message,
|
|
233
|
+
**kw
|
|
234
|
+
) -> UpdateType: ...
|
|
235
|
+
|
|
236
|
+
@overload
|
|
237
|
+
async def ask(
|
|
238
|
+
self,
|
|
239
|
+
chat_id: Union[int, str],
|
|
240
|
+
text: str,
|
|
241
|
+
message_id: int,
|
|
242
|
+
*,
|
|
243
|
+
parse_mode: Optional[pyro_enums.ParseMode] = None,
|
|
244
|
+
entities: Optional[List[pyro_types.MessageEntity]] = None,
|
|
245
|
+
link_preview_options: Optional[pyro_types.LinkPreviewOptions] = None,
|
|
246
|
+
schedule_date: Optional[datetime] = None,
|
|
247
|
+
business_connection_id: Optional[str] = None,
|
|
248
|
+
reply_markup: Optional[pyro_types.InlineKeyboardMarkup] = None,
|
|
249
|
+
# listen params
|
|
250
|
+
listen_user_id: Optional[int] = None,
|
|
251
|
+
listen_message_id: Optional[int] = None,
|
|
252
|
+
meta: Optional[JsonValueT] = None,
|
|
253
|
+
timeout: Optional[Number] = None,
|
|
254
|
+
update_type: Type[UpdateType] = Message,
|
|
255
|
+
**kw
|
|
256
|
+
) -> UpdateType: ...
|
|
257
|
+
|
|
258
|
+
async def ask(
|
|
259
|
+
self,
|
|
260
|
+
chat_id: Union[int, str],
|
|
261
|
+
text: str,
|
|
262
|
+
message_id: Optional[int] = None,
|
|
263
|
+
*,
|
|
264
|
+
parse_mode: Optional[pyro_enums.ParseMode] = None,
|
|
265
|
+
entities: Optional[List[pyro_types.MessageEntity]] = None,
|
|
266
|
+
link_preview_options: Optional[pyro_types.LinkPreviewOptions] = None,
|
|
267
|
+
schedule_date: Optional[datetime] = None,
|
|
268
|
+
business_connection_id: Optional[str] = None,
|
|
269
|
+
reply_markup: Optional[Union[
|
|
270
|
+
pyro_types.InlineKeyboardMarkup,
|
|
271
|
+
pyro_types.ReplyKeyboardMarkup,
|
|
272
|
+
pyro_types.ReplyKeyboardRemove,
|
|
273
|
+
pyro_types.ForceReply,
|
|
274
|
+
]] = None,
|
|
275
|
+
# send_message only params
|
|
276
|
+
disable_notification: Optional[bool] = None,
|
|
277
|
+
message_thread_id: Optional[int] = None,
|
|
278
|
+
direct_messages_topic_id: Optional[int] = None,
|
|
279
|
+
effect_id: Optional[int] = None,
|
|
280
|
+
reply_parameters: Optional[pyro_types.ReplyParameters] = None,
|
|
281
|
+
repeat_period: Optional[int] = None,
|
|
282
|
+
protect_content: Optional[bool] = None,
|
|
283
|
+
allow_paid_broadcast: Optional[bool] = None,
|
|
284
|
+
paid_message_star_count: Optional[int] = None,
|
|
285
|
+
suggested_post_parameters: Optional[pyro_types.SuggestedPostParameters] = None,
|
|
286
|
+
# listen params
|
|
287
|
+
listen_user_id: Optional[int] = None,
|
|
288
|
+
listen_message_id: Optional[int] = None,
|
|
289
|
+
meta: Optional[JsonValueT] = None,
|
|
290
|
+
timeout: Optional[Number] = None,
|
|
291
|
+
update_type: Type[UpdateType] = Message,
|
|
292
|
+
**kw
|
|
293
|
+
) -> UpdateType:
|
|
294
|
+
"""
|
|
295
|
+
Send or edit a message, then wait for a matching update.
|
|
296
|
+
|
|
297
|
+
If ``message_id`` is provided, the existing message is edited via
|
|
298
|
+
:meth:`edit_message_text`. Otherwise a new message is sent via
|
|
299
|
+
:meth:`send_message`.
|
|
300
|
+
|
|
301
|
+
After sending or editing, the method waits for the next update of
|
|
302
|
+
``update_type`` matching the given ``chat_id``, ``listen_user_id``, and
|
|
303
|
+
``listen_message_id``.
|
|
304
|
+
|
|
305
|
+
Parameters:
|
|
306
|
+
chat_id: Target chat.
|
|
307
|
+
text: Message text.
|
|
308
|
+
message_id: If provided, edit this message instead
|
|
309
|
+
of sending a new one.
|
|
310
|
+
parse_mode: Text parse mode.
|
|
311
|
+
entities: Message entities.
|
|
312
|
+
link_preview_options: Link preview settings.
|
|
313
|
+
schedule_date: Schedule the message.
|
|
314
|
+
business_connection_id: Business connection id.
|
|
315
|
+
reply_markup: Keyboard markup.
|
|
316
|
+
disable_notification: Send silently (send only).
|
|
317
|
+
message_thread_id: Thread id (send only).
|
|
318
|
+
direct_messages_topic_id: DM topic id (send only).
|
|
319
|
+
effect_id: Message effect (send only).
|
|
320
|
+
reply_parameters: Reply parameters (send only).
|
|
321
|
+
repeat_period: Repeat period (send only).
|
|
322
|
+
protect_content: Protect content (send only).
|
|
323
|
+
allow_paid_broadcast: Allow paid broadcast (send only).
|
|
324
|
+
paid_message_star_count: Paid message star count (send only).
|
|
325
|
+
suggested_post_parameters: Suggested post parameters (send only).
|
|
326
|
+
|
|
327
|
+
listen_user_id: Filter the awaited update by user.
|
|
328
|
+
listen_message_id: Filter the awaited update by message.
|
|
329
|
+
meta: Metadata attached to the listener.
|
|
330
|
+
timeout: Seconds to wait before raising
|
|
331
|
+
:class:`ListenerTimeout`.
|
|
332
|
+
update_type: The update type to wait for.
|
|
333
|
+
Determines the return type.
|
|
334
|
+
**kw: Additional keyword arguments passed directly to
|
|
335
|
+
:meth:`send_message` or :meth:`edit_message_text`
|
|
336
|
+
depending on which operation is performed.
|
|
337
|
+
|
|
338
|
+
Returns:
|
|
339
|
+
The matching update of type ``update_type``.
|
|
340
|
+
|
|
341
|
+
Raises:
|
|
342
|
+
ListenerTimeout: If the timeout expires before the update arrives.
|
|
343
|
+
ListenerCancelled: If the listener is cancelled while waiting.
|
|
344
|
+
"""
|
|
345
|
+
|
|
346
|
+
listener = self.listeners.get(update_type)
|
|
347
|
+
|
|
348
|
+
if listener is None:
|
|
349
|
+
raise RuntimeError(
|
|
350
|
+
f"No listener registered for {update_type.__name__}. "
|
|
351
|
+
f"Register one via client.register_listener() before calling ask()."
|
|
352
|
+
)
|
|
353
|
+
|
|
354
|
+
|
|
355
|
+
if message_id is not None:
|
|
356
|
+
if reply_markup is not None and not isinstance(reply_markup, pyro_types.InlineKeyboardMarkup):
|
|
357
|
+
raise ValueError("Edit mode only supports InlineKeyboardMarkup for reply_markup")
|
|
358
|
+
|
|
359
|
+
m = await self.edit_message_text(
|
|
360
|
+
chat_id=chat_id,
|
|
361
|
+
message_id=message_id,
|
|
362
|
+
text=text,
|
|
363
|
+
parse_mode=parse_mode,
|
|
364
|
+
entities=entities,
|
|
365
|
+
link_preview_options=link_preview_options,
|
|
366
|
+
schedule_date=schedule_date,
|
|
367
|
+
business_connection_id=business_connection_id,
|
|
368
|
+
reply_markup=reply_markup,
|
|
369
|
+
**kw
|
|
370
|
+
)
|
|
371
|
+
else:
|
|
372
|
+
m = await self.send_message(
|
|
373
|
+
chat_id=chat_id,
|
|
374
|
+
text=text,
|
|
375
|
+
parse_mode=parse_mode,
|
|
376
|
+
entities=entities,
|
|
377
|
+
link_preview_options=link_preview_options,
|
|
378
|
+
disable_notification=disable_notification,
|
|
379
|
+
message_thread_id=message_thread_id,
|
|
380
|
+
direct_messages_topic_id=direct_messages_topic_id,
|
|
381
|
+
effect_id=effect_id,
|
|
382
|
+
reply_parameters=reply_parameters,
|
|
383
|
+
schedule_date=schedule_date,
|
|
384
|
+
repeat_period=repeat_period,
|
|
385
|
+
protect_content=protect_content,
|
|
386
|
+
business_connection_id=business_connection_id,
|
|
387
|
+
allow_paid_broadcast=allow_paid_broadcast,
|
|
388
|
+
paid_message_star_count=paid_message_star_count,
|
|
389
|
+
suggested_post_parameters=suggested_post_parameters,
|
|
390
|
+
reply_markup=reply_markup,
|
|
391
|
+
**kw,
|
|
392
|
+
)
|
|
393
|
+
|
|
394
|
+
|
|
395
|
+
if meta is None or isinstance(meta, dict):
|
|
396
|
+
meta = {} if meta is None else meta.copy()
|
|
397
|
+
if "message_id" not in meta and m:
|
|
398
|
+
meta["message_id"] = m.id
|
|
399
|
+
|
|
400
|
+
final_chat_id = m.chat.id if (m and m.chat) else chat_id
|
|
401
|
+
|
|
402
|
+
if isinstance(final_chat_id, str):
|
|
403
|
+
final_chat_id = pyro_ut.get_peer_id(
|
|
404
|
+
await self.resolve_peer(final_chat_id)
|
|
405
|
+
)
|
|
406
|
+
|
|
407
|
+
return await listener(
|
|
408
|
+
chat_id=final_chat_id,
|
|
409
|
+
user_id=listen_user_id,
|
|
410
|
+
message_id=listen_message_id,
|
|
411
|
+
meta=meta,
|
|
412
|
+
timeout=timeout,
|
|
413
|
+
)
|