Command decorator defined
This commit is contained in:
parent
8ee798af5e
commit
cff3c30481
@ -1201,6 +1201,257 @@ class Bot(TelegramBot, ObjectWithDatabase):
|
||||
"""
|
||||
self._unknown_command_message = unknown_command_message
|
||||
|
||||
def command(self, command, aliases=None, show_in_keyboard=False,
|
||||
description="", authorization_level='admin'):
|
||||
"""Associate a bot command with a custom handler function.
|
||||
|
||||
Decorate command handlers like this:
|
||||
```
|
||||
@bot.command('/mycommand', ['Button'], True, "My command", 'user')
|
||||
async def command_handler(bot, update, user_record):
|
||||
return "Result"
|
||||
```
|
||||
When a message text starts with `/command[@bot_name]`, or with an
|
||||
alias, it gets passed to the decorated function.
|
||||
`command` is the command name (with or without /).
|
||||
`aliases` is a list of aliases; each will call the command handler
|
||||
function; the first alias will appear as button in
|
||||
default_keyboard.
|
||||
`show_in_keyboard`, if True, makes first alias appear in
|
||||
default_keyboard.
|
||||
`description` can be used to help users understand what `/command`
|
||||
does.
|
||||
`authorization_level` is the lowest authorization level needed to run
|
||||
the command.
|
||||
"""
|
||||
if not isinstance(command, str):
|
||||
raise TypeError(f'Command `{command}` is not a string')
|
||||
if aliases:
|
||||
if not isinstance(aliases, list):
|
||||
raise TypeError(f'Aliases is not a list: `{aliases}`')
|
||||
if not all(
|
||||
[
|
||||
isinstance(alias, str)
|
||||
for alias in aliases
|
||||
]
|
||||
):
|
||||
raise TypeError(
|
||||
f'Aliases {aliases} is not a list of strings string'
|
||||
)
|
||||
command = command.strip('/ ').lower()
|
||||
|
||||
def command_decorator(command_handler):
|
||||
async def decorated_command_handler(bot, update, user_record):
|
||||
logging.info(
|
||||
f"Command `{command}@{bot.name}` called by "
|
||||
"`{from_}`".format(
|
||||
from_=(
|
||||
update['from']
|
||||
if 'from' in update
|
||||
else update['chat']
|
||||
)
|
||||
)
|
||||
)
|
||||
if bot.authorization_function(
|
||||
update=update,
|
||||
user_record=user_record,
|
||||
authorization_level=authorization_level
|
||||
):
|
||||
return await command_handler(bot=bot, update=update,
|
||||
user_record=user_record)
|
||||
return self.unauthorized_message
|
||||
self.commands[command] = dict(
|
||||
handler=decorated_command_handler,
|
||||
description=description,
|
||||
authorization_level=authorization_level
|
||||
)
|
||||
if aliases:
|
||||
for alias in aliases:
|
||||
self.command_aliases[alias] = decorated_command_handler
|
||||
if show_in_keyboard:
|
||||
self.default_reply_keyboard_elements.append(aliases[0])
|
||||
return command_decorator
|
||||
|
||||
def parser(self, condition, description='', authorization_level='admin',
|
||||
argument='text'):
|
||||
"""Define a text message parser.
|
||||
|
||||
Decorate command handlers like this:
|
||||
```
|
||||
def custom_criteria(update):
|
||||
return 'from' in update
|
||||
|
||||
@bot.parser(custom_criteria, authorization_level='user')
|
||||
async def text_parser(bot, update, user_record):
|
||||
return "Result"
|
||||
```
|
||||
If condition evaluates True when run on a message text
|
||||
(not starting with '/'), such decorated function gets
|
||||
called on update.
|
||||
Conditions of parsers are evaluated in order; when one is True,
|
||||
others will be skipped.
|
||||
`description` provides information about the parser.
|
||||
`authorization_level` is the lowest authorization level needed to call
|
||||
the parser.
|
||||
"""
|
||||
if not callable(condition):
|
||||
raise TypeError(
|
||||
f'Condition {condition.__name__} is not a callable'
|
||||
)
|
||||
|
||||
def parser_decorator(parser):
|
||||
async def decorated_parser(bot, message, user_record):
|
||||
logging.info(
|
||||
f"Text message update matching condition "
|
||||
f"`{condition.__name__}@{bot.name}` from "
|
||||
"`{user}`".format(
|
||||
user=(
|
||||
message['from']
|
||||
if 'from' in message
|
||||
else message['chat']
|
||||
)
|
||||
)
|
||||
)
|
||||
if bot.authorization_function(
|
||||
update=message,
|
||||
user_record=user_record,
|
||||
authorization_level=authorization_level
|
||||
):
|
||||
return await parser(bot, message, user_record)
|
||||
return bot.unauthorized_message
|
||||
self.text_message_parsers[condition] = dict(
|
||||
handler=decorated_parser,
|
||||
description=description,
|
||||
authorization_level=authorization_level,
|
||||
argument=argument
|
||||
)
|
||||
return parser_decorator
|
||||
|
||||
def set_command(self, command, handler, aliases=None,
|
||||
show_in_keyboard=False, description="",
|
||||
authorization_level='admin'):
|
||||
"""Associate a `command` with a `handler`.
|
||||
|
||||
When a message text starts with `/command[@bot_name]`, or with an
|
||||
alias, it gets passed to the decorated function.
|
||||
`command` is the command name (with or without /)
|
||||
`handler` is the function to be called on update objects.
|
||||
`aliases` is a list of aliases; each will call the command handler
|
||||
function; the first alias will appear as button in
|
||||
default_keyboard.
|
||||
`show_in_keyboard`, if True, makes first alias appear in
|
||||
default_keyboard.
|
||||
`description` is a description and can be used to help users understand
|
||||
what `/command` does.
|
||||
`authorization_level` is the lowest authorization level needed to run
|
||||
the command.
|
||||
"""
|
||||
if not callable(handler):
|
||||
raise TypeError(f'Handler `{handler}` is not callable.')
|
||||
return self.command(
|
||||
command=command, aliases=aliases,
|
||||
show_in_keyboard=show_in_keyboard, description=description,
|
||||
authorization_level=authorization_level
|
||||
)(handler)
|
||||
|
||||
def button(self, data, description='', authorization_level='admin'):
|
||||
"""Associate a bot button prefix (`data`) with a handler.
|
||||
|
||||
When a callback data text starts with <data>, 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):
|
||||
return "Result"
|
||||
```
|
||||
`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):
|
||||
raise TypeError(
|
||||
f'Inline button callback_data {data} is not a string'
|
||||
)
|
||||
|
||||
def button_decorator(handler):
|
||||
async def decorated_button_handler(bot, update, user_record):
|
||||
logging.info(
|
||||
f"Button `{update['data']}`@{bot.name} pressed by "
|
||||
f"`{update['from']}`"
|
||||
)
|
||||
if bot.authorization_function(
|
||||
update=update,
|
||||
user_record=user_record,
|
||||
authorization_level=authorization_level
|
||||
):
|
||||
return await handler(bot, update, user_record)
|
||||
return bot.unauthorized_message
|
||||
self.callback_handlers[data] = dict(
|
||||
handler=decorated_button_handler,
|
||||
description=description,
|
||||
authorization_level=authorization_level
|
||||
)
|
||||
return button_decorator
|
||||
|
||||
def query(self, condition, description='', authorization_level='admin'):
|
||||
"""Define an inline query.
|
||||
|
||||
Decorator: `@bot.query(example)`
|
||||
When an inline query matches the `condition` function,
|
||||
decorated function is called and passed the query update object
|
||||
as argument.
|
||||
`description` is a description
|
||||
`authorization_level` is the lowest authorization level needed to run
|
||||
the command
|
||||
"""
|
||||
if not callable(condition):
|
||||
raise TypeError(
|
||||
'Condition {c} is not a callable'.format(
|
||||
c=condition.__name__
|
||||
)
|
||||
)
|
||||
|
||||
def decorator(func):
|
||||
if asyncio.iscoroutinefunction(func):
|
||||
async def decorated(message, user_record, bot):
|
||||
logging.info(
|
||||
"QUERY MATCHING CONDITION({c}) @{n} FROM({f})".format(
|
||||
c=condition.__name__,
|
||||
n=self.name,
|
||||
f=message['from']
|
||||
)
|
||||
)
|
||||
if self.authorization_function(
|
||||
update=message,
|
||||
user_record=user_record,
|
||||
authorization_level=authorization_level
|
||||
):
|
||||
return await func(message)
|
||||
return self.unauthorized_message
|
||||
else:
|
||||
def decorated(message, user_record, bot):
|
||||
logging.info(
|
||||
"QUERY MATCHING CONDITION({c}) @{n} FROM({f})".format(
|
||||
c=condition.__name__,
|
||||
n=self.name,
|
||||
f=message['from']
|
||||
)
|
||||
)
|
||||
if self.authorization_function(
|
||||
update=message,
|
||||
user_record=user_record,
|
||||
authorization_level=authorization_level
|
||||
):
|
||||
return func(message)
|
||||
return self.unauthorized_message
|
||||
self.inline_query_handlers[condition] = dict(
|
||||
function=decorated,
|
||||
description=description,
|
||||
authorization_level=authorization_level
|
||||
)
|
||||
return decorator
|
||||
|
||||
def set_chat_id_getter(self, getter):
|
||||
"""Set chat_id getter.
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user