From 6340b4d658c4c68e6901e42c95beaed887a5eae0 Mon Sep 17 00:00:00 2001 From: Davte Date: Fri, 24 Apr 2020 00:51:21 +0200 Subject: [PATCH] Notify new versions to admins --- davtelepot/__init__.py | 2 +- davtelepot/administration_tools.py | 66 +++++- davtelepot/messages.py | 330 +++++++++++++++-------------- 3 files changed, 239 insertions(+), 159 deletions(-) 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 f1b0ceb..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: @@ -994,3 +1050,7 @@ def init(telegram_bot, talk_messages=None, admin_messages=None): 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 = {