Queer European MD passionate about IT
Browse Source

Notify new versions to admins

Davte 4 years ago
parent
commit
6340b4d658
3 changed files with 236 additions and 156 deletions
  1. 1 1
      davtelepot/__init__.py
  2. 63 3
      davtelepot/administration_tools.py
  3. 172 152
      davtelepot/messages.py

+ 1 - 1
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"
 

+ 63 - 3
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)

+ 172 - 152
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': "<i>Restart was successful.</i>",
-            'it': "<i>Restart avvenuto con successo.</i>"
-        }
-    },
-    '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 <code>git pull</code> "
-                  "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 "
-                  "<code>git pull</code>)."
-        }
-    },
-    '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,53 +23,47 @@ default_admin_messages = {
             'it': "Database inviato."
         }
     },
-    'query_command': {
+    'errors_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"
+            'en': "Receive bot error log file, if set",
+            'it': "Ricevi il file di log degli errori del bot, se impostato"
         },
-        'help': {
-            'en': "Write a SQL query to be run on bot database.\n\n"
-                  "<b>Example</b>\n"
-                  "<code>/query SELECT * FROM users WHERE 0</code>",
-            'it': "Invia una query SQL da eseguire sul database del bot.\n\n"
-                  "<b>Esempio</b>\n"
-                  "<code>/query SELECT * FROM users WHERE 0</code>"
+        'no_log': {
+            'en': "Sorry but no errors log file is set.\n"
+                  "To set it, use `bot.set_errors_file_name` instance method"
+                  "or `Bot.set_class_errors_file_name` class method.",
+            'it': "Spiacente ma il file di log degli errori non è stato "
+                  "impostato.\n"
+                  "Per impostarlo, usa il metodo d'istanza "
+                  "`bot.set_errors_file_name` o il metodo di classe"
+                  "`Bot.set_class_errors_file_name`."
         },
-        'no_iterable': {
-            'en': "No result to show was returned",
-            'it': "La query non ha restituito risultati da mostrare"
+        'empty_log': {
+            'en': "Congratulations! Errors log is empty!",
+            'it': "Congratulazioni! Il log degli errori è vuoto!"
         },
-        'exception': {
-            'en': "The query threw this error:",
-            'it': "La query ha dato questo errore:"
+        'sending_failure': {
+            'en': "Sending errors log file failed!\n\n"
+                  "<b>Error:</b>\n"
+                  "<code>{e}</code>",
+            'it': "Inviio del messaggio di log degli errori fallito!\n\n"
+                  "<b>Errore:</b>\n"
+                  "<code>{e}</code>"
         },
-        '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!"
+        'here_is_log_file': {
+            'en': "Here is the complete errors log file.",
+            'it': "Ecco il file di log degli errori completo."
         },
-        'file_name': {
-            'en': "Query result.csv",
-            'it': "Risultato della query.csv"
+        'log_file_first_lines': {
+            'en': "Here are the first {lines} lines of the errors log file.",
+            'it': "Ecco le prime {lines} righe del file di log degli errori."
         },
-        'empty_file': {
-            'en': "No result to show.",
-            'it': "Nessun risultato da mostrare."
+        'log_file_last_lines': {
+            'en': "Here are the last {lines} lines of the errors log file.\n"
+                  "Newer lines are at the top of the file.",
+            'it': "Ecco le ultime {lines} righe del file di log degli "
+                  "errori.\n"
+                  "L'ordine è cronologico, con i messaggi nuovi in alto."
         }
     },
     'log_command': {
@@ -173,49 +103,6 @@ default_admin_messages = {
                   "L'ordine è cronologico, con i messaggi nuovi in alto."
         }
     },
-    'errors_command': {
-        'description': {
-            'en': "Receive bot error log file, if set",
-            'it': "Ricevi il file di log degli errori del bot, se impostato"
-        },
-        'no_log': {
-            'en': "Sorry but no errors log file is set.\n"
-                  "To set it, use `bot.set_errors_file_name` instance method"
-                  "or `Bot.set_class_errors_file_name` class method.",
-            'it': "Spiacente ma il file di log degli errori non è stato "
-                  "impostato.\n"
-                  "Per impostarlo, usa il metodo d'istanza "
-                  "`bot.set_errors_file_name` o il metodo di classe"
-                  "`Bot.set_class_errors_file_name`."
-        },
-        'empty_log': {
-            'en': "Congratulations! Errors log is empty!",
-            'it': "Congratulazioni! Il log degli errori è vuoto!"
-        },
-        'sending_failure': {
-            'en': "Sending errors log file failed!\n\n"
-                  "<b>Error:</b>\n"
-                  "<code>{e}</code>",
-            'it': "Inviio del messaggio di log degli errori fallito!\n\n"
-                  "<b>Errore:</b>\n"
-                  "<code>{e}</code>"
-        },
-        'here_is_log_file': {
-            'en': "Here is the complete errors log file.",
-            'it': "Ecco il file di log degli errori completo."
-        },
-        'log_file_first_lines': {
-            'en': "Here are the first {lines} lines of the errors log file.",
-            'it': "Ecco le prime {lines} righe del file di log degli errori."
-        },
-        'log_file_last_lines': {
-            'en': "Here are the last {lines} lines of the errors log file.\n"
-                  "Newer lines are at the top of the file.",
-            'it': "Ecco le ultime {lines} righe del file di log degli "
-                  "errori.\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': "<i>Manutenzione terminata!</i>"
         }
     },
+    'new_version': {
+        'title': {
+            'en': "🔔 New version detected! 📰",
+            'it': "🔔 Rilevata nuova versione! 📰",
+        },
+        'last_commit': {
+            'en': "Old commit: <code>{old_record[last_commit]}</code>\n"
+                  "New commit: <code>{new_record[last_commit]}</code>",
+            'it': "Vecchio commit: <code>{old_record[last_commit]}</code>\n"
+                  "Nuovo commit: <code>{new_record[last_commit]}</code>",
+        },
+        'davtelepot_version': {
+            'en': "davtelepot version: "
+                  "<code>{old_record[davtelepot_version]}</code> —> "
+                  "<code>{new_record[davtelepot_version]}</code>",
+            'it': "Versione di davtelepot: "
+                  "<code>{old_record[davtelepot_version]}</code> —> "
+                  "<code>{new_record[davtelepot_version]}</code>",
+        },
+    },
+    '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"
+                  "<b>Example</b>\n"
+                  "<code>/query SELECT * FROM users WHERE 0</code>",
+            'it': "Invia una query SQL da eseguire sul database del bot.\n\n"
+                  "<b>Esempio</b>\n"
+                  "<code>/query SELECT * FROM users WHERE 0</code>"
+        },
+        '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': "<i>Restart was successful.</i>",
+            'it': "<i>Restart avvenuto con successo.</i>"
+        }
+    },
+    '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 <code>git pull</code> "
+                  "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 "
+                  "<code>git pull</code>)."
+        }
+    },
+    '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: <code>{last_commit}</code>\n\n"
+                  "davtelepot version: <code>{davtelepot_version}</code>",
+            'it': "Ultimo commit: <code>{last_commit}</code>\n\n"
+                  "Versione di davtelepot: <code>{davtelepot_version}</code>",
         },
-    }
+    },
 }
 
 default_authorization_denied_message = {