Skip to content

Commit fcfa6af

Browse files
author
Pietro Albini
committed
Refactored the updates routing
Routing for updates (updates containing messages are processed by a specific hook, updates with callbacks by another...) is now fully customizable. This allows for more modularity, as well to add processing logic for more updates kinds easily.
1 parent 173a7e8 commit fcfa6af

File tree

3 files changed

+51
-19
lines changed

3 files changed

+51
-19
lines changed

botogram/bot.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
from . import frozenbot
2222
from . import shared
2323
from . import tasks
24+
from . import messages
2425

2526

2627
class Bot(frozenbot.FrozenBot):
@@ -63,6 +64,10 @@ def __init__(self, api_connection):
6364
# Setup the scheduler
6465
self._scheduler = tasks.Scheduler()
6566

67+
# Initialize the list of update processors
68+
self._update_processors = {}
69+
self.register_update_processor("message", messages.process_message)
70+
6671
self._bot_id = str(uuid.uuid4())
6772

6873
self.use(defaults.DefaultComponent())
@@ -191,6 +196,14 @@ def run(self, workers=2):
191196
inst = runner.BotogramRunner(self, workers=workers)
192197
inst.run()
193198

199+
def register_update_processor(self, kind, processor):
200+
"""Register a new update processor"""
201+
if kind in self._update_processors:
202+
raise NameError("An update processor for \"%s\" updates is "
203+
"already registered" % kind)
204+
205+
self._update_processors[kind] = processor
206+
194207
def freeze(self):
195208
"""Return a frozen instance of the bot"""
196209
chains = components.merge_chains(self._main_component,
@@ -202,7 +215,8 @@ def freeze(self):
202215
self.lang, self.itself, self._commands_re,
203216
self._commands, chains, self._scheduler,
204217
self._main_component._component_id,
205-
self._bot_id, self._shared_memory)
218+
self._bot_id, self._shared_memory,
219+
self._update_processors)
206220

207221
@property
208222
def lang(self):

botogram/frozenbot.py

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ class FrozenBot:
2323
def __init__(self, api, about, owner, hide_commands, before_help,
2424
after_help, process_backlog, lang, itself, commands_re,
2525
commands, chains, scheduler, main_component_id, bot_id,
26-
shared_memory):
26+
shared_memory, update_processors):
2727
# This attribute should be added with the default setattr, because is
2828
# needed by the custom setattr
2929
object.__setattr__(self, "_frozen", False)
@@ -43,6 +43,7 @@ def __init__(self, api, about, owner, hide_commands, before_help,
4343
self._shared_memory = shared_memory
4444
self._scheduler = scheduler
4545
self._chains = chains
46+
self._update_processors = update_processors
4647
self._commands = {name: command.for_bot(self)
4748
for name, command in commands.items()}
4849

@@ -65,7 +66,7 @@ def __reduce__(self):
6566
self.before_help, self.after_help, self.process_backlog,
6667
self.lang, self.itself, self._commands_re, self._commands,
6768
self._chains, self._scheduler, self._main_component_id,
68-
self._bot_id, self._shared_memory,
69+
self._bot_id, self._shared_memory, self._update_processors,
6970
)
7071
return restore, args
7172

@@ -171,21 +172,13 @@ def process(self, update):
171172
update.set_api(self.api) # Be sure to use the correct API object
172173

173174
try:
174-
for hook in self._chains["messages"]:
175-
# Get the correct name of the hook
176-
name = hook.name
177-
self.logger.debug("Processing update #%s with the %s hook..." %
178-
(update.update_id, name))
179-
180-
result = hook.call(self, update)
181-
if result is True:
182-
self.logger.debug("Update #%s was just processed by the "
183-
"%s hook." % (update.update_id, name))
184-
return True
185-
186-
self.logger.debug("No hook actually processed the #%s update." %
187-
update.update_id)
175+
for kind, processor in self._update_processors.items():
176+
# Call the processor of the right kind
177+
if getattr(update, kind) is None:
178+
continue
188179

180+
processor(self, self._chains, update)
181+
break
189182
except api_module.ChatUnavailableError as e:
190183
# Do some sane logging
191184
self.logger.warning("Chat %s is not available to your bot:" %
@@ -199,8 +192,6 @@ def process(self, update):
199192
e.chat_id))
200193
hook.call(self, e.chat_id, e.reason)
201194

202-
return False
203-
204195
def scheduled_tasks(self, current_time=None, wrap=True):
205196
"""Return a list of tasks scheduled for now"""
206197
# This provides a better API for the users of the method
@@ -215,6 +206,10 @@ def process():
215206
return [wrapper(job) for job in tasks]
216207
return list(tasks)
217208

209+
def register_update_processor(self, kind, processor):
210+
"""Register a new update processor"""
211+
raise FrozenBotError("Can't register new update processors at runtime")
212+
218213
# This helper manages the translation
219214

220215
def _(self, message, **args):

botogram/messages.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
"""
2+
botogram.messages
3+
Logic for processing messages sent to your bot
4+
5+
Copyright (c) 2016 Pietro Albini <[email protected]>
6+
Released under the MIT license
7+
"""
8+
9+
10+
def process_message(bot, chains, update):
11+
"""Process a message sent to the bot"""
12+
for hook in chains["messages"]:
13+
bot.logger.debug("Processing update #%s with the hook %s..." %
14+
(update.update_id, hook.name))
15+
16+
result = hook.call(bot, update)
17+
if result is True:
18+
bot.logger.debug("Update #%s was just processed by the %s hook." %
19+
(update.update_id, hook.name))
20+
return
21+
22+
bot.logger.debug("No hook actually processed the #%s update." %
23+
update.update_id)

0 commit comments

Comments
 (0)