From 91e377aacc92cde4fd33ed1f490105f6c8751447 Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Sun, 23 Jun 2019 01:30:38 +0200 Subject: [PATCH 1/6] Add ARTICLE_TITLE_EMPTY error --- compiler/error/source/400_BAD_REQUEST.tsv | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/error/source/400_BAD_REQUEST.tsv b/compiler/error/source/400_BAD_REQUEST.tsv index 43bade44..f44f5cb2 100644 --- a/compiler/error/source/400_BAD_REQUEST.tsv +++ b/compiler/error/source/400_BAD_REQUEST.tsv @@ -107,4 +107,5 @@ LINK_NOT_MODIFIED The chat link was not modified because you tried to link to th BROADCAST_ID_INVALID The channel is invalid MEGAGROUP_ID_INVALID The supergroup is invalid BUTTON_DATA_INVALID The button callback data contains invalid data or exceeds 64 bytes -START_PARAM_INVALID The start parameter is invalid \ No newline at end of file +START_PARAM_INVALID The start parameter is invalid +ARTICLE_TITLE_EMPTY The article title is empty \ No newline at end of file From 267797051c42a9f75eec8b56bc2dcc8509e594f4 Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Sun, 23 Jun 2019 01:30:50 +0200 Subject: [PATCH 2/6] Fix broken link --- docs/source/intro/quickstart.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/intro/quickstart.rst b/docs/source/intro/quickstart.rst index a7a7e377..13f646d1 100644 --- a/docs/source/intro/quickstart.rst +++ b/docs/source/intro/quickstart.rst @@ -46,4 +46,4 @@ In the next few pages of the introduction, we'll take a much more in-depth look Feeling eager to continue? You can take a shortcut to :doc:`Calling Methods <../start/invoking>` and come back later to learn some more details. -.. _community: //t.me/Pyrogram +.. _community: https://t.me/Pyrogram From bf71989bd047c68fade76360e4ead0e3c77cf725 Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Sun, 23 Jun 2019 01:31:18 +0200 Subject: [PATCH 3/6] Enhance PDF building --- docs/source/conf.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/docs/source/conf.py b/docs/source/conf.py index 01fbe6de..b0313901 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -66,3 +66,15 @@ html_theme_options = { html_logo = "_images/pyrogram.png" html_favicon = "_images/favicon.ico" + +latex_engine = "xelatex" +latex_logo = "_images/pyrogram.png" + +latex_elements = { + "pointsize": "12pt", + "fontpkg": r""" + \setmainfont{Noto Sans} + \setsansfont{Roboto Slab} + \setmonofont{Ubuntu Mono} + """ +} From b4f0f411bd5f7b2c491faab59ad5f9d2e999debc Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Sun, 23 Jun 2019 01:32:04 +0200 Subject: [PATCH 4/6] Small documentation fixes --- docs/source/faq.rst | 6 +- docs/source/index.rst | 174 +++++++++++++++++++++--------------------- 2 files changed, 90 insertions(+), 90 deletions(-) diff --git a/docs/source/faq.rst b/docs/source/faq.rst index 335f4bc6..f76f1790 100644 --- a/docs/source/faq.rst +++ b/docs/source/faq.rst @@ -68,7 +68,7 @@ To challenge the framework, the creator is constantly keeping a public `welcome bot `_ online 24/7 on his own, relatively-busy account for well over a year now. -In addition to that, about six months ago, one of the most popular Telegram bot has been rewritten +In addition to that, about six months ago, one of the most popular Telegram bot has been rewritten from scratch :doc:`using Pyrogram ` and is serving more than 200,000 Monthly Active Users since then, uninterruptedly and without any need for restarting it. @@ -134,8 +134,8 @@ If you -- even accidentally -- fail to do so, all the previous session copies wi and eventually the server will start throwing the error ``[406 AUTH_KEY_DUPLICATED]``, inviting you to login again. Why is that so? Because the server has recognized two identical sessions are running in two different locations, and -concludes it could possibly be due to a cloned/stolen device. Having the session ended in such occasions will protect -the user's privacy. +concludes it could possibly be due to a cloned/stolen device. Having the session terminated in such occasions will +protect the user's privacy. So, the only correct way to run multiple clients on the same account is authorizing your account (either user or bot) from the beginning every time, and use one separate session for each parallel client you are going to use. diff --git a/docs/source/index.rst b/docs/source/index.rst index b9682827..66722690 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -1,93 +1,6 @@ Welcome to Pyrogram =================== -.. raw:: html - -
- -
Pyrogram Logo
-
-
- -

- Telegram MTProto API Framework for Python - -
- - Source Code - - • - - Releases - - • - - Community - -

