Skip to content

Commit 2ff823d

Browse files
author
Pietro Albini
committed
Add support for processing edited messages
In the recent updates, the Telegram API added support for processing the edits users make to messages your bot knows about. This commit adds support for that, in the `@bot.message_edited` decorator and the `component.add_message_edited_hook()` method. Fixes: GH-63
1 parent fcfa6af commit 2ff823d

File tree

9 files changed

+106
-1
lines changed

9 files changed

+106
-1
lines changed

botogram/bot.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ def __init__(self, api_connection):
6767
# Initialize the list of update processors
6868
self._update_processors = {}
6969
self.register_update_processor("message", messages.process_message)
70+
self.register_update_processor("edited_message",
71+
messages.process_edited_message)
7072

7173
self._bot_id = str(uuid.uuid4())
7274

@@ -135,6 +137,11 @@ def __(func):
135137
return func
136138
return __
137139

140+
def message_edited(self, func):
141+
"""Add a message edited hook"""
142+
self._main_component.add_message_edited_hook(func)
143+
return func
144+
138145
def command(self, name, hidden=False):
139146
"""Register a new command"""
140147
def __(func):

botogram/components.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ def __new__(cls, *args, **kwargs):
3131
self.__memory_preparers = []
3232
self.__timers = []
3333
self.__chat_unavailable_hooks = []
34+
self.__messages_edited_hooks = []
3435

3536
self._component_id = str(uuid.uuid4())
3637

@@ -148,6 +149,14 @@ def add_chat_unavailable_hook(self, func):
148149
hook = hooks.ChatUnavailableHook(func, self)
149150
self.__chat_unavailable_hooks.append(hook)
150151

152+
def add_message_edited_hook(self, func):
153+
"""Add a new edited message hook"""
154+
if not callable(func):
155+
raise ValueError("A message edited hook must be callable")
156+
157+
hook = hooks.MessageEditedHook(func, self)
158+
self.__messages_edited_hooks.append(hook)
159+
151160
def _add_no_commands_hook(self, func):
152161
"""Register an hook which will be executed when no commands matches"""
153162
if not callable(func):
@@ -170,6 +179,7 @@ def _get_chains(self):
170179
"memory_preparers": [self.__memory_preparers],
171180
"tasks": [self.__timers],
172181
"chat_unavalable_hooks": [self.__chat_unavailable_hooks],
182+
"messages_edited": [self.__messages_edited_hooks],
173183
}
174184

175185
def _get_commands(self):

botogram/hooks.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,15 @@ def call(self, bot, chat_id, reason):
200200
reason=reason)
201201

202202

203+
class MessageEditedHook(Hook):
204+
"""Underlying hook for @bot.message_edited"""
205+
206+
def _call(self, bot, update):
207+
message = update.edited_message
208+
return bot._call(self.func, self.component_id, chat=message.chat,
209+
message=message)
210+
211+
203212
class TimerHook(Hook):
204213
"""Underlying hook for a timer"""
205214

botogram/messages.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,19 @@ def process_message(bot, chains, update):
2121

2222
bot.logger.debug("No hook actually processed the #%s update." %
2323
update.update_id)
24+
25+
26+
def process_edited_message(bot, chains, update):
27+
"""Process an edited message"""
28+
for hook in chains["messages_edited"]:
29+
bot.logger.debug("Processing edited message in update #%s with the "
30+
"hook %s..." % (update.update_id, hook.name))
31+
32+
result = hook.call(bot, update)
33+
if result is True:
34+
bot.logger.debug("Update %s was just processed by the %s hook." %
35+
(update.update_id, hook.name))
36+
return
37+
38+
bot.logger.debug("No hook actually processed the #%s update." %
39+
update.update_id)

botogram/objects/messages.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,7 @@ def from_(self):
319319
"migrate_to_chat_id": int,
320320
"migrate_from_chat_id": int,
321321
"pinned_message": _itself,
322+
"edit_date": int,
322323
}
323324
replace_keys = {
324325
"from": "sender",

botogram/objects/updates.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ class Update(BaseObject):
2121
"update_id": int,
2222
}
2323
optional = {
24-
"message": Message
24+
"message": Message,
25+
"edited_message": Message,
2526
}
2627
_check_equality_ = "update_id"
2728

docs/api/bot.rst

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,31 @@ components.
163163
:param bool multiple: If the function should be called multiple times on
164164
multiple matches.
165165

166+
.. py:decoratormethod:: message_edited
167+
168+
All the functions decorated with this method will be called when an user
169+
edits a message the bot knows about. This allows you, for example, to
170+
update the preview of a message if the user edits the request, or to
171+
enforce a no-edits policy on groups by banning whoever edits a message.
172+
173+
You can :ref:`request the following arguments <bot-structure-hooks-args>`
174+
in the decorated functions:
175+
176+
* **chat**: the chat in which the message was originally sent (instance
177+
of :py:class:`~botogram.Chat`)
178+
179+
* **message**: the edited message (instance of
180+
:py:class:`~botogram.Message`)
181+
182+
.. code-block:: python
183+
184+
@bot.message_edited
185+
def no_edits(chat, message):
186+
message.reply("You can't edit messages! Bye.")
187+
chat.ban(message.sender)
188+
189+
.. versionadded:: 0.3
190+
166191
.. py:decoratormethod:: command(name, [hidden=False])
167192
168193
This decorator register a new command, and calls the decorated function

docs/api/components.rst

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,37 @@ about how to create them in the ":ref:`custom-components`" chapter.
127127
:param bool multiple: If the function should be called multiple times on
128128
multiple matches.
129129

130+
.. py:method:: add_message_edited_hook(func)
131+
132+
All the functions provided to this method will be called when an user
133+
edits a message the bot knows about. This allows you, for example, to
134+
update the preview of a message if the user edits the request, or to
135+
enforce a no-edits policy on groups by banning whoever edits a message.
136+
137+
You can :ref:`request the following arguments <bot-structure-hooks-args>`
138+
in the provided functions:
139+
140+
* **chat**: the chat in which the message was orignally sent (instance of
141+
:py:class:`~botogram.Chat`)
142+
* **message**: the edited message (instance of
143+
:py:class:`~botogram.Message`)
144+
145+
.. code-block:: python
146+
147+
class NoEditsComponent(botogram.Component):
148+
component_name = "noedits"
149+
150+
def __init__(self):
151+
self.add_message_edited_hook(self.no_edits)
152+
153+
def no_edits(self, chat, message):
154+
message.reply("You can't edit messages! Bye.")
155+
chat.ban(message.sender)
156+
157+
:param callable func: The function you want to use.
158+
159+
.. versionadded:: 0.3
160+
130161
.. py:method:: add_command(name, func, [hidden=False])
131162
132163
This function registers a new command, and calls the provided function

docs/changelog.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,11 @@ New features
4545
* New argument ``hidden`` on :py:meth:`botogram.Bot.command`
4646
* New argument ``hidden`` on :py:meth:`botogram.Component.add_command`
4747

48+
* Add support for processing edited messages:
49+
50+
* New decorator :py:meth:`botogram.Bot.message_edited`
51+
* New method :py:meth:`botogram.Component.add_message_edited_hook`
52+
4853
* Added new attribute :py:attr:`botogram.Message.pinned_message`
4954
* Added new attribute :py:attr:`botogram.Sticker.emoji`
5055
* Added new attribute :py:attr:`botogram.Chat.admins`

0 commit comments

Comments
 (0)