Queer European MD passionate about IT
Эх сурвалжийг харах

Implemented /father command.

It allows to see commands stored by BotFather, get default command list, change it and send it to BotFather.
Davte 4 жил өмнө
parent
commit
a4079cf91d

+ 1 - 1
davtelepot/__init__.py

@@ -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.5.7"
+__version__ = "2.5.8"
 __maintainer__ = "Davide Testa"
 __contact__ = "t.me/davte"
 

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 848 - 112
davtelepot/administration_tools.py


+ 21 - 6
davtelepot/api.py

@@ -664,18 +664,33 @@ class TelegramBot:
             parameters=locals()
         )
 
-    async def sendPoll(self, chat_id, question, options,
-                       dummy=None,
-                       disable_notification=None,
-                       reply_to_message_id=None,
+    async def sendPoll(self,
+                       chat_id: Union[int, str],
+                       question: str,
+                       options: List[str],
+                       is_anonymous: bool = True,
+                       type_: str = 'regular',
+                       allows_multiple_answers: bool = False,
+                       correct_option_id: int = None,
+                       explanation: str = None,
+                       explanation_parse_mode: str = None,
+                       open_period: int = None,
+                       close_date: int = None,
+                       is_closed: bool = None,
+                       disable_notification: bool = None,
+                       reply_to_message_id: int = None,
                        reply_markup=None):
         """Send a native poll in a group, a supergroup or channel.
 
         See https://core.telegram.org/bots/api#sendpoll for details.
         """
+        # To avoid shadowing `type`, this workaround is required
+        parameters = locals().copy()
+        parameters['type'] = parameters['type_']
+        del parameters['type_']
         return await self.api_request(
             'sendPoll',
-            parameters=locals()
+            parameters=parameters
         )
 
     async def sendChatAction(self, chat_id, action):
@@ -1409,7 +1424,7 @@ class TelegramBot:
             parameters=locals()
         )
 
-    async def setMyCommands(self, commands: List[Command]):
+    async def setMyCommands(self, commands: List[Union[Command, dict]]):
         """Change the list of the bot's commands.
 
         Use this method to change the list of the bot's commands.

+ 1 - 0
davtelepot/api_helper.py

@@ -136,6 +136,7 @@ async def print_api_methods(loop=None,
                 parameters_table = tag
                 break  # Stop searching in siblings if <table> is found
             description += tag.get_text()
+        # Methods start with a lowercase letter
         if method_name and method_name[0] == method_name[0].lower():
             methods.append(
                 TelegramApiMethod(

+ 58 - 52
davtelepot/bot.py

@@ -17,11 +17,11 @@ Usage
                       database_url='my_other_db')
 
     @long_polling_bot.command('/foo')
-    async def foo_command(bot, update, user_record):
+    async def foo_command(bot, update, user_record, language):
         return "Bar!"
 
     @webhook_bot.command('/bar')
-    async def bar_command(bot, update, user_record):
+    async def bar_command(bot, update, user_record, language):
         return "Foo!"
 
     exit_state = Bot.run(
@@ -579,17 +579,19 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
     def administrators(self):
         return self._get_administrators(self)
 
-    async def message_router(self, update, user_record):
+    async def message_router(self, update, user_record, language):
         """Route Telegram `message` update to appropriate message handler."""
         for key, value in update.items():
             if key in self.message_handlers:
-                return await self.message_handlers[key](update, user_record)
+                return await self.message_handlers[key](update=update,
+                                                        user_record=user_record,
+                                                        language=language)
         logging.error(
             f"The following message update was received: {update}\n"
             "However, this message type is unknown."
         )
 
-    async def edited_message_handler(self, update, user_record):
+    async def edited_message_handler(self, update, user_record, language=None):
         """Handle Telegram `edited_message` update."""
         logging.info(
             f"The following update was received: {update}\n"
@@ -597,7 +599,7 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
         )
         return
 
-    async def channel_post_handler(self, update, user_record):
+    async def channel_post_handler(self, update, user_record, language=None):
         """Handle Telegram `channel_post` update."""
         logging.info(
             f"The following update was received: {update}\n"
@@ -605,7 +607,7 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
         )
         return
 
-    async def edited_channel_post_handler(self, update, user_record):
+    async def edited_channel_post_handler(self, update, user_record, language=None):
         """Handle Telegram `edited_channel_post` update."""
         logging.info(
             f"The following update was received: {update}\n"
@@ -613,7 +615,7 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
         )
         return
 
-    async def inline_query_handler(self, update, user_record):
+    async def inline_query_handler(self, update, user_record, language=None):
         """Handle Telegram `inline_query` update.
 
         Answer it with results or log errors.
