Redesigned message handlers

This commit is contained in:
Pieter van den Ham 2015-09-08 10:44:31 +02:00
parent 4526c4f8a7
commit f9cbcf9b65
2 changed files with 42 additions and 17 deletions

View File

@ -130,7 +130,25 @@ All [API methods](https://core.telegram.org/bots/api#available-methods) are loca
Outlined below are some general use cases of the API.
#### Message handlers
A message handler is a function which is decorated with the `message_handler` decorator of a TeleBot instance. The following examples illustrate the possibilities of message handlers:
A message handler is a function that is decorated with the `message_handler` decorator of a TeleBot instance. The following examples illustrate the possibilities of message handlers. Message handlers consists of one or multiple filters.
A message handler is declared in the following way (provided `bot` is an instance of TeleBot):
```python
@bot.message_handler(filters)
def function_name(message):
bot.reply_to(message, "This is a message handler")
```
`function_name` is not bound to any restrictions. Any function name is permitted with message handlers. The function must accept at most one argument, which will be the message that the function must handle.
`filters` is a list of keyword arguments. Each filter must return True for a certain message in order for the message handler to become eligible to handle that message.
TeleBot supports the following filters:
|name|argument(s)|Condition|
|:---:|---| ---|
|content_types|list of strings (default `['text']`)|`True` if message.content_type is in the list of strings.|
|regexp|a regular expression as a string|`True` if `re.search(regexp_arg)` returns `True` and `message.content_type == 'text'`|
|commands|list of strings|`True` if `message.content_type == 'text'` and `message.text` starts with a command that is in the list of strings.|
|func|a function (lambda or function reference)|True if the function or lambda reference returns True
A filter is declared in the following manner: `name=argument`.
Here are some examples of using the filters and message handlers:
```python
import telebot
bot = telebot.TeleBot("TOKEN")
@ -163,7 +181,7 @@ def test_message(message):
def handle_text_doc(message)
pass
```
*Note: all handlers are tested in the order in which they were declared*
**Important: all handlers are tested in the order in which they were declared**
#### TeleBot
```python
import telebot

View File

@ -371,31 +371,38 @@ class TeleBot:
:param func: Optional lambda function. The lambda receives the message to test as the first parameter. It must return True if the command should handle the message.
:param content_types: This commands' supported content types. Must be a list. Defaults to ['text'].
"""
def decorator(fn):
func_dict = {'function': fn, 'content_types': content_types}
handler_dict = {'function': fn}
filters = {'content_types': content_types}
if regexp:
func_dict['regexp'] = regexp if 'text' in content_types else None
filters['regexp'] = regexp
if func:
func_dict['lambda'] = func
filters['lambda'] = func
if commands:
func_dict['commands'] = commands if 'text' in content_types else None
self.message_handlers.append(func_dict)
filters['commands'] = commands
handler_dict['filters'] = filters
self.message_handlers.append(handler_dict)
return fn
return decorator
@staticmethod
def _test_message_handler(message_handler, message):
if message.content_type not in message_handler['content_types']:
return False
if 'commands' in message_handler and message.content_type == 'text':
return util.extract_command(message.text) in message_handler['commands']
if 'regexp' in message_handler and message.content_type == 'text' and re.search(message_handler['regexp'],
message.text):
return True
if 'lambda' in message_handler:
return message_handler['lambda'](message)
for filter, filter_value in message_handler['filters'].iteritems():
if not TeleBot._test_filter(filter, filter_value, message):
return False
return True
@staticmethod
def _test_filter(filter, filter_value, message):
if filter == 'content_types':
return message.content_type in filter_value
if filter == 'regexp':
return message.content_type == 'text' and re.search(filter_value, message.text)
if filter == 'commands':
return message.content_type == 'text' and util.extract_command(message.text) in filter_value
if filter == 'func':
return filter_value(message)
return False
def _notify_command_handlers(self, new_messages):