diff --git a/davtelepot/__init__.py b/davtelepot/__init__.py
index e504cd2..8f6b159 100644
--- a/davtelepot/__init__.py
+++ b/davtelepot/__init__.py
@@ -14,7 +14,7 @@ __author__ = "Davide Testa"
__email__ = "davide@davte.it"
__credits__ = ["Marco Origlia", "Nick Lee @Nickoala"]
__license__ = "GNU General Public License v3.0"
-__version__ = "2.4.23"
+__version__ = "2.4.24"
__maintainer__ = "Davide Testa"
__contact__ = "t.me/davte"
diff --git a/davtelepot/administration_tools.py b/davtelepot/administration_tools.py
index 7481913..60bc14c 100644
--- a/davtelepot/administration_tools.py
+++ b/davtelepot/administration_tools.py
@@ -779,7 +779,8 @@ def get_maintenance_exception_criterion(bot, allowed_command):
return criterion
-async def _version_command(bot, update, user_record):
+async def get_version():
+ """Get last commit hash and davtelepot version."""
try:
_subprocess = await asyncio.create_subprocess_exec(
'git', 'rev-parse', 'HEAD',
@@ -788,9 +789,16 @@ async def _version_command(bot, update, user_record):
)
stdout, _ = await _subprocess.communicate()
last_commit = stdout.decode().strip()
- davtelepot_version = davtelepot.__version__
except Exception as e:
- return f"{e}"
+ last_commit = f"{e}"
+ if last_commit.startswith("fatal: not a git repository"):
+ last_commit = "-"
+ davtelepot_version = davtelepot.__version__
+ return last_commit, davtelepot_version
+
+
+async def _version_command(bot, update, user_record):
+ last_commit, davtelepot_version = await get_version()
return bot.get_message(
'admin', 'version_command', 'result',
last_commit=last_commit,
@@ -799,6 +807,54 @@ async def _version_command(bot, update, user_record):
)
+async def notify_new_version(bot):
+ """Notify `bot` administrators about new versions.
+
+ Notify admins when last commit and/or davtelepot version change.
+ """
+ last_commit, davtelepot_version = await get_version()
+ old_record = bot.db['version_history'].find_one(
+ order_by=['-id']
+ )
+ if old_record is None:
+ old_record = dict(
+ updated_at=datetime.datetime.min,
+ last_commit=None,
+ davtelepot_version=None
+ )
+ if (
+ old_record['last_commit'] != last_commit
+ or old_record['davtelepot_version'] != davtelepot_version
+ ):
+ new_record = dict(
+ updated_at=datetime.datetime.now(),
+ last_commit=last_commit,
+ davtelepot_version=davtelepot_version
+ )
+ bot.db['version_history'].insert(
+ new_record
+ )
+ for admin in bot.db['users'].find(privileges=[1, 2]):
+ await bot.send_message(
+ chat_id=admin['telegram_id'],
+ disable_notification=True,
+ text='\n\n'.join(
+ bot.get_message(
+ 'admin', 'new_version', field,
+ old_record=old_record,
+ new_record=new_record,
+ user_record=admin
+ )
+ for field in filter(
+ lambda x: (x not in old_record
+ or old_record[x] != new_record[x]),
+ ('title', 'last_commit', 'davtelepot_version')
+ )
+ )
+ )
+ return
+
+
def init(telegram_bot, talk_messages=None, admin_messages=None):
"""Assign parsers, commands, buttons and queries to given `bot`."""
if talk_messages is None:
@@ -848,18 +904,26 @@ def init(telegram_bot, talk_messages=None, admin_messages=None):
admin_record=session['admin_record']
)
- @telegram_bot.command(command='/talk', aliases=[], show_in_keyboard=False,
- description=admin_messages['talk_command']['description'],
+ @telegram_bot.command(command='/talk',
+ aliases=[],
+ show_in_keyboard=False,
+ description=admin_messages[
+ 'talk_command']['description'],
authorization_level='admin')
async def talk_command(bot, update, user_record):
return await _talk_command(bot, update, user_record)
- @telegram_bot.button(prefix='talk:///', separator='|', authorization_level='admin')
+ @telegram_bot.button(prefix='talk:///',
+ separator='|',
+ authorization_level='admin')
async def talk_button(bot, update, user_record, data):
return await _talk_button(bot, update, user_record, data)
- @telegram_bot.command(command='/restart', aliases=[], show_in_keyboard=False,
- description=admin_messages['restart_command']['description'],
+ @telegram_bot.command(command='/restart',
+ aliases=[],
+ show_in_keyboard=False,
+ description=admin_messages[
+ 'restart_command']['description'],
authorization_level='admin')
async def restart_command(bot, update, user_record):
return await _restart_command(bot, update, user_record)
@@ -892,50 +956,72 @@ def init(telegram_bot, talk_messages=None, admin_messages=None):
)
return
- @telegram_bot.command(command='/stop', aliases=[], show_in_keyboard=False,
- description=admin_messages['stop_command']['description'],
+ @telegram_bot.command(command='/stop',
+ aliases=[],
+ show_in_keyboard=False,
+ description=admin_messages[
+ 'stop_command']['description'],
authorization_level='admin')
async def stop_command(bot, update, user_record):
return await _stop_command(bot, update, user_record)
- @telegram_bot.button(prefix='stop:///', separator='|',
- description=admin_messages['stop_command']['description'],
+ @telegram_bot.button(prefix='stop:///',
+ separator='|',
+ description=admin_messages[
+ 'stop_command']['description'],
authorization_level='admin')
async def stop_button(bot, update, user_record, data):
return await _stop_button(bot, update, user_record, data)
- @telegram_bot.command(command='/db', aliases=[], show_in_keyboard=False,
- description=admin_messages['db_command']['description'],
+ @telegram_bot.command(command='/db',
+ aliases=[],
+ show_in_keyboard=False,
+ description=admin_messages[
+ 'db_command']['description'],
authorization_level='admin')
async def send_bot_database(bot, update, user_record):
return await _send_bot_database(bot, update, user_record)
- @telegram_bot.command(command='/query', aliases=[], show_in_keyboard=False,
- description=admin_messages['query_command']['description'],
+ @telegram_bot.command(command='/query',
+ aliases=[],
+ show_in_keyboard=False,
+ description=admin_messages[
+ 'query_command']['description'],
authorization_level='admin')
async def query_command(bot, update, user_record):
return await _query_command(bot, update, user_record)
- @telegram_bot.command(command='/select', aliases=[], show_in_keyboard=False,
- description=admin_messages['select_command']['description'],
+ @telegram_bot.command(command='/select',
+ aliases=[],
+ show_in_keyboard=False,
+ description=admin_messages[
+ 'select_command']['description'],
authorization_level='admin')
async def select_command(bot, update, user_record):
return await _query_command(bot, update, user_record)
- @telegram_bot.button(prefix='db_query:///', separator='|',
- description=admin_messages['query_command']['description'],
+ @telegram_bot.button(prefix='db_query:///',
+ separator='|',
+ description=admin_messages[
+ 'query_command']['description'],
authorization_level='admin')
async def query_button(bot, update, user_record, data):
return await _query_button(bot, update, user_record, data)
- @telegram_bot.command(command='/log', aliases=[], show_in_keyboard=False,
- description=admin_messages['log_command']['description'],
+ @telegram_bot.command(command='/log',
+ aliases=[],
+ show_in_keyboard=False,
+ description=admin_messages[
+ 'log_command']['description'],
authorization_level='admin')
async def log_command(bot, update, user_record):
return await _log_command(bot, update, user_record)
- @telegram_bot.command(command='/errors', aliases=[], show_in_keyboard=False,
- description=admin_messages['errors_command']['description'],
+ @telegram_bot.command(command='/errors',
+ aliases=[],
+ show_in_keyboard=False,
+ description=admin_messages[
+ 'errors_command']['description'],
authorization_level='admin')
async def errors_command(bot, update, user_record):
return await _errors_command(bot, update, user_record)
@@ -943,18 +1029,28 @@ def init(telegram_bot, talk_messages=None, admin_messages=None):
for exception in allowed_during_maintenance:
telegram_bot.allow_during_maintenance(exception)
- @telegram_bot.command(command='/maintenance', aliases=[], show_in_keyboard=False,
- description=admin_messages['maintenance_command']['description'],
+ @telegram_bot.command(command='/maintenance', aliases=[],
+ show_in_keyboard=False,
+ description=admin_messages[
+ 'maintenance_command']['description'],
authorization_level='admin')
async def maintenance_command(bot, update, user_record):
return await _maintenance_command(bot, update, user_record)
@telegram_bot.command(command='/version',
aliases=[],
- reply_keyboard_button=admin_messages['version_command']['reply_keyboard_button'],
+ **{key: admin_messages['version_command'][key]
+ for key in ('reply_keyboard_button',
+ 'description',
+ 'help_section',)
+ },
show_in_keyboard=False,
- description=admin_messages['version_command']['description'],
- help_section=admin_messages['version_command']['help_section'],
authorization_level='admin',)
async def version_command(bot, update, user_record):
- return await _version_command(bot=bot, update=update, user_record=user_record)
+ return await _version_command(bot=bot,
+ update=update,
+ user_record=user_record)
+
+ @telegram_bot.additional_task(when='BEFORE', bot=telegram_bot)
+ async def notify_version(bot):
+ return await notify_new_version(bot=bot)
diff --git a/davtelepot/messages.py b/davtelepot/messages.py
index 5e2071e..57471ab 100644
--- a/davtelepot/messages.py
+++ b/davtelepot/messages.py
@@ -1,70 +1,6 @@
"""Default messages for bot functions."""
default_admin_messages = {
- 'talk_command': {
- 'description': {
- 'en': "Choose a user and forward messages to each other",
- 'it': "Scegli un utente e il bot farà da tramite inoltrando a "
- "ognuno i messaggi dell'altro finché non terminerai la "
- "sessione"
- }
- },
- 'restart_command': {
- 'description': {
- 'en': "Restart bots",
- 'it': "Riavvia i bot"
- },
- 'restart_scheduled_message': {
- 'en': "Bots are being restarted, after pulling from repository.",
- 'it': "I bot verranno riavviati in pochi secondi, caricando "
- "prima le eventuali modifiche al codice."
- },
- 'restart_completed_message': {
- 'en': "Restart was successful.",
- 'it': "Restart avvenuto con successo."
- }
- },
- 'stop_command': {
- 'description': {
- 'en': "Stop bots",
- 'it': "Ferma i bot"
- },
- 'text': {
- 'en': "Are you sure you want to stop all bots?\n"
- "To make them start again you will have to ssh-log "
- "in server.\n\n"
- "To restart the bots remotely use the /restart command "
- "instead (before starting over, a git pull
"
- "is performed).",
- 'it': "Sei sicuro di voler fermare i bot?\n"
- "Per farli ripartire dovrai accedere al server.\n\n"
- "Per far ripartire i bot da remoto usa invece il comando "
- "/restart (prima di ripartire farò un "
- "git pull
)."
- }
- },
- 'stop_button': {
- 'stop_text': {
- 'en': "Stop bots",
- 'it': "Ferma i bot"
- },
- 'cancel': {
- 'en': "Cancel",
- 'it': "Annulla"
- },
- 'confirm': {
- 'en': "Do you really want to stop all bots?",
- 'it': "Vuoi davvero fermare tutti i bot?"
- },
- 'stopping': {
- 'en': "Stopping bots...",
- 'it': "Arresto in corso..."
- },
- 'cancelled': {
- 'en': "Operation was cancelled",
- 'it': "Operazione annullata"
- }
- },
'db_command': {
'description': {
'en': "Ask for bot database via Telegram",
@@ -87,92 +23,6 @@ default_admin_messages = {
'it': "Database inviato."
}
},
- 'query_command': {
- 'description': {
- 'en': "Receive the result of a SQL query performed on bot "
- "database",
- 'it': "Ricevi il risultato di una query SQL sul database del bot"
- },
- 'help': {
- 'en': "Write a SQL query to be run on bot database.\n\n"
- "Example\n"
- "/query SELECT * FROM users WHERE 0
",
- 'it': "Invia una query SQL da eseguire sul database del bot.\n\n"
- "Esempio\n"
- "/query SELECT * FROM users WHERE 0
"
- },
- 'no_iterable': {
- 'en': "No result to show was returned",
- 'it': "La query non ha restituito risultati da mostrare"
- },
- 'exception': {
- 'en': "The query threw this error:",
- 'it': "La query ha dato questo errore:"
- },
- 'result': {
- 'en': "Query result",
- 'it': "Risultato della query"
- }
- },
- 'select_command': {
- 'description': {
- 'en': "Receive the result of a SELECT query performed on bot "
- "database",
- 'it': "Ricevi il risultato di una query SQL di tipo SELECT "
- "sul database del bot"
- }
- },
- 'query_button': {
- 'error': {
- 'en': "Error!",
- 'it': "Errore!"
- },
- 'file_name': {
- 'en': "Query result.csv",
- 'it': "Risultato della query.csv"
- },
- 'empty_file': {
- 'en': "No result to show.",
- 'it': "Nessun risultato da mostrare."
- }
- },
- 'log_command': {
- 'description': {
- 'en': "Receive bot log file, if set",
- 'it': "Ricevi il file di log del bot, se impostato"
- },
- 'no_log': {
- 'en': "Sorry but no log file is set.\n"
- "To set it, use `bot.set_log_file_name` instance method or "
- "`Bot.set_class_log_file_name` class method.",
- 'it': "Spiacente ma il file di log non è stato impostato.\n"
- "Per impostarlo, usa il metodo d'istanza "
- "`bot.set_log_file_name` o il metodo di classe"
- "`Bot.set_class_log_file_name`."
- },
- 'sending_failure': {
- 'en': "Sending log file failed!\n\n"
- "Error:\n"
- "{e}
",
- 'it': "Inviio del messaggio di log fallito!\n\n"
- "Errore:\n"
- "{e}
"
- },
- 'here_is_log_file': {
- 'en': "Here is the complete log file.",
- 'it': "Ecco il file di log completo."
- },
- 'log_file_first_lines': {
- 'en': "Here are the first {lines} lines of the log file.",
- 'it': "Ecco le prime {lines} righe del file di log."
- },
- 'log_file_last_lines': {
- 'en': "Here are the last {lines} lines of the log file.\n"
- "Newer lines are at the top of the file.",
- 'it': "Ecco le ultime {lines} righe del file di log.\n"
- "L'ordine è cronologico, con i messaggi nuovi in alto."
- }
- },
'errors_command': {
'description': {
'en': "Receive bot error log file, if set",
@@ -216,6 +66,43 @@ default_admin_messages = {
"L'ordine è cronologico, con i messaggi nuovi in alto."
}
},
+ 'log_command': {
+ 'description': {
+ 'en': "Receive bot log file, if set",
+ 'it': "Ricevi il file di log del bot, se impostato"
+ },
+ 'no_log': {
+ 'en': "Sorry but no log file is set.\n"
+ "To set it, use `bot.set_log_file_name` instance method or "
+ "`Bot.set_class_log_file_name` class method.",
+ 'it': "Spiacente ma il file di log non è stato impostato.\n"
+ "Per impostarlo, usa il metodo d'istanza "
+ "`bot.set_log_file_name` o il metodo di classe"
+ "`Bot.set_class_log_file_name`."
+ },
+ 'sending_failure': {
+ 'en': "Sending log file failed!\n\n"
+ "Error:\n"
+ "{e}
",
+ 'it': "Inviio del messaggio di log fallito!\n\n"
+ "Errore:\n"
+ "{e}
"
+ },
+ 'here_is_log_file': {
+ 'en': "Here is the complete log file.",
+ 'it': "Ecco il file di log completo."
+ },
+ 'log_file_first_lines': {
+ 'en': "Here are the first {lines} lines of the log file.",
+ 'it': "Ecco le prime {lines} righe del file di log."
+ },
+ 'log_file_last_lines': {
+ 'en': "Here are the last {lines} lines of the log file.\n"
+ "Newer lines are at the top of the file.",
+ 'it': "Ecco le ultime {lines} righe del file di log.\n"
+ "L'ordine è cronologico, con i messaggi nuovi in alto."
+ }
+ },
'maintenance_command': {
'description': {
'en': "Put the bot under maintenance",
@@ -236,6 +123,139 @@ default_admin_messages = {
'it': "Manutenzione terminata!"
}
},
+ 'new_version': {
+ 'title': {
+ 'en': "🔔 New version detected! 📰",
+ 'it': "🔔 Rilevata nuova versione! 📰",
+ },
+ 'last_commit': {
+ 'en': "Old commit: {old_record[last_commit]}
\n"
+ "New commit: {new_record[last_commit]}
",
+ 'it': "Vecchio commit: {old_record[last_commit]}
\n"
+ "Nuovo commit: {new_record[last_commit]}
",
+ },
+ 'davtelepot_version': {
+ 'en': "davtelepot version: "
+ "{old_record[davtelepot_version]}
—> "
+ "{new_record[davtelepot_version]}
",
+ 'it': "Versione di davtelepot: "
+ "{old_record[davtelepot_version]}
—> "
+ "{new_record[davtelepot_version]}
",
+ },
+ },
+ 'query_button': {
+ 'error': {
+ 'en': "Error!",
+ 'it': "Errore!",
+ },
+ 'file_name': {
+ 'en': "Query result.csv",
+ 'it': "Risultato della query.csv",
+ },
+ 'empty_file': {
+ 'en': "No result to show.",
+ 'it': "Nessun risultato da mostrare.",
+ }
+ },
+ 'query_command': {
+ 'description': {
+ 'en': "Receive the result of a SQL query performed on bot "
+ "database",
+ 'it': "Ricevi il risultato di una query SQL sul database del bot"
+ },
+ 'help': {
+ 'en': "Write a SQL query to be run on bot database.\n\n"
+ "Example\n"
+ "/query SELECT * FROM users WHERE 0
",
+ 'it': "Invia una query SQL da eseguire sul database del bot.\n\n"
+ "Esempio\n"
+ "/query SELECT * FROM users WHERE 0
"
+ },
+ 'no_iterable': {
+ 'en': "No result to show was returned",
+ 'it': "La query non ha restituito risultati da mostrare"
+ },
+ 'exception': {
+ 'en': "The query threw this error:",
+ 'it': "La query ha dato questo errore:"
+ },
+ 'result': {
+ 'en': "Query result",
+ 'it': "Risultato della query"
+ }
+ },
+ 'restart_command': {
+ 'description': {
+ 'en': "Restart bots",
+ 'it': "Riavvia i bot"
+ },
+ 'restart_scheduled_message': {
+ 'en': "Bots are being restarted, after pulling from repository.",
+ 'it': "I bot verranno riavviati in pochi secondi, caricando "
+ "prima le eventuali modifiche al codice."
+ },
+ 'restart_completed_message': {
+ 'en': "Restart was successful.",
+ 'it': "Restart avvenuto con successo."
+ }
+ },
+ 'select_command': {
+ 'description': {
+ 'en': "Receive the result of a SELECT query performed on bot "
+ "database",
+ 'it': "Ricevi il risultato di una query SQL di tipo SELECT "
+ "sul database del bot"
+ }
+ },
+ 'stop_button': {
+ 'stop_text': {
+ 'en': "Stop bots",
+ 'it': "Ferma i bot"
+ },
+ 'cancel': {
+ 'en': "Cancel",
+ 'it': "Annulla"
+ },
+ 'confirm': {
+ 'en': "Do you really want to stop all bots?",
+ 'it': "Vuoi davvero fermare tutti i bot?"
+ },
+ 'stopping': {
+ 'en': "Stopping bots...",
+ 'it': "Arresto in corso..."
+ },
+ 'cancelled': {
+ 'en': "Operation was cancelled",
+ 'it': "Operazione annullata"
+ }
+ },
+ 'stop_command': {
+ 'description': {
+ 'en': "Stop bots",
+ 'it': "Ferma i bot"
+ },
+ 'text': {
+ 'en': "Are you sure you want to stop all bots?\n"
+ "To make them start again you will have to ssh-log "
+ "in server.\n\n"
+ "To restart the bots remotely use the /restart command "
+ "instead (before starting over, a git pull
"
+ "is performed).",
+ 'it': "Sei sicuro di voler fermare i bot?\n"
+ "Per farli ripartire dovrai accedere al server.\n\n"
+ "Per far ripartire i bot da remoto usa invece il comando "
+ "/restart (prima di ripartire farò un "
+ "git pull
)."
+ }
+ },
+ 'talk_command': {
+ 'description': {
+ 'en': "Choose a user and forward messages to each other",
+ 'it': "Scegli un utente e il bot farà da tramite inoltrando a "
+ "ognuno i messaggi dell'altro finché non terminerai la "
+ "sessione"
+ }
+ },
'version_command': {
'reply_keyboard_button': {
'en': "Version #️⃣",
@@ -247,12 +267,12 @@ default_admin_messages = {
},
'help_section': None,
'result': {
- 'en': "Last commit: {last_commit}\n"
- "davtelepot version: {davtelepot_version}",
- 'it': "Ultimo commit: {last_commit}\n"
- "Versione di davtelepot: {davtelepot_version}",
+ 'en': "Last commit: {last_commit}
\n\n"
+ "davtelepot version: {davtelepot_version}
",
+ 'it': "Ultimo commit: {last_commit}
\n\n"
+ "Versione di davtelepot: {davtelepot_version}
",
},
- }
+ },
}
default_authorization_denied_message = {