- -.. code-block:: python - - from pyrogram import Client, Filters - - app = Client("my_account") - - - @app.on_message(Filters.private) - def hello(client, message): - message.reply("Hello {}".format(message.from_user.first_name)) - - - app.run() - -**Pyrogram** is an elegant, easy-to-use Telegram_ client library and framework written from the ground up in Python and -C. It enables you to easily create custom apps for both user and bot identities (bot API alternative) via the -:doc:`MTProto API `. - -.. _Telegram: https://telegram.org - -How the Documentation is Organized ----------------------------------- - -Contents are organized into self-contained topics and can be all accessed from the sidebar, or by following them in -order using the :guilabel:`Next` button at the end of each page. Here below you can, instead, find a list of the most -relevant pages for a quick access. - -First Steps ------------ - -.. hlist:: - :columns: 2 - - - :doc:`Quick Start `: Overview to get you started quickly. - - :doc:`Calling Methods `: How to call Pyrogram's methods. - - :doc:`Handling Updates `: How to handle Telegram updates. - - :doc:`Error Handling `: How to handle API errors correctly. - -API Reference -------------- - -.. hlist:: - :columns: 2 - - - :doc:`Pyrogram Client `: Reference details about the Client class. - - :doc:`Available Methods `: List of available high-level methods. - - :doc:`Available Types `: List of available high-level types. - - :doc:`Bound Methods `: List of convenient bound methods. - -Meta ----- - -.. hlist:: - :columns: 2 - - - :doc:`Pyrogram FAQ `: Answers to common Pyrogram questions. - - :doc:`Pyrogram Glossary `: List of words with brief explanations. - - :doc:`Powered by Pyrogram `: Collection of Pyrogram Projects. - - :doc:`Support Pyrogram `: Ways to show your appreciation. - - :doc:`About the License `: Information about the Project license. - - :doc:`Release Notes `: Release notes for Pyrogram releases. - .. toctree:: :hidden: :caption: Introduction @@ -159,4 +72,91 @@ Meta telegram/functions/index telegram/types/index +.. raw:: html + +
+ +
Pyrogram Logo
+
+
+ +

+ Telegram MTProto API Framework for Python + +
+ + Source Code + + • + + Releases + + • + + Community + +

