Skip to content

Commit fad031b

Browse files
committed
feat(messages): asynchronous context manager for chat actions
1 parent e2df10f commit fad031b

2 files changed

Lines changed: 138 additions & 0 deletions

File tree

hydrogram/methods/messages/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@
6565
from .stop_poll import StopPoll
6666
from .stream_media import StreamMedia
6767
from .vote_poll import VotePoll
68+
from .action import Action
6869

6970

7071
class Messages(
@@ -116,5 +117,6 @@ class Messages(
116117
GetDiscussionRepliesCount,
117118
StreamMedia,
118119
GetCustomEmojiStickers,
120+
Action,
119121
):
120122
pass
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
# Hydrogram - Telegram MTProto API Client Library for Python
2+
# Copyright (C) 2017-2023 Dan <https://github.com/delivrance>
3+
# Copyright (C) 2023-present Hydrogram <https://hydrogram.org>
4+
#
5+
# This file is part of Hydrogram.
6+
#
7+
# Hydrogram is free software: you can redistribute it and/or modify
8+
# it under the terms of the GNU Lesser General Public License as published
9+
# by the Free Software Foundation, either version 3 of the License, or
10+
# (at your option) any later version.
11+
#
12+
# Hydrogram is distributed in the hope that it will be useful,
13+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
# GNU Lesser General Public License for more details.
16+
#
17+
# You should have received a copy of the GNU Lesser General Public License
18+
# along with Hydrogram. If not, see <http://www.gnu.org/licenses/>.
19+
20+
from __future__ import annotations
21+
22+
import asyncio
23+
from typing import TYPE_CHECKING
24+
25+
import hydrogram
26+
from hydrogram import enums
27+
28+
if TYPE_CHECKING:
29+
from types import TracebackType
30+
31+
32+
class ActionContext:
33+
def __init__(
34+
self,
35+
client: hydrogram.Client,
36+
chat_id: int | str,
37+
action: enums.ChatAction,
38+
delay: float = 4.0,
39+
message_thread_id: int | None = None
40+
):
41+
self._client = client
42+
self._chat_id = chat_id
43+
self._action = action
44+
self._delay = delay
45+
self._message_thread_id = message_thread_id
46+
self._task: asyncio.Task | None = None
47+
48+
async def _keep_typing(self) -> None:
49+
try:
50+
while True:
51+
await self._client.send_chat_action(
52+
chat_id=self._chat_id,
53+
action=self._action,
54+
message_thread_id=self._message_thread_id
55+
)
56+
await asyncio.sleep(self._delay)
57+
except asyncio.CancelledError:
58+
pass
59+
60+
async def __aenter__(self) -> ActionContext:
61+
self._task = asyncio.create_task(self._keep_typing())
62+
return self
63+
64+
async def __aexit__(
65+
self,
66+
exc_type: type[BaseException] | None,
67+
exc_val: BaseException | None,
68+
exc_tb: TracebackType | None
69+
) -> None:
70+
if self._task:
71+
self._task.cancel()
72+
try:
73+
await self._task
74+
except asyncio.CancelledError:
75+
pass
76+
self._task = None
77+
78+
await self._client.send_chat_action(
79+
chat_id=self._chat_id,
80+
action=enums.ChatAction.CANCEL,
81+
message_thread_id=self._message_thread_id
82+
)
83+
84+
85+
class Action:
86+
def action(
87+
self: hydrogram.Client,
88+
chat_id: int | str,
89+
action: enums.ChatAction,
90+
delay: float = 4.0,
91+
message_thread_id: int | None = None
92+
) -> ActionContext:
93+
"""Return a context manager to keep a chat action active continuously.
94+
95+
.. include:: /_includes/usable-by/users-bots.rst
96+
97+
Parameters:
98+
chat_id (``int`` | ``str``):
99+
Unique identifier (int) or username (str) of the target chat.
100+
For your personal cloud (Saved Messages) you can simply use "me" or "self".
101+
For a contact that exists in your Telegram address book you can use his phone number (str).
102+
103+
action (:obj:`~hydrogram.enums.ChatAction`):
104+
Type of action to broadcast continuously.
105+
106+
delay (``float``, *optional*):
107+
Time in seconds to wait before sending the next action update.
108+
Defaults to 4.0.
109+
110+
message_thread_id (``int``, *optional*):
111+
Unique identifier for the target message thread (topic) of the forum.
112+
For forum supergroups only.
113+
114+
Returns:
115+
:obj:`ActionContext`: An asynchronous context manager.
116+
117+
Example:
118+
.. code-block:: python
119+
120+
import asyncio
121+
from hydrogram import enums
122+
123+
async with app.action(chat_id, enums.ChatAction.TYPING):
124+
await asyncio.sleep(10)
125+
await app.send_message(chat_id, "I type really slow!")
126+
127+
async with app.action(chat_id, enums.ChatAction.UPLOAD_DOCUMENT):
128+
await generate_and_upload_large_file()
129+
"""
130+
return ActionContext(
131+
client=self,
132+
chat_id=chat_id,
133+
action=action,
134+
delay=delay,
135+
message_thread_id=message_thread_id
136+
)

0 commit comments

Comments
 (0)