@@ -648,7 +650,7 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
             logging.info("Error answering inline query\n{}".format(e))
         return
 
-    async def chosen_inline_result_handler(self, update, user_record):
+    async def chosen_inline_result_handler(self, update, user_record, language=None):
         """Handle Telegram `chosen_inline_result` update."""
         if user_record is not None:
             user_id = user_record['telegram_id']
@@ -678,7 +680,7 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
         self.chosen_inline_result_handlers[user_id][result_id] = handler
         return
 
-    async def callback_query_handler(self, update, user_record):
+    async def callback_query_handler(self, update, user_record, language=None):
         """Handle Telegram `callback_query` update.
 
         A callback query is sent when users press inline keyboard buttons.
@@ -699,7 +701,8 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
                 answer = await _function(
                     bot=self,
                     update=update,
-                    user_record=user_record
+                    user_record=user_record,
+                    language=language
                 )
                 break
         if answer is None:
@@ -733,7 +736,7 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
             logging.error(e)
         return
 
-    async def shipping_query_handler(self, update, user_record):
+    async def shipping_query_handler(self, update, user_record, language=None):
         """Handle Telegram `shipping_query` update."""
         logging.info(
             f"The following update was received: {update}\n"
@@ -741,7 +744,7 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
         )
         return
 
-    async def pre_checkout_query_handler(self, update, user_record):
+    async def pre_checkout_query_handler(self, update, user_record, language=None):
         """Handle Telegram `pre_checkout_query` update."""
         logging.info(
             f"The following update was received: {update}\n"
@@ -749,7 +752,7 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
         )
         return
 
-    async def poll_handler(self, update, user_record):
+    async def poll_handler(self, update, user_record, language=None):
         """Handle Telegram `poll` update."""
         logging.info(
             f"The following update was received: {update}\n"
@@ -757,7 +760,7 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
         )
         return
 
-    async def text_message_handler(self, update, user_record):
+    async def text_message_handler(self, update, user_record, language=None):
         """Handle `text` message update."""
         replier, reply = None, None
         text = update['text'].lower()
@@ -817,56 +820,56 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
                 )
         return
 
-    async def audio_file_handler(self, update, user_record):
+    async def audio_file_handler(self, update, user_record, language=None):
         """Handle `audio` file update."""
         logging.info(
             "A audio file update was received, "
             "but this handler does nothing yet."
         )
 
-    async def document_message_handler(self, update, user_record):
+    async def document_message_handler(self, update, user_record, language=None):
         """Handle `document` message update."""
         logging.info(
             "A document message update was received, "
             "but this handler does nothing yet."
         )
 
-    async def animation_message_handler(self, update, user_record):
+    async def animation_message_handler(self, update, user_record, language=None):
         """Handle `animation` message update."""
         logging.info(
             "A animation message update was received, "
             "but this handler does nothing yet."
         )
 
-    async def game_message_handler(self, update, user_record):
+    async def game_message_handler(self, update, user_record, language=None):
         """Handle `game` message update."""
         logging.info(
             "A game message update was received, "
             "but this handler does nothing yet."
         )
 
-    async def photo_message_handler(self, update, user_record):
+    async def photo_message_handler(self, update, user_record, language=None):
         """Handle `photo` message update."""
         logging.info(
             "A photo message update was received, "
             "but this handler does nothing yet."
         )
 
-    async def sticker_message_handler(self, update, user_record):
+    async def sticker_message_handler(self, update, user_record, language=None):
         """Handle `sticker` message update."""
         logging.info(
             "A sticker message update was received, "
             "but this handler does nothing yet."
         )
 
-    async def video_message_handler(self, update, user_record):
+    async def video_message_handler(self, update, user_record, language=None):
         """Handle `video` message update."""
         logging.info(
             "A video message update was received, "
             "but this handler does nothing yet."
         )
 
-    async def voice_message_handler(self, update, user_record):
+    async def voice_message_handler(self, update, user_record, language=None):
         """Handle `voice` message update."""
         replier, reply = None, None
         user_id = update['from']['id'] if 'from' in update else None
@@ -896,21 +899,21 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
                 )
         return
 
-    async def video_note_message_handler(self, update, user_record):
+    async def video_note_message_handler(self, update, user_record, language=None):
         """Handle `video_note` message update."""
         logging.info(
             "A video_note message update was received, "
             "but this handler does nothing yet."
         )
 
-    async def contact_message_handler(self, update, user_record):
+    async def contact_message_handler(self, update, user_record, language=None):
         """Handle `contact` message update."""
         logging.info(
             "A contact message update was received, "
             "but this handler does nothing yet."
         )
 
-    async def location_message_handler(self, update, user_record):
+    async def location_message_handler(self, update, user_record, language=None):
         """Handle `location` message update."""
         replier, reply = None, None
         user_id = update['from']['id'] if 'from' in update else None
@@ -940,56 +943,56 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
                 )
         return
 
-    async def venue_message_handler(self, update, user_record):
+    async def venue_message_handler(self, update, user_record, language=None):
         """Handle `venue` message update."""
         logging.info(
             "A venue message update was received, "
             "but this handler does nothing yet."
         )
 
-    async def poll_message_handler(self, update, user_record):
+    async def poll_message_handler(self, update, user_record, language=None):
         """Handle `poll` message update."""
         logging.info(
             "A poll message update was received, "
             "but this handler does nothing yet."
         )
 
-    async def new_chat_members_message_handler(self, update, user_record):
+    async def new_chat_members_message_handler(self, update, user_record, language=None):
         """Handle `new_chat_members` message update."""
         logging.info(
             "A new_chat_members message update was received, "
             "but this handler does nothing yet."
         )
 
-    async def left_chat_member_message_handler(self, update, user_record):
+    async def left_chat_member_message_handler(self, update, user_record, language=None):
         """Handle `left_chat_member` message update."""
         logging.info(
             "A left_chat_member message update was received, "
             "but this handler does nothing yet."
         )
 
-    async def new_chat_title_message_handler(self, update, user_record):
+    async def new_chat_title_message_handler(self, update, user_record, language=None):
         """Handle `new_chat_title` message update."""
         logging.info(
             "A new_chat_title message update was received, "
             "but this handler does nothing yet."
         )
 
-    async def new_chat_photo_message_handler(self, update, user_record):
+    async def new_chat_photo_message_handler(self, update, user_record, language=None):
         """Handle `new_chat_photo` message update."""
         logging.info(
             "A new_chat_photo message update was received, "
             "but this handler does nothing yet."
         )
 
-    async def delete_chat_photo_message_handler(self, update, user_record):
+    async def delete_chat_photo_message_handler(self, update, user_record, language=None):
         """Handle `delete_chat_photo` message update."""
         logging.info(
             "A delete_chat_photo message update was received, "
             "but this handler does nothing yet."
         )
 
-    async def group_chat_created_message_handler(self, update, user_record):
+    async def group_chat_created_message_handler(self, update, user_record, language=None):
         """Handle `group_chat_created` message update."""
         logging.info(
             "A group_chat_created message update was received, "
@@ -1004,63 +1007,63 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
             "but this handler does nothing yet."
         )
 
-    async def channel_chat_created_message_handler(self, update, user_record):
+    async def channel_chat_created_message_handler(self, update, user_record, language=None):
         """Handle `channel_chat_created` message update."""
         logging.info(
             "A channel_chat_created message update was received, "
             "but this handler does nothing yet."
         )
 
-    async def migrate_to_chat_id_message_handler(self, update, user_record):
+    async def migrate_to_chat_id_message_handler(self, update, user_record, language=None):
         """Handle `migrate_to_chat_id` message update."""
         logging.info(
             "A migrate_to_chat_id message update was received, "
             "but this handler does nothing yet."
         )
 
-    async def migrate_from_chat_id_message_handler(self, update, user_record):
+    async def migrate_from_chat_id_message_handler(self, update, user_record, language=None):
         """Handle `migrate_from_chat_id` message update."""
         logging.info(
             "A migrate_from_chat_id message update was received, "
             "but this handler does nothing yet."
         )
 
-    async def pinned_message_message_handler(self, update, user_record):
+    async def pinned_message_message_handler(self, update, user_record, language=None):
         """Handle `pinned_message` message update."""
         logging.info(
             "A pinned_message message update was received, "
             "but this handler does nothing yet."
         )
 
-    async def invoice_message_handler(self, update, user_record):
+    async def invoice_message_handler(self, update, user_record, language=None):
         """Handle `invoice` message update."""
         logging.info(
             "A invoice message update was received, "
             "but this handler does nothing yet."
         )
 
-    async def successful_payment_message_handler(self, update, user_record):
+    async def successful_payment_message_handler(self, update, user_record, language=None):
         """Handle `successful_payment` message update."""
         logging.info(
             "A successful_payment message update was received, "
             "but this handler does nothing yet."
         )
 
-    async def connected_website_message_handler(self, update, user_record):
+    async def connected_website_message_handler(self, update, user_record, language=None):
         """Handle `connected_website` message update."""
         logging.info(
             "A connected_website message update was received, "
             "but this handler does nothing yet."
         )
 
-    async def passport_data_message_handler(self, update, user_record):
+    async def passport_data_message_handler(self, update, user_record, language=None):
         """Handle `passport_data` message update."""
         logging.info(
             "A passport_data message update was received, "
             "but this handler does nothing yet."
         )
 
-    async def dice_handler(self, update, user_record):
+    async def dice_handler(self, update, user_record, language=None):
         """Handle `dice` message update."""
         logging.info(
             "A dice message update was received, "
@@ -2013,7 +2016,7 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
         """
         self._allowed_during_maintenance.append(criterion)
 
