Queer European MD passionate about IT
Forráskód Böngészése

Maintenance system implemented

While under maintenance, route updates in a special way.
Davte 5 éve
szülő
commit
2bb0ef9436
1 módosított fájl, 126 hozzáadás és 0 törlés
  1. 126 0
      davtelepot/bot.py

+ 126 - 0
davtelepot/bot.py

@@ -30,6 +30,8 @@ class Bot(TelegramBot):
     local_host = 'localhost'
     port = 3000
     final_state = 0
+    _maintenance_message = ("I am currently under maintenance!\n"
+                            "Please retry later...")
 
     def __init__(
         self, token, hostname='', certificate=None, max_connections=40,
@@ -58,6 +60,9 @@ class Bot(TelegramBot):
         self._session_token = get_secure_key(length=10)
         self._name = None
         self._telegram_id = None
+        self._under_maintenance = False
+        self._allowed_during_maintenance = []
+        self._maintenance_message = None
         return
 
     @property
@@ -137,6 +142,122 @@ class Bot(TelegramBot):
         """
         return self._offset
 
+    @property
+    def under_maintenance(self):
+        """Return True if bot is under maintenance.
+
+        While under maintenance, bot will reply `self.maintenance_message` to
+            any update, except those which `self.is_allowed_during_maintenance`
+            returns True for.
+        """
+        return self._under_maintenance
+
+    @property
+    def allowed_during_maintenance(self):
+        """Return the list of criteria to allow an update during maintenance.
+
+        If any of this criteria returns True on an update, that update will be
+            handled even during maintenance.
+        """
+        return self._allowed_during_maintenance
+
+    @property
+    def maintenance_message(self):
+        """Message to be returned if bot is under maintenance.
+
+        If instance message is not set, class message is returned.
+        """
+        if self._maintenance_message:
+            return self._maintenance_message
+        if self.__class__.maintenance_message:
+            return self.__class__._maintenance_message
+        return ("I am currently under maintenance!\n"
+                "Please retry later...")
+
+    @classmethod
+    def set_class_maintenance_message(cls, maintenance_message):
+        """Set class maintenance message.
+
+        It will be returned if bot is under maintenance, unless and instance
+            `_maintenance_message` is set.
+        """
+        cls._maintenance_message = maintenance_message
+
+    def set_maintenance_message(self, maintenance_message):
+        """Set instance maintenance message.
+
+        It will be returned if bot is under maintenance.
+        If instance message is None, default class message is used.
+        """
+        self._maintenance_message = maintenance_message
+
+    def change_maintenance_status(self, maintenance_message=None, status=None):
+        """Put the bot under maintenance or end it.
+
+        While in maintenance, bot will reply to users with maintenance_message
+            with a few exceptions.
+        If status is not set, it is by default the opposite of the current one.
+        Optionally, `maintenance_message` may be set.
+        """
+        if status is None:
+            status = not self.under_maintenance
+        assert type(status) is bool, "status must be a boolean value!"
+        self._under_maintenance = status
+        if maintenance_message:
+            self.set_maintenance_message(maintenance_message)
+        return self._under_maintenance  # Return new status
+
+    def is_allowed_during_maintenance(self, update):
+        """Return True if update is allowed during maintenance.
+
+        An update is allowed if any of the criteria in
+            `self.allowed_during_maintenance` returns True called on it.
+        """
+        for criterion in self.allowed_during_maintenance:
+            if criterion(update):
+                return True
+        return False
+
+    def allow_during_maintenance(self, criterion):
+        """Add a criterion to allow certain updates during maintenance.
+
+        `criterion` must be a function taking a Telegram `update` dictionary
+            and returning a boolean.
+        ```# Example of criterion
+        def allow_text_messages(update):
+            if 'message' in update and 'text' in update['message']:
+                return True
+            return False
+        ```
+        """
+        self._allowed_during_maintenance.append(criterion)
+
+    async def handle_update_during_maintenance(self, update):
+        """Handle an update while bot is under maintenance.
+
+        Handle all types of updates.
+        """
+        if (
+            'message' in update
+            and 'chat' in update['message']
+            and update['message']['chat']['id'] > 0
+        ):
+            return await self.send_message(
+                text=self.maintenance_message,
+                update=update['message'],
+                reply_to_update=True
+            )
+        elif 'callback_query' in update:
+            pass
+        elif 'inline_query' in update:
+            await self.answer_inline_query(
+                update['inline_query']['id'],
+                self.maintenance_message,
+                cache_time=30,
+                is_personal=False,
+            )
+        return
+
     async def webhook_feeder(self, request):
         """Handle incoming HTTP `request`s.
 
@@ -269,6 +390,11 @@ class Bot(TelegramBot):
             text=update['message']['text']
         )
         return
+        if (
+            self.under_maintenance
+            and not self.is_allowed_during_maintenance(update)
+        ):
+            return await self.handle_update_during_maintenance(update)
 
     @classmethod
     async def start_app(cls):