Queer European MD passionate about IT
Davte пре 4 година
родитељ
комит
06d3569fbd
4 измењених фајлова са 38 додато и 29 уклоњено
  1. 1 1
      davtelepot/__init__.py
  2. 18 17
      davtelepot/api.py
  3. 16 8
      davtelepot/bot.py
  4. 3 3
      davtelepot/database.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.14"
+__version__ = "2.4.15"
 __maintainer__ = "Davide Testa"
 __contact__ = "t.me/davte"
 

+ 18 - 17
davtelepot/api.py

@@ -18,7 +18,7 @@ from aiohttp import web
 class TelegramError(Exception):
     """Telegram API exceptions class."""
 
-    def __init__(self, error_code=0, description=None, ok=False):
+    def __init__(self, error_code=0, description=None):
         """Get an error response and return corresponding Exception."""
         self._code = error_code
         if description is None:
@@ -38,7 +38,9 @@ class TelegramError(Exception):
         return f"Error {self.code}: {self._description}"
 
 
-class TelegramBot(object):
+# This class needs to mirror Telegram API, so camelCase method are needed
+# noinspection PyPep8Naming
+class TelegramBot:
     """Provide python method having the same signature as Telegram API methods.
 
     All mirrored methods are camelCase.
@@ -65,12 +67,13 @@ class TelegramBot(object):
         self._token = token
         self.sessions = dict()
         self._flood_wait = 0
-        self.last_sending_time = dict(
-            absolute=(
+        self.last_sending_time = {
+            'absolute': (
                 datetime.datetime.now()
                 - self.absolute_cooldown_timedelta
-            )
-        )
+            ),
+            0: []  # Each `telegram_id` key has a list of `datetime.datetime` as value
+        }
 
     @property
     def token(self):
@@ -139,14 +142,16 @@ class TelegramBot(object):
         return response['result']
 
     @staticmethod
-    def adapt_parameters(parameters, exclude=[]):
+    def adapt_parameters(parameters, exclude=None):
         """Build a aiohttp.FormData object from given `paramters`.
 
         Exclude `self`, empty values and parameters in `exclude` list.
         Cast integers to string to avoid TypeError during json serialization.
         """
+        if exclude is None:
+            exclude = []
         exclude.append('self')
-        # quote_fields must be set to False, otherwise filenames cause troubles
+        # quote_fields must be set to False, otherwise some file names cause troubles
         data = aiohttp.FormData(quote_fields=False)
         for key, value in parameters.items():
             if not (key in exclude or value is None):
@@ -260,13 +265,17 @@ class TelegramBot(object):
         self.last_sending_time['absolute'] = now()
         return
 
-    async def api_request(self, method, parameters={}, exclude=[]):
+    async def api_request(self, method, parameters=None, exclude=None):
         """Return the result of a Telegram bot API request, or an Exception.
 
         Opened sessions will be used more than one time (if appropriate) and
             will be closed on `Bot.app.cleanup`.
         Result may be a Telegram API json response, None, or Exception.
         """
+        if exclude is None:
+            exclude = []
+        if parameters is None:
+            parameters = {}
         response_object = None
         session, session_must_be_closed = self.get_session(method)
         # Prevent Telegram flood control for all methodsd having a `chat_id`
@@ -343,14 +352,6 @@ class TelegramBot(object):
 
         See https://core.telegram.org/bots/api#setwebhook for details.
         """
