Allow language-labelled commands

This commit is contained in:
Davte 2020-05-14 15:32:06 +02:00
parent f840f9fe13
commit e6fdacd2f4
4 changed files with 66 additions and 32 deletions

View File

@ -11,7 +11,7 @@ __author__ = "Davide Testa"
__email__ = "davide@davte.it" __email__ = "davide@davte.it"
__credits__ = ["Marco Origlia", "Nick Lee @Nickoala"] __credits__ = ["Marco Origlia", "Nick Lee @Nickoala"]
__license__ = "GNU General Public License v3.0" __license__ = "GNU General Public License v3.0"
__version__ = "2.5.11" __version__ = "2.5.12"
__maintainer__ = "Davide Testa" __maintainer__ = "Davide Testa"
__contact__ = "t.me/davte" __contact__ = "t.me/davte"

View File

@ -43,7 +43,7 @@ import re
import sys import sys
from collections import OrderedDict from collections import OrderedDict
from typing import Callable from typing import Callable, Union, Dict
# Third party modules # Third party modules
from aiohttp import web from aiohttp import web
@ -2100,10 +2100,14 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
help_section['authorization_level'] = 'admin' help_section['authorization_level'] = 'admin'
self.messages['help_sections'][help_section['name']] = help_section self.messages['help_sections'][help_section['name']] = help_section
def command(self, command, aliases=None, reply_keyboard_button=None, def command(self,
command: Union[str, Dict[str, str]],
aliases=None,
reply_keyboard_button=None,
show_in_keyboard=False, description="", show_in_keyboard=False, description="",
help_section=None, help_section=None,
authorization_level='admin'): authorization_level='admin',
language_labelled_commands: Dict[str, str] = None):
"""Associate a bot command with a custom handler function. """Associate a bot command with a custom handler function.
Decorate command handlers like this: Decorate command handlers like this:
@ -2114,7 +2118,8 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
``` ```
When a message text starts with `/command[@bot_name]`, or with an When a message text starts with `/command[@bot_name]`, or with an
alias, it gets passed to the decorated function. alias, it gets passed to the decorated function.
`command` is the command name (with or without /). `command` is the command name (with or without /). Language-labeled
commands are supported in the form of {'en': 'command', ...}
`aliases` is a list of aliases; each will call the command handler `aliases` is a list of aliases; each will call the command handler
function; the first alias will appear as button in function; the first alias will appear as button in
reply keyboard if `reply_keyboard_button` is not set. reply keyboard if `reply_keyboard_button` is not set.
@ -2142,7 +2147,30 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
} }
`authorization_level` is the lowest authorization level needed to run `authorization_level` is the lowest authorization level needed to run
the command. the command.
For advanced examples see `davtelepot.helper` or other modules
(suggestions, administration_tools, ...).
""" """
if language_labelled_commands is None:
language_labelled_commands = dict()
# Handle language-labelled commands:
# choose one main command and add others to `aliases`
if isinstance(command, dict) and len(command) > 0:
language_labelled_commands = command.copy()
if 'main' in language_labelled_commands:
command = language_labelled_commands['main']
elif self.default_language in language_labelled_commands:
command = language_labelled_commands[self.default_language]
else:
for command in language_labelled_commands.values():
break
if aliases is None:
aliases = []
aliases += [
alias
for alias in language_labelled_commands.values()
if alias != command
]
if not isinstance(command, str): if not isinstance(command, str):
raise TypeError(f'Command `{command}` is not a string') raise TypeError(f'Command `{command}` is not a string')
if isinstance(reply_keyboard_button, dict): if isinstance(reply_keyboard_button, dict):
@ -2192,7 +2220,8 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
self.commands[command] = dict( self.commands[command] = dict(
handler=decorated_command_handler, handler=decorated_command_handler,
description=description, description=description,
authorization_level=authorization_level authorization_level=authorization_level,
language_labelled_commands=language_labelled_commands
) )
if type(description) is dict: if type(description) is dict:
self.messages['commands'][command] = dict( self.messages['commands'][command] = dict(

View File

@ -1,16 +1,15 @@
"""Make a self-consistent bot help section.""" """Make a self-consistent bot help section."""
# Third party modules # Project modules
from davtelepot.utilities import ( from .bot import Bot
from .messages import default_help_messages
from .utilities import (
get_cleaned_text, make_inline_keyboard, get_cleaned_text, make_inline_keyboard,
make_lines_of_buttons, make_button make_lines_of_buttons, make_button
) )
# Project modules
from .messages import default_help_messages
def get_commands_description(bot: Bot, update, user_record):
def get_commands_description(bot, update, user_record):
"""Get a string description of `bot` commands. """Get a string description of `bot` commands.
Show only commands available for `update` sender. Show only commands available for `update` sender.
@ -31,7 +30,11 @@ def get_commands_description(bot, update, user_record):
commands[command_role.code] = [] commands[command_role.code] = []
commands[command_role.code].append( commands[command_role.code].append(
"/{command}{authorization_level}: {description}".format( "/{command}{authorization_level}: {description}".format(
command=command, command=bot.get_message(
messages=details['language_labelled_commands'],
default_message=command,
user_record=user_record, update=update
),
authorization_level=( authorization_level=(
f" <i>[{command_role.plural}]</i>" f" <i>[{command_role.plural}]</i>"
if command_role.code != bot.Role.default_role_code if command_role.code != bot.Role.default_role_code

View File

@ -140,26 +140,9 @@ class MultiLanguageObject(object):
result = messages or self.messages result = messages or self.messages
for field in fields: for field in fields:
if field not in result: if field not in result:
logging.debug( if not default_message:
"Please define self.message{f}".format(
f=''.join(
'[\'{field}\']'.format(
field=field
)
for field in fields
)
)
)
return default_message or self.missing_message
result = result[field]
if language not in result:
# For specific languages, try generic ones
language = language.partition('-')[0]
if language not in result:
language = 'en'
if language not in result:
logging.debug( logging.debug(
"Please define self.message{f}['en']".format( "Please define self.message{f}".format(
f=''.join( f=''.join(
'[\'{field}\']'.format( '[\'{field}\']'.format(
field=field field=field
@ -168,6 +151,25 @@ class MultiLanguageObject(object):
) )
) )
) )
return default_message or self.missing_message
result = result[field]
if language not in result:
# For specific languages, try generic ones
language = language.partition('-')[0]
if language not in result:
language = 'en'
if language not in result:
if not default_message:
logging.debug(
"Please define self.message{f}['en']".format(
f=''.join(
'[\'{field}\']'.format(
field=field
)
for field in fields
)
)
)
return default_message or self.missing_message return default_message or self.missing_message
if type(result) is str: if type(result) is str:
return result return result