Queer European MD passionate about IT
소스 검색

Merge branch 'develop' of ssh://gogs.davte.it:8445/Davte/davtelepot into develop

Davte 4 년 전
부모
커밋
b0a2770177
3개의 변경된 파일299개의 추가작업 그리고 183개의 파일을 삭제
  1. 1 1
      davtelepot/__init__.py
  2. 126 30
      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"
 

+ 126 - 30
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)

+ 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 = {