-        if url is None:
-            url = self.webhook_url
-        if allowed_updates is None:
-            allowed_updates = self.allowed_updates
-        if max_connections is None:
-            max_connections = self.max_connections
-        if certificate is None:
-            certificate = self.certificate
         if type(certificate) is str:
             try:
                 certificate = dict(

+ 16 - 8
davtelepot/bot.py

@@ -1,6 +1,6 @@
 """Provide a simple Bot object, mirroring Telegram API methods.
 
-camelCase methods mirror API directly, while snake_case ones act as middlewares
+camelCase methods mirror API directly, while snake_case ones act as middleware
     someway.
 
 Usage
@@ -58,6 +58,8 @@ from .utilities import (
 logging.getLogger('aiohttp').setLevel(logging.WARNING)
 
 
+# Some methods are not implemented yet: that's the reason behind the following statement
+# noinspection PyUnusedLocal,PyMethodMayBeStatic,PyMethodMayBeStatic
 class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
     """Simple Bot object, providing methods corresponding to Telegram bot API.
 
@@ -579,7 +581,7 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
                 break
         if not results:
             results = self.default_inline_query_answer
-        if type(results) is dict and 'answer' in results:
+        if isinstance(results, dict) and 'answer' in results:
             if 'switch_pm_text' in results:
                 switch_pm_text = results['switch_pm_text']
             if 'switch_pm_parameter' in results:
@@ -1010,6 +1012,7 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
             "but this handler does nothing yet."
         )
 
+    # noinspection SpellCheckingInspection
     @staticmethod
     def split_message_text(text, limit=None, parse_mode='HTML'):
         r"""Split text if it hits telegram limits for text messages.
@@ -1076,7 +1079,7 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
             method = self.send_voice
         if method is not None:
             return await method(update=update, *args, **kwargs)
-        raise Exception("Unsopported keyword arguments for `Bot().reply`.")
+        raise Exception("Unsupported keyword arguments for `Bot().reply`.")
 
     async def send_message(self, chat_id=None, text=None,
                            parse_mode='HTML',
@@ -1121,7 +1124,7 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
             return
         parse_mode = str(parse_mode)
         if isinstance(text, dict) and chat_id > 0:
-            if user_record is None :
+            if user_record is None:
                 user_record = self.db['users'].find_one(telegram_id=chat_id)
             text = self.get_message(
                 update=update,
@@ -1255,7 +1258,6 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
         Set `disable_notification` to True to avoid disturbing recipient.
         Pass the `update` to be forwarded or its identifier (`from_chat_id` and
             `message_id`).
-            @type message_id: int
         """
         if from_chat_id is None or message_id is None:
             message_identifier = self.get_message_identifier(update)
@@ -1669,7 +1671,7 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
             set to True, use file_id (it is faster and recommended).
         `document_path` may contain `{path}`: it will be replaced by
             `self.path`.
-        `document_name` diplayed to Telegram may differ from actual document
+        `document_name` displayed to Telegram may differ from actual document
             name if this parameter is set.
         """
         already_sent = False
@@ -1785,7 +1787,7 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
         return sent_update
 
     async def download_file(self, file_id,
-                            file_name=None, mime_type=None, path=None):
+                            file_name=None, path=None):
         """Given a telegram `file_id`, download the related file.
 
         Telegram may not preserve the original file name and MIME type: the
@@ -1998,7 +2000,7 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
 
         Decorate command handlers like this:
             ```
-            @bot.command('/mycommand', ['Button'], True, "My command", 'user')
+            @bot.command('/my_command', ['Button'], True, "My command", 'user')
             async def command_handler(bot, update, user_record):
                 return "Result"
             ```
@@ -2573,6 +2575,12 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
             return
         if allowed_updates is None:
             allowed_updates = []
+        if certificate is None:
+            certificate = self.certificate
+        if max_connections is None:
+            max_connections = self.max_connections
+        if url is None:
+            url = self.webhook_url
         webhook_was_set = await self.setWebhook(
             url=url, certificate=certificate, max_connections=max_connections,
             allowed_updates=allowed_updates

+ 3 - 3
davtelepot/database.py

@@ -22,7 +22,7 @@ class ObjectWithDatabase(object):
         ```
     """
 
-    def __init__(self, database_url=None):
+    def __init__(self, database_url: str = None):
         """Instantiate object and open connection with database."""
         if database_url is None:
             database_url = 'database.db'
@@ -41,12 +41,12 @@ class ObjectWithDatabase(object):
             logging.error(f"{e}")
 
     @property
-    def db_url(self):
+    def db_url(self) -> str:
         """Return complete path to database."""
         return self._database_url
 
     @property
-    def db(self):
+    def db(self) -> dataset.Database:
         """Return the dataset.Database instance related to `self`."""
         return self._database