Queer European MD passionate about IT
Browse Source

Identify edited methods (new or deprecated parameters) in addition to new methods.

Davte 3 years ago
parent
commit
a3cc676432
2 changed files with 169 additions and 35 deletions
  1. 72 0
      davtelepot/api.py
  2. 97 35
      davtelepot/api_helper.py

+ 72 - 0
davtelepot/api.py

@@ -1464,3 +1464,75 @@ class TelegramBot:
             'setStickerSetThumb',
             parameters=locals()
         )
+
+    async def logOut(self):
+        """Log out from the cloud Bot API server.
+
+        Use this method to log out from the cloud Bot API server
+        before launching the bot locally.
+        You must log out the bot before running it locally, otherwise there
+        is no guarantee that the bot will receive updates.
+        After a successful call, you can immediately log in on a local server,
+        but will not be able to log in back to the cloud Bot API server
+        for 10 minutes.
+        Returns True on success. Requires no parameters.
+        See https://core.telegram.org/bots/api#logout for details.
+        """
+        return await self.api_request(
+            'logOut',
+            parameters=locals()
+        )
+
+    async def close(self):
+        """Close bot instance in local server.
+
+        Use this method to close the bot instance before moving it from one
+        local server to another.
+        You need to delete the webhook before calling this method to ensure
+        that the bot isn't launched again after server restart.
+        The method will return error 429 in the first 10 minutes after the
+        bot is launched. Returns True on success.
+        Requires no parameters.
+        See https://core.telegram.org/bots/api#close for details.
+        """
+        return await self.api_request(
+            'close',
+            parameters=locals()
+        )
+
+    async def copyMessage(self, chat_id: Union[int, str],
+                          from_chat_id: Union[int, str],
+                          message_id: int,
+                          caption: str = None,
+                          parse_mode: str = None,
+                          caption_entities: list = None,
+                          disable_notification: bool = None,
+                          reply_to_message_id: int = None,
+                          allow_sending_without_reply: bool = None,
+                          reply_markup=None):
+        """Use this method to copy messages of any kind.
+
+        The method is analogous to the method forwardMessages, but the copied
+        message doesn't have a link to the original message.
+        Returns the MessageId of the sent message on success.
+        See https://core.telegram.org/bots/api#copymessage for details.
+        """
+        return await self.api_request(
+            'copyMessage',
+            parameters=locals()
+        )
+
+    async def unpinAllChatMessages(self, chat_id: Union[int, str]):
+        """Use this method to clear the list of pinned messages in a chat.
+
+        If the chat is not a private chat, the bot must be an administrator
+        in the chat for this to work and must have the 'can_pin_messages'
+        admin right in a supergroup or 'can_edit_messages' admin right in a
+        channel.
+        Returns True on success.
+        See https://core.telegram.org/bots/api#unpinallchatmessages for details.
+        """
+        return await self.api_request(
+            'unpinAllChatMessages',
+            parameters=locals()
+        )

+ 97 - 35
davtelepot/api_helper.py

@@ -3,9 +3,13 @@
 # Standard library modules
 import argparse
 import asyncio
+import inspect
 import logging
 
 # Third party modules
+import os
+from typing import List
+
 import aiohttp
 from bs4 import BeautifulSoup
 
@@ -52,7 +56,7 @@ class TelegramApiMethod(object):
         return self._parameters
 
     @property
-    def parameters_with_types(self):
+    def parameters_with_types(self) -> List[str]:
         return [
             f"{parameter['name']}: {parameter['type']}"
             for parameter in self._parameters
@@ -101,22 +105,30 @@ class TelegramApiMethod(object):
 async def print_api_methods(loop=None,
                             filename=None,
                             print_all=False,
-                            output_file=None):
+                            output_file=None,
+                            input_file=None):
     """Get information from Telegram bot API web page."""
     if loop is None:
         loop = asyncio.get_event_loop()
     implemented_methods = dir(TelegramBot)
-    async with aiohttp.ClientSession(
-        loop=loop,
-        timeout=aiohttp.ClientTimeout(
-            total=100
-        )
-    ) as session:
-        async with session.get(
-                api_url
-        ) as response:
+    if input_file is None or not os.path.isfile(input_file):
+        async with aiohttp.ClientSession(
+            loop=loop,
+            timeout=aiohttp.ClientTimeout(
+                total=100
+            )
+        ) as session:
+            async with session.get(
+                    api_url
+            ) as response:
+                web_page = BeautifulSoup(
+                    await response.text(),
+                    "html.parser"
+                )
+    else:
+        with open(input_file, 'r') as local_web_page:
             web_page = BeautifulSoup(
-                await response.text(),
+                ''.join(local_web_page.readlines()),
                 "html.parser"
             )
     if filename is not None:
@@ -146,40 +158,84 @@ async def print_api_methods(loop=None,
                 )
             )
     new_line = '\n'
+    new_methods = []
+    edited_methods = []
+    for method in methods:
+        if print_all or method.name not in implemented_methods:
+            new_methods.append(method)
+        else:
+            parameters = set(parameter['name'] for parameter in method.parameters)
+            implemented_parameters = set(
+                parameter.strip('_')  # Parameter `type` becomes `type_` in python
+                for parameter in inspect.signature(
+                    getattr(TelegramBot,
+                            method.name)
+                ).parameters.keys()
+                if parameter != 'self'
+            )
+            new_parameters = parameters - implemented_parameters
+            deprecated_parameters = implemented_parameters - parameters
+            if new_parameters or deprecated_parameters:
+                edited_methods.append(
+                    dict(
+                        name=method.name,
+                        new_parameters=new_parameters,
+                        deprecated_parameters=deprecated_parameters
+                    )
+                )
     if output_file:
         with open(output_file, 'w') as file:
-            file.write(
-                "from typing import List, Union\n"
-                "from davtelepot.api import TelegramBot\n"
-                "self = TelegramBot('fake_token')\n\n\n"
-            )
+            if new_methods:
+                file.write(
+                    "from typing import List, Union\n"
+                    "from davtelepot.api import TelegramBot\n\n\n"
+                    "# noinspection PyPep8Naming\n"
+                    "class Bot(TelegramBot):\n\n"
+                )
             file.writelines(
-                f"async def {method.name}("
-                f"{', '.join(method.parameters_with_types)}"
-                "):\n"
-                "    \"\"\""
-                f"{method.description.replace(new_line, new_line + ' ' * 4)}\n"
-                "    See https://core.telegram.org/bots/api#"
-                f"{method.name.lower()} for details.\n"
-                "    \"\"\"\n"
-                "    return await self.api_request(\n"
-                f"        '{method.name}',\n"
-                "        parameters=locals()\n"
-                "    )\n\n\n"
-                for method in methods
-                if print_all or method.name not in implemented_methods
+                f"    async def {method.name}("
+                f"{', '.join(['self'] + method.parameters_with_types)}"
+                f"):\n"
+                f"        \"\"\""
+                f"    {method.description.replace(new_line, new_line + ' ' * 4)}\n"
+                f"        See https://core.telegram.org/bots/api#"
+                f"    {method.name.lower()} for details.\n"
+                f"        \"\"\"\n"
+                f"        return await self.api_request(\n"
+                f"            '{method.name}',\n"
+                f"            parameters=locals()\n"
+                f"        )\n\n"
+                for method in new_methods
             )
+            if edited_methods:
+                file.write('\n# === EDITED METHODS ===\n')
+            for method in edited_methods:
+                file.write(f'\n"""{method["name"]}\n')
+                if method['new_parameters']:
+                    file.write("    New parameters: "
+                               + ", ".join(method['new_parameters'])
+                               + "\n")
+                if method['deprecated_parameters']:
+                    file.write("    Deprecated parameters: "
+                               + ", ".join(method['deprecated_parameters'])
+                               + "\n")
+                file.write('"""\n')
     else:
         print(
             '\n'.join(
                 f"NAME\n\t{method.name}\n"
-                f"PARAMETERS\n\t{', '.join(method.parameters_with_types)}\n"
+                f"PARAMETERS\n\t{', '.join(['self'] + method.parameters_with_types)}\n"
                 f"DESCRIPTION\n\t{method.description}\n"
                 f"TABLE\n\t{method.print_parameters_table()}\n\n"
-                for method in methods
-                if print_all or method.name not in implemented_methods
+                for method in new_methods
             )
         )
+        for method in edited_methods:
+            print(method['name'])
+            if method['new_parameters']:
+                print("\tNew parameters: " + ", ".join(method['new_parameters']))
+            if method['deprecated_parameters']:
+                print("\tDeprecated parameters: " + ", ".join(method['deprecated_parameters']))
 
 
 def main():
@@ -202,16 +258,22 @@ def main():
                             default=None,
                             required=False,
                             help='File path to store methods implementation')
+    cli_parser.add_argument('--in', '--input', '-i', type=str,
+                            default=None,
+                            required=False,
+                            help='File path to read Telegram API web page')
     cli_arguments = vars(cli_parser.parse_args())
     filename = cli_arguments['file']
     print_all = cli_arguments['all']
     output_file = cli_arguments['out']
+    input_file = cli_arguments['in']
     loop = asyncio.get_event_loop()
     loop.run_until_complete(
         print_api_methods(loop=loop,
                           filename=filename,
                           print_all=print_all,
-                          output_file=output_file)
+                          output_file=output_file,
+                          input_file=input_file)
     )
     logging.info("Done!")