+ +.. code-block:: python + + from pyrogram import Client, Filters + + app = Client("my_account") + + + @app.on_message(Filters.private) + def hello(client, message): + message.reply("Hello {}".format(message.from_user.first_name)) + + + app.run() + +**Pyrogram** is an elegant, easy-to-use Telegram_ client library and framework written from the ground up in Python and +C. It enables you to easily create custom apps for both user and bot identities (bot API alternative) via the +:doc:`MTProto API `. + +.. _Telegram: https://telegram.org + +How the Documentation is Organized +---------------------------------- + +Contents are organized into self-contained topics and can be all accessed from the sidebar, or by following them in +order using the :guilabel:`Next` button at the end of each page. Here below you can, instead, find a list of the most +relevant pages for a quick access. + +First Steps +^^^^^^^^^^^ + +.. hlist:: + :columns: 2 + + - :doc:`Quick Start `: Overview to get you started quickly. + - :doc:`Calling Methods `: How to call Pyrogram's methods. + - :doc:`Handling Updates `: How to handle Telegram updates. + - :doc:`Error Handling `: How to handle API errors correctly. + +API Reference +^^^^^^^^^^^^^ + +.. hlist:: + :columns: 2 + + - :doc:`Pyrogram Client `: Reference details about the Client class. + - :doc:`Available Methods `: List of available high-level methods. + - :doc:`Available Types `: List of available high-level types. + - :doc:`Bound Methods `: List of convenient bound methods. + +Meta +^^^^ + +.. hlist:: + :columns: 2 + + - :doc:`Pyrogram FAQ `: Answers to common Pyrogram questions. + - :doc:`Pyrogram Glossary `: List of words with brief explanations. + - :doc:`Powered by Pyrogram `: Collection of Pyrogram Projects. + - :doc:`Support Pyrogram `: Ways to show your appreciation. + - :doc:`About the License `: Information about the Project license. + - :doc:`Release Notes `: Release notes for Pyrogram releases. + Last updated on |today| \ No newline at end of file From 31f39a00ab602c9714c827833e93730b9466bcb2 Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Sun, 23 Jun 2019 01:33:46 +0200 Subject: [PATCH 5/6] Make plugin callback functions return the function itself when decorated --- pyrogram/client/client.py | 6 ++--- .../methods/decorators/on_callback_query.py | 24 ++++++++----------- .../methods/decorators/on_deleted_messages.py | 24 ++++++++----------- .../methods/decorators/on_disconnect.py | 13 +++++----- .../methods/decorators/on_inline_query.py | 24 ++++++++----------- .../client/methods/decorators/on_message.py | 24 ++++++++----------- pyrogram/client/methods/decorators/on_poll.py | 24 ++++++++----------- .../methods/decorators/on_raw_update.py | 24 ++++++++----------- .../methods/decorators/on_user_status.py | 24 ++++++++----------- 9 files changed, 79 insertions(+), 108 deletions(-) diff --git a/pyrogram/client/client.py b/pyrogram/client/client.py index e1bebeaf..fdfc1e68 100644 --- a/pyrogram/client/client.py +++ b/pyrogram/client/client.py @@ -1106,7 +1106,7 @@ class Client(Methods, BaseClient): for name in vars(module).keys(): # noinspection PyBroadException try: - handler, group = getattr(module, name) + handler, group = getattr(module, name).pyrogram_plugin if isinstance(handler, Handler) and isinstance(group, int): self.add_handler(handler, group) @@ -1141,7 +1141,7 @@ class Client(Methods, BaseClient): for name in handlers: # noinspection PyBroadException try: - handler, group = getattr(module, name) + handler, group = getattr(module, name).pyrogram_plugin if isinstance(handler, Handler) and isinstance(group, int): self.add_handler(handler, group) @@ -1179,7 +1179,7 @@ class Client(Methods, BaseClient): for name in handlers: # noinspection PyBroadException try: - handler, group = getattr(module, name) + handler, group = getattr(module, name).pyrogram_plugin if isinstance(handler, Handler) and isinstance(group, int): self.remove_handler(handler, group) diff --git a/pyrogram/client/methods/decorators/on_callback_query.py b/pyrogram/client/methods/decorators/on_callback_query.py index 1552bae7..1706d71a 100644 --- a/pyrogram/client/methods/decorators/on_callback_query.py +++ b/pyrogram/client/methods/decorators/on_callback_query.py @@ -16,11 +16,10 @@ # You should have received a copy of the GNU Lesser General Public License # along with Pyrogram. If not, see . -from typing import Tuple +from typing import Callable import pyrogram from pyrogram.client.filters.filter import Filter -from pyrogram.client.handlers.handler import Handler from ...ext import BaseClient @@ -44,18 +43,15 @@ class OnCallbackQuery(BaseClient): The group identifier, defaults to 0. """ - def decorator(func: callable) -> Tuple[Handler, int]: - if isinstance(func, tuple): - func = func[0].callback + def decorator(func: Callable) -> Callable: + if isinstance(self, pyrogram.Client): + self.add_handler(pyrogram.CallbackQueryHandler(func, filters), group) + elif isinstance(self, Filter) or self is None: + func.pyrogram_plugin = ( + pyrogram.CallbackQueryHandler(func, self), + group if filters is None else filters + ) - handler = pyrogram.CallbackQueryHandler(func, filters) - - if isinstance(self, Filter): - return pyrogram.CallbackQueryHandler(func, self), group if filters is None else filters - - if self is not None: - self.add_handler(handler, group) - - return handler, group + return func return decorator diff --git a/pyrogram/client/methods/decorators/on_deleted_messages.py b/pyrogram/client/methods/decorators/on_deleted_messages.py index 0d87ba5a..86dda587 100644 --- a/pyrogram/client/methods/decorators/on_deleted_messages.py +++ b/pyrogram/client/methods/decorators/on_deleted_messages.py @@ -16,11 +16,10 @@ # You should have received a copy of the GNU Lesser General Public License # along with Pyrogram. If not, see . -from typing import Tuple +from typing import Callable import pyrogram from pyrogram.client.filters.filter import Filter -from pyrogram.client.handlers.handler import Handler from ...ext import BaseClient @@ -44,18 +43,15 @@ class OnDeletedMessages(BaseClient): The group identifier, defaults to 0. """ - def decorator(func: callable) -> Tuple[Handler, int]: - if isinstance(func, tuple): - func = func[0].callback + def decorator(func: Callable) -> Callable: + if isinstance(self, pyrogram.Client): + self.add_handler(pyrogram.DeletedMessagesHandler(func, filters), group) + elif isinstance(self, Filter) or self is None: + func.pyrogram_plugin = ( + pyrogram.DeletedMessagesHandler(func, self), + group if filters is None else filters + ) - handler = pyrogram.DeletedMessagesHandler(func, filters) - - if isinstance(self, Filter): - return pyrogram.DeletedMessagesHandler(func, self), group if filters is None else filters - - if self is not None: - self.add_handler(handler, group) - - return handler, group + return func return decorator diff --git a/pyrogram/client/methods/decorators/on_disconnect.py b/pyrogram/client/methods/decorators/on_disconnect.py index 4a514a41..012abd38 100644 --- a/pyrogram/client/methods/decorators/on_disconnect.py +++ b/pyrogram/client/methods/decorators/on_disconnect.py @@ -16,8 +16,9 @@ # You should have received a copy of the GNU Lesser General Public License # along with Pyrogram. If not, see . +from typing import Callable + import pyrogram -from pyrogram.client.handlers.handler import Handler from ...ext import BaseClient @@ -28,12 +29,10 @@ class OnDisconnect(BaseClient): This does the same thing as :meth:`~pyrogram.Client.add_handler` using the :obj:`~pyrogram.DisconnectHandler`. """ - def decorator(func: callable) -> Handler: - handler = pyrogram.DisconnectHandler(func) + def decorator(func: Callable) -> Callable: + if isinstance(self, pyrogram.Client): + self.add_handler(pyrogram.DisconnectHandler(func)) - if self is not None: - self.add_handler(handler) - - return handler + return func return decorator diff --git a/pyrogram/client/methods/decorators/on_inline_query.py b/pyrogram/client/methods/decorators/on_inline_query.py index adc65d25..d0f2925b 100644 --- a/pyrogram/client/methods/decorators/on_inline_query.py +++ b/pyrogram/client/methods/decorators/on_inline_query.py @@ -16,11 +16,10 @@ # You should have received a copy of the GNU Lesser General Public License # along with Pyrogram. If not, see . -from typing import Tuple +from typing import Callable import pyrogram from pyrogram.client.filters.filter import Filter -from pyrogram.client.handlers.handler import Handler from ...ext import BaseClient @@ -43,18 +42,15 @@ class OnInlineQuery(BaseClient): The group identifier, defaults to 0. """ - def decorator(func: callable) -> Tuple[Handler, int]: - if isinstance(func, tuple): - func = func[0].callback + def decorator(func: Callable) -> Callable: + if isinstance(self, pyrogram.Client): + self.add_handler(pyrogram.InlineQueryHandler(func, filters), group) + elif isinstance(self, Filter) or self is None: + func.pyrogram_plugin = ( + pyrogram.InlineQueryHandler(func, self), + group if filters is None else filters + ) - handler = pyrogram.InlineQueryHandler(func, filters) - - if isinstance(self, Filter): - return pyrogram.InlineQueryHandler(func, self), group if filters is None else filters - - if self is not None: - self.add_handler(handler, group) - - return handler, group + return func return decorator diff --git a/pyrogram/client/methods/decorators/on_message.py b/pyrogram/client/methods/decorators/on_message.py index 758a6831..5640f22c 100644 --- a/pyrogram/client/methods/decorators/on_message.py +++ b/pyrogram/client/methods/decorators/on_message.py @@ -16,11 +16,10 @@ # You should have received a copy of the GNU Lesser General Public License # along with Pyrogram. If not, see . -from typing import Tuple +from typing import Callable import pyrogram from pyrogram.client.filters.filter import Filter -from pyrogram.client.handlers.handler import Handler from ...ext import BaseClient @@ -43,18 +42,15 @@ class OnMessage(BaseClient): The group identifier, defaults to 0. """ - def decorator(func: callable) -> Tuple[Handler, int]: - if isinstance(func, tuple): - func = func[0].callback + def decorator(func: Callable) -> Callable: + if isinstance(self, pyrogram.Client): + self.add_handler(pyrogram.MessageHandler(func, filters), group) + elif isinstance(self, Filter) or self is None: + func.pyrogram_plugin = ( + pyrogram.MessageHandler(func, self), + group if filters is None else filters + ) - handler = pyrogram.MessageHandler(func, filters) - - if isinstance(self, Filter): - return pyrogram.MessageHandler(func, self), group if filters is None else filters - - if self is not None: - self.add_handler(handler, group) - - return handler, group + return func return decorator diff --git a/pyrogram/client/methods/decorators/on_poll.py b/pyrogram/client/methods/decorators/on_poll.py index 0ade42c0..24282f28 100644 --- a/pyrogram/client/methods/decorators/on_poll.py +++ b/pyrogram/client/methods/decorators/on_poll.py @@ -16,11 +16,10 @@ # You should have received a copy of the GNU Lesser General Public License # along with Pyrogram. If not, see . -from typing import Tuple +from typing import Callable import pyrogram from pyrogram.client.filters.filter import Filter -from pyrogram.client.handlers.handler import Handler from ...ext import BaseClient @@ -43,18 +42,15 @@ class OnPoll(BaseClient): The group identifier, defaults to 0. """ - def decorator(func: callable) -> Tuple[Handler, int]: - if isinstance(func, tuple): - func = func[0].callback + def decorator(func: Callable) -> Callable: + if isinstance(self, pyrogram.Client): + self.add_handler(pyrogram.PollHandler(func, filters), group) + elif isinstance(self, Filter) or self is None: + func.pyrogram_plugin = ( + pyrogram.PollHandler(func, self), + group if filters is None else filters + ) - handler = pyrogram.PollHandler(func, filters) - - if isinstance(self, Filter): - return pyrogram.PollHandler(func, self), group if filters is None else filters - - if self is not None: - self.add_handler(handler, group) - - return handler, group + return func return decorator diff --git a/pyrogram/client/methods/decorators/on_raw_update.py b/pyrogram/client/methods/decorators/on_raw_update.py index 7dff75fa..bbf40c8b 100644 --- a/pyrogram/client/methods/decorators/on_raw_update.py +++ b/pyrogram/client/methods/decorators/on_raw_update.py @@ -16,10 +16,9 @@ # You should have received a copy of the GNU Lesser General Public License # along with Pyrogram. If not, see . -from typing import Tuple +from typing import Callable import pyrogram -from pyrogram.client.handlers.handler import Handler from ...ext import BaseClient @@ -37,18 +36,15 @@ class OnRawUpdate(BaseClient): The group identifier, defaults to 0. """ - def decorator(func: callable) -> Tuple[Handler, int]: - if isinstance(func, tuple): - func = func[0].callback + def decorator(func: Callable) -> Callable: + if isinstance(self, pyrogram.Client): + self.add_handler(pyrogram.RawUpdateHandler(func), group) + else: + func.pyrogram_plugin = ( + pyrogram.RawUpdateHandler(func), + group if self is None else group + ) - handler = pyrogram.RawUpdateHandler(func) - - if isinstance(self, int): - return handler, group if self is None else group - - if self is not None: - self.add_handler(handler, group) - - return handler, group + return func return decorator diff --git a/pyrogram/client/methods/decorators/on_user_status.py b/pyrogram/client/methods/decorators/on_user_status.py index 09e037f7..81a83d02 100644 --- a/pyrogram/client/methods/decorators/on_user_status.py +++ b/pyrogram/client/methods/decorators/on_user_status.py @@ -16,11 +16,10 @@ # You should have received a copy of the GNU Lesser General Public License # along with Pyrogram. If not, see . -from typing import Tuple +from typing import Callable import pyrogram from pyrogram.client.filters.filter import Filter -from pyrogram.client.handlers.handler import Handler from ...ext import BaseClient @@ -41,18 +40,15 @@ class OnUserStatus(BaseClient): The group identifier, defaults to 0. """ - def decorator(func: callable) -> Tuple[Handler, int]: - if isinstance(func, tuple): - func = func[0].callback + def decorator(func: Callable) -> Callable: + if isinstance(self, pyrogram.Client): + self.add_handler(pyrogram.UserStatusHandler(func, filters), group) + elif isinstance(self, Filter) or self is None: + func.pyrogram_plugin = ( + pyrogram.UserStatusHandler(func, self), + group if filters is None else filters + ) - handler = pyrogram.UserStatusHandler(func, filters) - - if isinstance(self, Filter): - return pyrogram.UserStatusHandler(func, self), group if filters is None else filters - - if self is not None: - self.add_handler(handler, group) - - return handler, group + return func return decorator From 5f2d76ceca82e06e43d7f0d995729f82f7bccbc4 Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Sun, 23 Jun 2019 01:34:27 +0200 Subject: [PATCH 6/6] Remove outdated note --- docs/source/start/updates.rst | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/docs/source/start/updates.rst b/docs/source/start/updates.rst index 9ac428b3..9b0a5a32 100644 --- a/docs/source/start/updates.rst +++ b/docs/source/start/updates.rst @@ -96,14 +96,3 @@ to do so is by decorating your callback function with the :meth:`~pyrogram.Clien app.run() - - -.. note:: - - Due to how these decorators work in Pyrogram, they will wrap your defined callback function in a tuple consisting of - ``(handler, group)``; this will be the value held by your function identifier (e.g.: *my_function* from the example - above). - - In case, for some reason, you want to get your own function back after it has been decorated, you need to access - ``my_function[0].callback``, that is, the *callback* field of the *handler* object which is the first element in the - tuple, accessed by bracket notation *[0]*.