|
@@ -42,7 +42,7 @@ from aiohttp import web
|
|
|
from davtelepot.api import TelegramBot, TelegramError
|
|
|
from davtelepot.database import ObjectWithDatabase
|
|
|
from davtelepot.utilities import (
|
|
|
- escape_html_chars, get_secure_key, make_inline_query_answer,
|
|
|
+ escape_html_chars, extract, get_secure_key, make_inline_query_answer,
|
|
|
make_lines_of_buttons, remove_html_tags
|
|
|
)
|
|
|
|
|
@@ -168,6 +168,7 @@ class Bot(TelegramBot, ObjectWithDatabase):
|
|
|
self.text_message_parsers = OrderedDict()
|
|
|
# Callback query-related properties
|
|
|
self.callback_handlers = OrderedDict()
|
|
|
+ self._callback_data_separator = None
|
|
|
# Inline query-related properties
|
|
|
self.inline_query_handlers = OrderedDict()
|
|
|
self._default_inline_query_answer = None
|
|
@@ -348,6 +349,25 @@ class Bot(TelegramBot, ObjectWithDatabase):
|
|
|
return self._unknown_command_message
|
|
|
return self.__class__._unknown_command_message
|
|
|
|
|
|
+ @property
|
|
|
+ def callback_data_separator(self):
|
|
|
+ """Separator between callback data elements.
|
|
|
+
|
|
|
+ Example of callback_data: 'my_button_prefix:///1|4|test'
|
|
|
+ Prefix: `my_button_prefix:///`
|
|
|
+ Separator: `|` <--- this is returned
|
|
|
+ Data: `['1', '4', 'test']`
|
|
|
+ """
|
|
|
+ return self._callback_data_separator
|
|
|
+
|
|
|
+ def set_callback_data_separator(self, separator):
|
|
|
+ """Set a callback_data separator.
|
|
|
+
|
|
|
+ See property `callback_data_separator` for details.
|
|
|
+ """
|
|
|
+ assert type(separator) is str, "Separator must be a string!"
|
|
|
+ self._callback_data_separator = separator
|
|
|
+
|
|
|
@property
|
|
|
def default_inline_query_answer(self):
|
|
|
"""Answer to be returned if inline query returned None.
|
|
@@ -1387,24 +1407,28 @@ class Bot(TelegramBot, ObjectWithDatabase):
|
|
|
authorization_level=authorization_level
|
|
|
)(handler)
|
|
|
|
|
|
- def button(self, data, description='', authorization_level='admin'):
|
|
|
- """Associate a bot button prefix (`data`) with a handler.
|
|
|
+ def button(self, prefix, separator=None, description='',
|
|
|
+ authorization_level='admin'):
|
|
|
+ """Associate a bot button `prefix` with a handler.
|
|
|
|
|
|
- When a callback data text starts with <data>, the associated handler is
|
|
|
- called upon the update.
|
|
|
+ When a callback data text starts with `prefix`, the associated handler
|
|
|
+ is called upon the update.
|
|
|
Decorate button handlers like this:
|
|
|
```
|
|
|
- @bot.button('a_prefix:///', "A button", 'user')
|
|
|
- async def button_handler(bot, update, user_record):
|
|
|
+ @bot.button('a_prefix:///', description="A button",
|
|
|
+ authorization_level='user')
|
|
|
+ async def button_handler(bot, update, user_record, data):
|
|
|
return "Result"
|
|
|
```
|
|
|
+ `separator` will be used to parse callback data received when a button
|
|
|
+ starting with `prefix` will be pressed.
|
|
|
`description` contains information about the button.
|
|
|
`authorization_level` is the lowest authorization level needed to
|
|
|
be allowed to push the button.
|
|
|
"""
|
|
|
- if not isinstance(data, str):
|
|
|
+ if not isinstance(prefix, str):
|
|
|
raise TypeError(
|
|
|
- f'Inline button callback_data {data} is not a string'
|
|
|
+ f'Inline button callback_data {prefix} is not a string'
|
|
|
)
|
|
|
|
|
|
def button_decorator(handler):
|
|
@@ -1419,8 +1443,20 @@ class Bot(TelegramBot, ObjectWithDatabase):
|
|
|
authorization_level=authorization_level
|
|
|
):
|
|
|
return await handler(bot, update, user_record)
|
|
|
+ # Remove `prefix` from `ðata`
|
|
|
+ data = extract(update['data'], prefix)
|
|
|
+ # If a specific separator or default separator is set,
|
|
|
+ # use it to split `data` string in a list.
|
|
|
+ # Cast numeric `data` elements to `int`.
|
|
|
+ _separator = separator or self.callback_data_separator
|
|
|
+ if _separator:
|
|
|
+ data = [
|
|
|
+ int(element) if element.isnumeric()
|
|
|
+ else element
|
|
|
+ for element in data.split(_separator)
|
|
|
+ ]
|
|
|
return bot.unauthorized_message
|
|
|
- self.callback_handlers[data] = dict(
|
|
|
+ self.callback_handlers[prefix] = dict(
|
|
|
handler=decorated_button_handler,
|
|
|
description=description,
|
|
|
authorization_level=authorization_level
|