-    async def handle_update_during_maintenance(self, update, user_record=None):
+    async def handle_update_during_maintenance(self, update, user_record=None, language=None):
         """Handle an update while bot is under maintenance.
 
         Handle all types of updates.
@@ -2106,7 +2109,7 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
         Decorate command handlers like this:
             ```
             @bot.command('/my_command', ['Button'], True, "My command", 'user')
-            async def command_handler(bot, update, user_record):
+            async def command_handler(bot, update, user_record, language):
                 return "Result"
             ```
         When a message text starts with `/command[@bot_name]`, or with an
@@ -2165,7 +2168,7 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
         command = command.strip('/ ').lower()
 
         def command_decorator(command_handler):
-            async def decorated_command_handler(bot, update, user_record):
+            async def decorated_command_handler(bot, update, user_record, language=None):
                 logging.info(
                     f"Command `{command}@{bot.name}` called by "
                     f"`{update['from'] if 'from' in update else update['chat']}`"
@@ -2223,7 +2226,7 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
                 return 'from' in update
 
             @bot.parser(custom_criteria, authorization_level='user')
-            async def text_parser(bot, update, user_record):
+            async def text_parser(bot, update, user_record, language):
                 return "Result"
             ```
         If condition evaluates True when run on a message text
@@ -2241,7 +2244,7 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
             )
 
         def parser_decorator(parser):
-            async def decorated_parser(bot, update, user_record):
+            async def decorated_parser(bot, update, user_record, language=None):
                 logging.info(
                     f"Text message update matching condition "
                     f"`{condition.__name__}@{bot.name}` from "
@@ -2310,7 +2313,7 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
             ```
             @bot.button('a_prefix:///', description="A button",
                         authorization_level='user')
-            async def button_handler(bot, update, user_record, data):
+            async def button_handler(bot, update, user_record, language, data):
                 return "Result"
             ```
         `separator` will be used to parse callback data received when a button
@@ -2325,7 +2328,7 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
             )
 
         def button_decorator(handler):
-            async def decorated_button_handler(bot, update, user_record):
+            async def decorated_button_handler(bot, update, user_record, language=None):
                 logging.info(
                     f"Button `{update['data']}`@{bot.name} pressed by "
                     f"`{update['from']}`"
@@ -2382,7 +2385,7 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
             )
 
         def query_decorator(handler):
-            async def decorated_query_handler(bot, update, user_record):
+            async def decorated_query_handler(bot, update, user_record, language=None):
                 logging.info(
                     f"Inline query matching condition "
                     f"`{condition.__name__}@{bot.name}` from "
@@ -2881,9 +2884,12 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
         for key, value in update.items():
             if key in self.routing_table:
                 user_record = self.get_user_record(update=value)
+                language = self.get_language(update=update,
+                                             user_record=user_record)
                 return await self.routing_table[key](
                     update=value,
-                    user_record=user_record
+                    user_record=user_record,
+                    language=language
                 )
         logging.error(f"Unknown type of update.\n{update}")
 

+ 320 - 0
davtelepot/messages.py

@@ -1,6 +1,24 @@
 """Default messages for bot functions."""
 
 default_admin_messages = {
+    'cancel': {
+        'button': {
+            'en': "↩️ Cancel",
+            'it': "↩️ Annulla"
+        },
+        'done': {
+            'en': "↩️ Operation cancelled",
+            'it': "↩️ Operazione annullata",
+        },
+        'lower': {
+            'en': "cancel",
+            'it': "annulla",
+        },
+    },
+    'confirm': {
+        'en': "🔄 Click again to confirm",
+        'it': "🔄 Clicka di nuovo per confermare",
+    },
     'db_command': {
         'description': {
             'en': "Ask for bot database via Telegram",
@@ -23,6 +41,12 @@ default_admin_messages = {
             'it': "Database inviato."
         }
     },
+    'error': {
+        'text': {
+            'en': "❌️ Error!",
+            'it': "❌️ Errore!"
+        },
+    },
     'errors_command': {
         'description': {
             'en': "Receive bot error log file, if set",
@@ -66,6 +90,302 @@ default_admin_messages = {
                   "L'ordine è cronologico, con i messaggi nuovi in alto."
         }
     },
+    'father_command': {
+        'back': {
+            'en': "↩️ Back",
+            'it': "↩️ Indietro",
+        },
+        'description': {
+            'en': "Edit the @BotFather commands",
+            'it': "Modifica i comandi con @BotFather",
+        },
+        'error': {
+            'en': "❌ Error! ❌",
+            'it': "❌ Errore! ❌",
+        },
+        'modes': [
+            {
+                'id': "get",
+                'name': {
+                    'en': "See",
+                    'it': "Consulta"
+                },
+                'symbol': "ℹ️",
+                'description': {
+                    'en': "See commands stored by @BotFather",
+                    'it': "Consulta i comandi salvati su @BotFather"
+                },
+            },
+            {
+                'id': "set",
+                'name': {
+                    'en': "Change",
+                    'it': "Modifica"
+                },
+                'symbol': "✏️",
+                'description': {
+                    'en': "Change commands stored by @BotFather",
+                    'it': "Modifica i comandi salvati su @BotFather"
+                },
+            },
+            {
+                'id': "settings",
+                'name': {
+                    'en': "Settings",
+                    'it': "Impostazioni"
+                },
+                'symbol': "⚙️",
+                'description': {
+                    'en': "Set commands to hide or to add",
+                    'it': "Imposta comandi da nascondere o aggiungere"
+                },
+            },
+        ],
+        'set': {
+            'button': {
+                'en': "⚠️ Set these commands 🔧",
+                'it': "⚠️ Imposta questi comandi 🔧",
+            },
+            'done': {
+                'en': "✅ Done!",
+                'it': "✅ Fatto!",
+            },
+            'error': {
+                'en': "Something went wrong 😕",
+                'it': "Qualcosa è andato storto 😕",
+            },
+            'header': {
+                'en': "✏️ <b>Change commands stored by @BotFather 🤖</b>",
+                'it': "✏️ <b>Modifica i comandi salvati su @BotFather 🤖</b>",
+            },
+            'legend': {
+                'en': "<b>Legend</b>\n"
+                      "✅ <i>Already stored</i>\n"
+                      "✏️ <i>New description</i>\n"
+                      "☑ <i>New command</i>\n"
+                      "❌ <i>Will be removed</i>",
+                'it': "<b>Legenda</b>\n"
+                      "✅ <i>Già presente</i>\n"
+                      "✏️ <i>Nuova descrizione</i>\n"
+                      "☑ <i>Nuovo comando</i>\n"
+                      "❌ <i>Comando da eliminare</i>",
+            },
+            'no_change': {
+                'en': "❌ No change detected",
+                'it': "❌ Nessuna modifica",
+            },
+        },
+        'settings': {
+            'browse_records': {
+                'en': "✏️ <b>Edit BotFather settings</b> ⚙️\n\n"
+                      "Select a record to edit.\n\n"
+                      "{commands_list}\n\n"
+                      "<i>Legend</i>\n"
+                      "➕ Added commands\n"
+                      "➖ Hidden commands\n\n"
+                      "Showing records from {record_interval[0]} to "
+                      "{record_interval[1]} of {record_interval[2]}",
+                'it': "✏️ <b>Modifica impostazioni di BotFather</b> ⚙\n\n️"
+                      "Seleziona un'impostazione da modificare.\n\n"
+                      "{commands_list}\n\n"
+                      "<i>Legenda</i>\n"
+                      "➕ Comandi aggiunti\n"
+                      "➖ Comandi nascosti\n\n"
+                      "Record da {record_interval[0]} a "
+                      "{record_interval[1]} di {record_interval[2]}",
+            },
+            'modes': {
+                'add': {
+                    'add': {
+                        'done': {
+                            'en': "➕️️ <b>Added additional command</b>\n\n"
+                                  "Command: {command}\n"
+                                  "Description: {description}",
+                            'it': "➕️️ <b>Inserito comando aggiuntivo</b>\n\n"
+                                  "Comando: {command}\n"
+                                  "Descrizione: {description}",
+                        },
+                        'popup': {
+                            'en': "Write the command to add",
+                            'it': "Scrivimi il comando da aggiungere",
+                        },
+                        'text': {
+                            'en': "Write the command to add or /cancel this operation",
+                            'it': "Scrivimi il comando da aggiungere o /annulla",
+                        },
+                    },
+                    'description': {
+                        'en': "Add command to default list",
+                        'it': "Aggiungi un comando dalla lista autogenerata"
+                    },
+                    'edit': {
+                        'done': {
+                            'en': "✏️ <b>Edited additional command</b>\n\n"
+                                  "Command: {command}\n"
+                                  "Description: {description}",
+                            'it': "✏️ <b>Comando da nascondere modificato</b>\n\n"
+                                  "Comando: {command}\n"
+                                  "Descrizione: {description}",
+                        },
+                    },
+                    'error': {
+                        'description_too_long': {
+                            'en': "<b>Description is too long</b>\n\n"
+                                  "Description length must be 3-256 chars.",
+                            'it': "<b>Descrizione troppo lunga</b>\n\n"
+                                  "La descrizione deve essere di 3-256 caratteri.",
+                        },
+                        'duplicate_record': {
+                            'en': "<b>Duplicate record</b>\n\n"
+                                  "Command is already being added to default "
+                                  "output. Edit that record if you need to.",
+                            'it': "<b>Record già presente</b>\n\n"
+                                  "Questo comando è già aggiunto a quelli di "
+                                  "default. Modifica il record già presente se "
+                                  "necessario.",
+                        },
+                        'missing_description': {
+                            'en': "<b>Missing description</b>\n\n"
+                                  "Additional commands must have a description "
+                                  "(3-256 chars).",
+                            'it': "<b>Descrizione mancante</b>\n\n"
+                                  "I comandi aggiuntivi devono avere una "
+                                  "descrizione di 3-256 caratteri.",
+                        },
+                        'unhandled_exception': {
+                            'en': "❌ <b>Unhandled exception </b> ⚠️",
+                            'it': "❌ <b>Errore imprevisto </b> ⚠️",
+                        },
+                    },
+                    'name': {
+                        'en': "Add",
+                        'it': "Aggiungi"
+                    },
+                    'symbol': "➕️",
+                },
+                'hide': {
+                    'add': {
+                        'done': {
+                            'en': "➖ <b>Added hidden command</b>\n\n"
+                                  "Command: {command}\n",
+                            'it': "➖ <b>Comando da nascondere aggiunto</b>"
+                                  "Comando: {command}\n",
+                        },
+                        'popup': {
+                            'en': "Write the command to hide",
+                            'it': "Scrivimi il comando da nascondere",
+                        },
+                        'text': {
+                            'en': "Write the command to hide or /cancel this operation",
+                            'it': "Scrivimi il comando da nascondere o /annulla",
+                        }
+                    },
+                    'description': {
+                        'en': "Hide command from default list",
+                        'it': "Nascondi un comando dalla lista autogenerata"
+                    },
+                    'edit': {
+                        'done': {
+                            'en': "✏️ <b>Edited hidden command</b>\n\n"
+                                  "Command: {command}\n"
+                                  "Description: {description}",
+                            'it': "✏️ <b>Comando da nascondere modificato</b>\n\n"
+                                  "Comando: {command}\n"
+                                  "Descrizione: {description}",
+                        },
+                    },
+                    'name': {
+                        'en': "Hide",
+                        'it': "Nascondi"
+                    },
+                    'symbol': "➖️",
+                },
+                'edit': {
+                    'button': {
+                        'en': "✏️ Edit record",
+                        'it': "✏️ Modifica record"
+                    },
+                    'description': {
+                        'en': "Edit added or hidden commands",
+                        'it': "Modifica i comandi aggiunti o nascosti"
+                    },
+                    'edit': {
+                        'popup': {
+                            'en': "Write the new description",
+                            'it': "Scrivimi la nuova descrizione",
+                        },
+                        'text': {
+                            'en': "Write the new description for command "
+                                  "{command} or /cancel",
+                            'it': "Scrivimi la nuova descrizione per il  "
+                                  "comando {command} o /annulla",
+                        },
+                        'done': {
+                            'en': "✏️ Edit succeeded ✅\n\n"
+                                  "Command: {command}\n"""
+                                  "Description: {description}",
+                            'it': "✏️ Modifica completata ✅\n\n"
+                                  "Comando: {command}\n"""
+                                  "Descrizione: {description}",
+                        }
+                    },
+                    'name': {
+                        'en': "Edit",
+                        'it': "Modifica"
+                    },
+                    'panel': {
+                        'delete': {
+                            'button': {
+                                'en': "❌ Delete record",
+                                'it': "❌ Elimina record",
+                            },
+                            'done': {
+                                'popup': {
+                                    'en': "Record deleted ✅",
+                                    'it': "Record eliminato ✅",
+                                },
+                                'text': {
+                                    'en': "Record deleted ✅",
+                                    'it': "Record eliminato ✅",
+                                },
+                            },
+                        },
+                        'edit_description': {
+                            'button': {
+                                'en': "✏️ Edit description",
+                                'it': "✏️ Modifica descrizione",
+                            },
+                        },
+                        'text': {
+                            'en': "✏️ Edit record ✅\n\n"
+                                  "Command: {command}\n"""
+                                  "Description: {description}",
+                            'it': "✏️ Modifica record\n\n"
+                                  "Comando: {command}\n"""
+                                  "Descrizione: {description}",
+                        },
+                    },
+                    'symbol': "✏️",
+                },
+            },
+            'panel': {
+                'en': "🤖 <b>@BotFather settings</b> ⚙️\n\n"
+                      "➕ <i>Additional commands</i>\n"
+                      "{additional_commands}\n\n"
+                      "➖ <i>Hidden commands</i>\n"
+                      "{hidden_commands}",
+                'it': "⚙️ <b>Impostazioni di @BotFather</b> 🤖\n\n"
+                      "➕ <i>Comandi aggiuntivi</i>\n"
+                      "{additional_commands}\n\n"
+                      "➖ <i>Comandi nascosti</i>\n"
+                      "{hidden_commands}",
+            },
+        },
+        'title': {
+            'en': "🤖 <b>BotFather</b>",
+            'it': "🤖 <b>BotFather</b>",
+        },
+    },
     'log_command': {
         'description': {
             'en': "Receive bot log file, if set",

+ 5 - 1
davtelepot/utilities.py

@@ -18,6 +18,8 @@ import time
 from difflib import SequenceMatcher
 
 # Third party modules
+from typing import Union
+
 import aiohttp
 from aiohttp import web
 from bs4 import BeautifulSoup
@@ -703,7 +705,7 @@ class Confirmable():
 
     CONFIRM_TIMEDELTA = datetime.timedelta(seconds=10)
 
-    def __init__(self, confirm_timedelta=None):
+    def __init__(self, confirm_timedelta: Union[datetime.timedelta, int] = None):
         """Instantiate Confirmable instance.
 
         If `confirm_timedelta` is not passed,
@@ -711,6 +713,8 @@ class Confirmable():
         """
         if confirm_timedelta is None:
             confirm_timedelta = self.__class__.CONFIRM_TIMEDELTA
+        elif type(confirm_timedelta) is int:
+            confirm_timedelta = datetime.timedelta(seconds=confirm_timedelta)
         self.set_confirm_timedelta(confirm_timedelta)
         self._confirm_datetimes = {}
 

Энэ ялгаанд хэт олон файл өөрчлөгдсөн тул зарим файлыг харуулаагүй болно