Queer European MD passionate about IT
Browse Source

Document handlers implemented

Davte 2 years ago
parent
commit
e481623a75
3 changed files with 112 additions and 6 deletions
  1. 1 1
      davtelepot/__init__.py
  2. 109 4
      davtelepot/bot.py
  3. 2 1
      update_package.sh

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

+ 109 - 4
davtelepot/bot.py

@@ -193,6 +193,8 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
         self.messages['reply_keyboard_buttons'] = dict()
         self._unknown_command_message = None
         self.text_message_parsers = OrderedDict()
+        self.document_handlers = OrderedDict()
+        self.individual_document_message_handlers = dict()
         # Support for /help command
         self.messages['help_sections'] = OrderedDict()
         # Handle location messages
@@ -881,10 +883,38 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
 
     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."
-        )
+        replier, reply = None, None
+        user_id = update['from']['id'] if 'from' in update else None
+        if user_id in self.individual_document_message_handlers:
+            replier = self.individual_document_message_handlers[user_id]
+            del self.individual_document_message_handlers[user_id]
+        else:
+            for check_function, handler in self.document_handlers.items():
+                if check_function(update):
+                    replier = handler['handler']
+                    break
+        if replier:
+            reply = await replier(
+                bot=self,
+                **{
+                    name: argument
+                    for name, argument in locals().items()
+                    if name in inspect.signature(
+                        replier
+                    ).parameters
+                }
+            )
+        if reply:
+            if type(reply) is str:
+                reply = dict(text=reply)
+            try:
+                return await self.reply(update=update, **reply)
+            except Exception as e:
+                logging.error(
+                    f"Failed to handle document:\n{e}",
+                    exc_info=True
+                )
+        return
 
     async def animation_message_handler(self, update, user_record, language=None):
         """Handle `animation` message update."""
@@ -2410,6 +2440,47 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
             )
         return parser_decorator
 
+    def document_handler(self, condition, description='',
+                         authorization_level='admin'):
+        """Decorator: define a handler for document updates matching `condition`.
+
+        You may provide a description and a minimum authorization level.
+        The first handler matching condition is called (other matching handlers
+            are ignored).
+        """
+        if not callable(condition):
+            raise TypeError(
+                f'Condition {condition.__name__} is not a callable'
+            )
+
+        def parser_decorator(parser):
+            async def decorated_parser(bot, update, user_record, language=None):
+                logging.info(
+                    f"Document update matching condition "
+                    f"`{condition.__name__}@{bot.name}` from "
+                    f"`{update['from'] if 'from' in update else update['chat']}`"
+                )
+                if bot.authorization_function(
+                    update=update,
+                    user_record=user_record,
+                    authorization_level=authorization_level
+                ):
+                    # Pass supported arguments from locals() to parser
+                    return await parser(
+                        **{
+                            name: arg
+                            for name, arg in locals().items()
+                            if name in inspect.signature(parser).parameters
+                        }
+                    )
+                return dict(text=bot.authorization_denied_message)
+            self.document_handlers[condition] = dict(
+                handler=decorated_parser,
+                description=description,
+                authorization_level=authorization_level,
+            )
+        return parser_decorator
+
     def set_command(self, command, handler, aliases=None,
                     reply_keyboard_button=None, show_in_keyboard=False,
                     description="",
@@ -2671,6 +2742,40 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
             del self.individual_location_handlers[identifier]
         return
 
+    def set_individual_document_handler(self, handler,
+                                        update=None, user_id=None):
+        """Set a custom document handler for the user.
+
+        Any document update from the user will be handled by this custom
+            handler instead of default handlers for documents.
+        Custom handlers last one single use, but they can call this method and
+            set themselves as next custom document handler.
+        """
+        identifier = self.get_user_identifier(
+            user_id=user_id,
+            update=update
+        )
+        assert callable(handler), (f"Handler `{handler.name}` is not "
+                                   "callable. Custom document handler "
+                                   "could not be set.")
+        self.individual_document_message_handlers[identifier] = handler
+        return
+
+    def remove_individual_document_handler(self,
+                                           update=None, user_id=None):
+        """Remove a custom document handler for the user.
+
+        Any document update from the user will be handled by default
+            handlers for documents.
+        """
+        identifier = self.get_user_identifier(
+            user_id=user_id,
+            update=update
+        )
+        if identifier in self.individual_document_message_handlers:
+            del self.individual_document_message_handlers[identifier]
+        return
+
     def set_individual_voice_handler(self, handler,
                                      update=None, user_id=None):
         """Set a custom voice message handler for the user.

+ 2 - 1
update_package.sh

@@ -1,7 +1,8 @@
 #!/bin/bash
 
 # Get current directory
-this_script_directory=$(cd `dirname $0` && pwd)
+this_script_directory=$(cd "$(dirname "$0")" && pwd)
+packenv="";
 
 # Python virtual environment directory: packenv variable in my_config.sh
 source $this_script_directory/my_config.sh;