Config command implemented, allowing administrators to add variables to configuration files

This commit is contained in:
Davte 2023-07-25 16:41:22 +02:00
parent fb04211e81
commit febe5cee3f
Signed by: Davte
GPG Key ID: 81F45E046B2D138E
5 changed files with 111 additions and 9 deletions

View File

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

View File

@ -29,13 +29,17 @@ from davtelepot.utilities import (
async_wrapper, CachedPage, Confirmator, extract, get_cleaned_text,
get_user, clean_html_string, line_drawing_unordered_list, make_button,
make_inline_keyboard, remove_html_tags, send_part_of_text_file,
send_csv_file, make_lines_of_buttons
send_csv_file, make_lines_of_buttons, join_path
)
# Use this parameter in SQL `LIMIT x OFFSET y` clauses
rows_number_limit = 10
command_description_parser = re.compile(r'(?P<command>\w+)(\s?-\s?(?P<description>.*))?')
variable_regex = re.compile(r"(?P<name>[a-zA-Z][\w]*)\s*=\s*"
r"(?P<value>[\d.,]+|True|False|"
r"'[^']*'|"
r"\"[^\"]*\")")
async def _forward_to(update,
@ -1805,6 +1809,40 @@ async def _father_button(bot: Bot, user_record: OrderedDict,
return result
async def _config_command(bot: Bot, update: dict,
user_record: dict, language: str):
text = get_cleaned_text(
update,
bot,
['config']
)
if not text:
return bot.get_message('admin', 'config_command',
'instructions',
user_record=user_record,
language=language)
match = variable_regex.match(text)
if not match:
return bot.get_message('admin', 'config_command',
'invalid_input',
user_record=user_record,
language=language)
match = match.groupdict()
if (',' in match['value']
and not match['value'].startswith('\'')
and not match['value'].startswith('"')):
match['value'] = match['value'].replace(',', '.')
new_variable = f"{match['name']} = {match['value']}"
with open(join_path(bot.path, 'data', 'config.py'),
'a') as configuration_file:
configuration_file.write(f"{new_variable}\n")
return bot.get_message('admin', 'config_command',
'success',
new_variable=new_variable,
user_record=user_record,
language=language)
def init(telegram_bot: Bot,
talk_messages: dict = None,
admin_messages: dict = None,
@ -2019,3 +2057,18 @@ def init(telegram_bot: Bot,
update=update,
user_record=user_record,
language=language)
@telegram_bot.command(command='/config',
aliases=[],
**{key: admin_messages['config_command'][key]
for key in ('reply_keyboard_button',
'description',
'help_section',)
},
show_in_keyboard=False,
authorization_level='admin')
async def config_command(bot, update, user_record, language):
return await _config_command(bot=bot,
update=update,
user_record=user_record,
language=language)

View File

@ -10,14 +10,10 @@ import davtelepot.administration_tools as administration_tools
import davtelepot.helper as helper
from davtelepot.bot import Bot
from davtelepot.utilities import (get_cleaned_text, get_secure_key,
get_user, json_read, json_write,
get_user, join_path, json_read, json_write,
line_drawing_unordered_list)
def join_path(*args):
return os.path.abspath(os.path.join(*args))
def dir_path(path):
if os.path.isdir(path) and os.access(path, os.W_OK):
return path
@ -99,11 +95,13 @@ async def elevate_to_admin(bot: Bot, update: dict, user_record: dict,
def allow_elevation_to_admin(telegram_bot: Bot) -> None:
secret = get_secure_key(length=15)
@telegram_bot.additional_task('BEFORE')
async def print_secret():
await telegram_bot.get_me()
logging.info(f"To get administration privileges, enter code {secret} "
f"or click here: https://t.me/{telegram_bot.name}?start=00elevate_{secret}")
@telegram_bot.command(command='/elevate', aliases=['00elevate_'], show_in_keyboard=False,
authorization_level='anybody')
async def _elevate_to_admin(bot, update, user_record):
@ -143,7 +141,7 @@ def send_single_message(telegram_bot: Bot):
line_drawing_unordered_list(
list(map(lambda x: get_user(x, False),
records[:max_shown]))
+ (['...'] if len(records)>=max_shown else [])
+ (['...'] if len(records) >= max_shown else [])
),
sep='\n')
text = input("Select a recipient: write part of their name.\t\t")
@ -165,7 +163,7 @@ def run_from_command_line():
stored_arguments_file = os.path.join(arguments['path'],
'cli_args.json')
for key, value in json_read(file_=stored_arguments_file,
default={}).items():
default={}).items():
if key not in arguments or not arguments[key]:
arguments[key] = value
set_loggers(**{k: v

View File

@ -36,6 +36,53 @@ default_admin_messages = {
'it': "annulla",
},
},
'config_command': {
'description': {
'en': "Add a variable to the configuration file",
'it': "Aggiungi una variabile al file di configurazione",
},
'help_section': None,
'instructions': {
'en': "<b>Config 🔧</b>\n\n"
"<i>Send me a new configuration variable, for example:</i>\n"
"<code>variable = 2</code>",
'it': "<b>Configurazione 🔧</b>\n\n"
"<i>Mandami una variabile da aggiungere al file di "
"configurazione, per esempio:</i>\n"
"<code>variabile = 2</code>",
},
'invalid_input': {
'en': "<b>❌ Invalid input 🔧</b>\n\n"
"<i>Send me a new configuration variable, for example:</i>\n"
"<code>int_var = 2\n"
"str_var = 'test'\n"
"bool_var = False\n"
"float_var = 3.5</code>",
'it': "<b>❌ Configurazione scorretta 🔧</b>\n\n"
"<i>Mandami una variabile da aggiungere al file di "
"configurazione, per esempio:</i>\n"
"<code>var_int = 2\n"
"var_str = 'test'\n"
"var_bool = False\n"
"var_float = 3.5</code>",
},
'reply_keyboard_button': {
'en': "Config 🔧",
'it': "Configurazione 🔧",
},
'success': {
'en': "<b>✔️ Configuration updated 🔧</b>\n\n"
"The following variable has been added to the configuration "
"file:\n"
"<code>{new_variable}</code>\n\n"
"/restart to apply",
'it': "<b>✔️ Configurazione aggiornata 🔧</b>\n\n"
"La seguente variabile è stata aggiunta al file di "
"configurazione:\n"
"<code>{new_variable}</code>\n\n"
"Per rendere effettive le modifiche fai /restart",
},
},
'confirm': {
'en': "🔄 Click again to confirm",
'it': "🔄 Clicka di nuovo per confermare",

View File

@ -1738,3 +1738,7 @@ async def aio_subprocess_shell(command: str) -> Tuple[str, str]:
)
)
return stdout, stderr
def join_path(*args):
return os.path.abspath(os.path.join(*args))