From b14ca1abf9f6a782ea474c59d6297e5a18e50831 Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Sat, 25 May 2019 02:12:45 +0200 Subject: [PATCH 01/50] Create FUNDING.yml --- .github/FUNDING.yml | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .github/FUNDING.yml diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 00000000..f34f615a --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,2 @@ +github: delivrance +custom: https://docs.pyrogram.org/support-pyrogram From 41f010caadc7ac35d153fcbe988a4fb48a4c3ac7 Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Sun, 26 May 2019 16:52:22 +0200 Subject: [PATCH 02/50] Add USER_DEACTIVATED_BAN error --- compiler/error/source/401_UNAUTHORIZED.tsv | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/error/source/401_UNAUTHORIZED.tsv b/compiler/error/source/401_UNAUTHORIZED.tsv index 54b24dd7..e5cd3874 100644 --- a/compiler/error/source/401_UNAUTHORIZED.tsv +++ b/compiler/error/source/401_UNAUTHORIZED.tsv @@ -2,6 +2,7 @@ id message AUTH_KEY_UNREGISTERED The key is not registered in the system AUTH_KEY_INVALID The key is invalid USER_DEACTIVATED The user has been deleted/deactivated +USER_DEACTIVATED_BAN The user has been deleted/deactivated SESSION_REVOKED The authorization has been invalidated, because of the user terminating all sessions SESSION_EXPIRED The authorization has expired ACTIVE_USER_REQUIRED The method is only available to already activated users From 87ad98142022ca91ba773b2546eaa32e8c176381 Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Mon, 27 May 2019 14:39:10 +0200 Subject: [PATCH 03/50] Add get_user_dc method --- pyrogram/client/methods/users/__init__.py | 4 +- pyrogram/client/methods/users/get_user_dc.py | 52 ++++++++++++++++++++ 2 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 pyrogram/client/methods/users/get_user_dc.py diff --git a/pyrogram/client/methods/users/__init__.py b/pyrogram/client/methods/users/__init__.py index d67a18bd..a33a0f0c 100644 --- a/pyrogram/client/methods/users/__init__.py +++ b/pyrogram/client/methods/users/__init__.py @@ -18,6 +18,7 @@ from .delete_user_profile_photos import DeleteUserProfilePhotos from .get_me import GetMe +from .get_user_dc import GetUserDC from .get_user_profile_photos import GetUserProfilePhotos from .get_user_profile_photos_count import GetUserProfilePhotosCount from .get_users import GetUsers @@ -32,6 +33,7 @@ class Users( GetUsers, GetMe, UpdateUsername, - GetUserProfilePhotosCount + GetUserProfilePhotosCount, + GetUserDC ): pass diff --git a/pyrogram/client/methods/users/get_user_dc.py b/pyrogram/client/methods/users/get_user_dc.py new file mode 100644 index 00000000..27631e95 --- /dev/null +++ b/pyrogram/client/methods/users/get_user_dc.py @@ -0,0 +1,52 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-2019 Dan Tès +# +# This file is part of Pyrogram. +# +# Pyrogram is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pyrogram is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Pyrogram. If not, see . + +from typing import Union + +from pyrogram.api import functions, types + +from ...ext import BaseClient + + +class GetUserDC(BaseClient): + def get_user_dc(self, user_id: Union[int, str]) -> Union[int, None]: + """Get the assigned data center (DC) of a user. + + Parameters: + user_id (``int`` | ``str``): + Unique identifier (int) or username (str) of the target chat. + For your personal cloud (Saved Messages) you can simply use "me" or "self". + For a contact that exists in your Telegram address book you can use his phone number (str). + + Returns: + ``int`` | ``None``: The DC identifier as integer, or None in case it wasn't possible to get it. + + Raises: + RPCError: In case of a Telegram RPC error. + """ + + r = self.send(functions.users.GetUsers(id=[self.resolve_peer(user_id)])) + + if r: + r = r[0] + + if r.photo: + if isinstance(r.photo.photo_small, types.FileLocation): + return r.photo.photo_small.dc_id + + return None From e94dcd3b0b06b33ad7f0acb040d6a33b5a565631 Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Tue, 28 May 2019 16:41:55 +0200 Subject: [PATCH 04/50] Update docs --- docs/sitemap.py | 10 +- docs/source/api/bound-methods.rst | 102 +++-- docs/source/api/decorators.rst | 57 ++- docs/source/api/handlers.rst | 33 +- docs/source/api/methods.rst | 414 +++++++++--------- docs/source/api/types.rst | 158 ++++--- docs/source/conf.py | 4 +- docs/source/faq.rst | 42 +- docs/source/glossary.rst | 14 +- docs/source/index.rst | 51 +-- docs/source/intro/install.rst | 3 +- docs/source/intro/quickstart.rst | 4 +- docs/source/intro/setup.rst | 8 +- docs/source/license.rst | 15 + docs/source/start/auth.rst | 9 +- docs/source/start/invoking.rst | 11 +- docs/source/start/updates.rst | 38 +- docs/source/topics/advanced-usage.rst | 41 +- docs/source/topics/auto-auth.rst | 2 +- docs/source/topics/bots-interaction.rst | 5 +- docs/source/topics/filters.rst | 24 +- docs/source/topics/more-on-updates.rst | 8 +- docs/source/topics/serialize.rst | 7 +- docs/source/topics/session-settings.rst | 2 +- docs/source/topics/smart-plugins.rst | 17 +- docs/source/topics/text-formatting.rst | 4 +- .../client/methods/chats/set_chat_photo.py | 2 +- .../types/messages_and_media/message.py | 2 +- 28 files changed, 536 insertions(+), 551 deletions(-) create mode 100644 docs/source/license.rst diff --git a/docs/sitemap.py b/docs/sitemap.py index 87c27849..4def886f 100644 --- a/docs/sitemap.py +++ b/docs/sitemap.py @@ -23,11 +23,11 @@ canonical = "https://docs.pyrogram.org/" dirs = { ".": ("weekly", 1.0), - "intro": ("weekly", 0.8), - "start": ("weekly", 0.8), - "api": ("weekly", 0.6), - "topics": ("weekly", 0.6), - "telegram": ("weekly", 0.4) + "intro": ("weekly", 0.9), + "start": ("weekly", 0.9), + "api": ("weekly", 0.8), + "topics": ("weekly", 0.8), + "telegram": ("weekly", 0.6) } diff --git a/docs/source/api/bound-methods.rst b/docs/source/api/bound-methods.rst index d93497fe..0622e6b8 100644 --- a/docs/source/api/bound-methods.rst +++ b/docs/source/api/bound-methods.rst @@ -22,43 +22,65 @@ some of the required arguments. .. currentmodule:: pyrogram -- Message_ -- CallbackQuery_ -- InlineQuery_ - -.. _Message: +Index +----- Message +^^^^^^^ + +.. hlist:: + :columns: 3 + + - :meth:`~Message.click` + - :meth:`~Message.delete` + - :meth:`~Message.download` + - :meth:`~Message.edit` + - :meth:`~Message.edit_caption` + - :meth:`~Message.edit_media` + - :meth:`~Message.edit_reply_markup` + - :meth:`~Message.forward` + - :meth:`~Message.pin` + - :meth:`~Message.reply` + - :meth:`~Message.reply_animation` + - :meth:`~Message.reply_audio` + - :meth:`~Message.reply_cached_media` + - :meth:`~Message.reply_chat_action` + - :meth:`~Message.reply_contact` + - :meth:`~Message.reply_document` + - :meth:`~Message.reply_game` + - :meth:`~Message.reply_inline_bot_result` + - :meth:`~Message.reply_location` + - :meth:`~Message.reply_media_group` + - :meth:`~Message.reply_photo` + - :meth:`~Message.reply_poll` + - :meth:`~Message.reply_sticker` + - :meth:`~Message.reply_venue` + - :meth:`~Message.reply_video` + - :meth:`~Message.reply_video_note` + - :meth:`~Message.reply_voice` + +CallbackQuery +^^^^^^^^^^^^^ + +.. hlist:: + :columns: 2 + + - :meth:`~CallbackQuery.answer` + +InlineQuery +^^^^^^^^^^^ + +.. hlist:: + :columns: 2 + + - :meth:`~InlineQuery.answer` + +----- + +Details ------- -- :meth:`Message.click()` -- :meth:`Message.delete()` -- :meth:`Message.download()` -- :meth:`Message.edit()` -- :meth:`Message.edit_caption()` -- :meth:`Message.edit_media()` -- :meth:`Message.edit_reply_markup()` -- :meth:`Message.forward()` -- :meth:`Message.pin()` -- :meth:`Message.reply()` -- :meth:`Message.reply_animation()` -- :meth:`Message.reply_audio()` -- :meth:`Message.reply_cached_media()` -- :meth:`Message.reply_chat_action()` -- :meth:`Message.reply_contact()` -- :meth:`Message.reply_document()` -- :meth:`Message.reply_game()` -- :meth:`Message.reply_inline_bot_result()` -- :meth:`Message.reply_location()` -- :meth:`Message.reply_media_group()` -- :meth:`Message.reply_photo()` -- :meth:`Message.reply_poll()` -- :meth:`Message.reply_sticker()` -- :meth:`Message.reply_venue()` -- :meth:`Message.reply_video()` -- :meth:`Message.reply_video_note()` -- :meth:`Message.reply_voice()` - +.. Message .. automethod:: Message.click() .. automethod:: Message.delete() .. automethod:: Message.download() @@ -87,16 +109,8 @@ Message .. automethod:: Message.reply_video_note() .. automethod:: Message.reply_voice() -.. _CallbackQuery: - -CallbackQuery -------------- - +.. CallbackQuery .. automethod:: CallbackQuery.answer() -.. _InlineQuery: - -InlineQuery ------------ - -.. automethod:: InlineQuery.answer() \ No newline at end of file +.. InlineQuery +.. automethod:: InlineQuery.answer() diff --git a/docs/source/api/decorators.rst b/docs/source/api/decorators.rst index be8376f5..ff31cb27 100644 --- a/docs/source/api/decorators.rst +++ b/docs/source/api/decorators.rst @@ -1,13 +1,13 @@ Decorators ========== -While still being methods bound to the :obj:`Client ` class, decorators are of a special kind and thus deserve a -dedicated page. +While still being methods bound to the :class:`~pyrogram.Client` class, decorators are of a special kind and thus +deserve a dedicated page. Decorators are able to register callback functions for handling updates in a much easier and cleaner way compared to -`Handlers `_; they do so by instantiating the correct handler and calling -:meth:`add_handler() `, automatically. All you need to do is adding the decorators on top -of your functions. +:doc:`Handlers `; they do so by instantiating the correct handler and calling +:meth:`~pyrogram.Client.add_handler`, automatically. All you need to do is adding the decorators on top of your +functions. .. code-block:: python :emphasize-lines: 6 @@ -24,25 +24,34 @@ of your functions. app.run() -.. currentmodule:: pyrogram.Client +.. currentmodule:: pyrogram -.. autosummary:: - :nosignatures: +Index +----- - on_message - on_callback_query - on_inline_query - on_deleted_messages - on_user_status - on_poll - on_disconnect - on_raw_update +.. hlist:: + :columns: 3 -.. automethod:: pyrogram.Client.on_message() -.. automethod:: pyrogram.Client.on_callback_query() -.. automethod:: pyrogram.Client.on_inline_query() -.. automethod:: pyrogram.Client.on_deleted_messages() -.. automethod:: pyrogram.Client.on_user_status() -.. automethod:: pyrogram.Client.on_poll() -.. automethod:: pyrogram.Client.on_disconnect() -.. automethod:: pyrogram.Client.on_raw_update() \ No newline at end of file + - :meth:`~Client.on_message` + - :meth:`~Client.on_callback_query` + - :meth:`~Client.on_inline_query` + - :meth:`~Client.on_deleted_messages` + - :meth:`~Client.on_user_status` + - :meth:`~Client.on_poll` + - :meth:`~Client.on_disconnect` + - :meth:`~Client.on_raw_update` + +----- + +Details +------- + +.. Decorators +.. autodecorator:: pyrogram.Client.on_message() +.. autodecorator:: pyrogram.Client.on_callback_query() +.. autodecorator:: pyrogram.Client.on_inline_query() +.. autodecorator:: pyrogram.Client.on_deleted_messages() +.. autodecorator:: pyrogram.Client.on_user_status() +.. autodecorator:: pyrogram.Client.on_poll() +.. autodecorator:: pyrogram.Client.on_disconnect() +.. autodecorator:: pyrogram.Client.on_raw_update() \ No newline at end of file diff --git a/docs/source/api/handlers.rst b/docs/source/api/handlers.rst index 90c8e614..f91dd3d5 100644 --- a/docs/source/api/handlers.rst +++ b/docs/source/api/handlers.rst @@ -3,8 +3,8 @@ Update Handlers Handlers are used to instruct Pyrogram about which kind of updates you'd like to handle with your callback functions. -For a much more convenient way of registering callback functions have a look at `Decorators `_ instead. -In case you decided to manually create a handler, use :meth:`add_handler() ` to register +For a much more convenient way of registering callback functions have a look at :doc:`Decorators ` instead. +In case you decided to manually create a handler, use :class:`~pyrogram.Client.add_handler` to register it. .. code-block:: python @@ -25,18 +25,27 @@ it. .. currentmodule:: pyrogram -.. autosummary:: - :nosignatures: +Index +----- - MessageHandler - DeletedMessagesHandler - CallbackQueryHandler - InlineQueryHandler - UserStatusHandler - PollHandler - DisconnectHandler - RawUpdateHandler +.. hlist:: + :columns: 3 + - :class:`MessageHandler` + - :class:`DeletedMessagesHandler` + - :class:`CallbackQueryHandler` + - :class:`InlineQueryHandler` + - :class:`UserStatusHandler` + - :class:`PollHandler` + - :class:`DisconnectHandler` + - :class:`RawUpdateHandler` + +----- + +Details +------- + +.. Handlers .. autoclass:: MessageHandler() .. autoclass:: DeletedMessagesHandler() .. autoclass:: CallbackQueryHandler() diff --git a/docs/source/api/methods.rst b/docs/source/api/methods.rst index 7c061d3a..7614918e 100644 --- a/docs/source/api/methods.rst +++ b/docs/source/api/methods.rst @@ -1,7 +1,7 @@ Available Methods ================= -All Pyrogram methods listed here are bound to a :obj:`Client ` instance. +All Pyrogram methods listed here are bound to a :class:`~pyrogram.Client` instance. .. code-block:: python :emphasize-lines: 6 @@ -13,253 +13,249 @@ All Pyrogram methods listed here are bound to a :obj:`Client ` with app: app.send_message("haskell", "hi") -.. currentmodule:: pyrogram.Client +.. currentmodule:: pyrogram + +Index +----- Utilities ---------- +^^^^^^^^^ -.. autosummary:: - :nosignatures: +.. hlist:: + :columns: 4 - start - stop - restart - idle - run - add_handler - remove_handler - send - resolve_peer - save_file - stop_transmission + - :meth:`~Client.start` + - :meth:`~Client.stop` + - :meth:`~Client.restart` + - :meth:`~Client.idle` + - :meth:`~Client.run` + - :meth:`~Client.add_handler` + - :meth:`~Client.remove_handler` + - :meth:`~Client.send` + - :meth:`~Client.resolve_peer` + - :meth:`~Client.save_file` + - :meth:`~Client.stop_transmission` Messages --------- +^^^^^^^^ -.. autosummary:: - :nosignatures: +.. hlist:: + :columns: 3 - send_message - forward_messages - send_photo - send_audio - send_document - send_sticker - send_video - send_animation - send_voice - send_video_note - send_media_group - send_location - send_venue - send_contact - send_cached_media - send_chat_action - edit_message_text - edit_message_caption - edit_message_reply_markup - edit_message_media - delete_messages - get_messages - get_history - get_history_count - iter_history - send_poll - vote_poll - stop_poll - retract_vote - download_media + - :meth:`~Client.send_message` + - :meth:`~Client.forward_messages` + - :meth:`~Client.send_photo` + - :meth:`~Client.send_audio` + - :meth:`~Client.send_document` + - :meth:`~Client.send_sticker` + - :meth:`~Client.send_video` + - :meth:`~Client.send_animation` + - :meth:`~Client.send_voice` + - :meth:`~Client.send_video_note` + - :meth:`~Client.send_media_group` + - :meth:`~Client.send_location` + - :meth:`~Client.send_venue` + - :meth:`~Client.send_contact` + - :meth:`~Client.send_cached_media` + - :meth:`~Client.send_chat_action` + - :meth:`~Client.edit_message_text` + - :meth:`~Client.edit_message_caption` + - :meth:`~Client.edit_message_reply_markup` + - :meth:`~Client.edit_message_media` + - :meth:`~Client.delete_messages` + - :meth:`~Client.get_messages` + - :meth:`~Client.get_history` + - :meth:`~Client.get_history_count` + - :meth:`~Client.iter_history` + - :meth:`~Client.send_poll` + - :meth:`~Client.vote_poll` + - :meth:`~Client.stop_poll` + - :meth:`~Client.retract_vote` + - :meth:`~Client.download_media` Chats ------ +^^^^^ -.. autosummary:: - :nosignatures: +.. hlist:: + :columns: 3 - join_chat - leave_chat - kick_chat_member - unban_chat_member - restrict_chat_member - promote_chat_member - export_chat_invite_link - set_chat_photo - delete_chat_photo - set_chat_title - set_chat_description - pin_chat_message - unpin_chat_message - get_chat - get_chat_member - get_chat_members - get_chat_members_count - iter_chat_members - get_dialogs - iter_dialogs - get_dialogs_count - restrict_chat - update_chat_username + - :meth:`~Client.join_chat` + - :meth:`~Client.leave_chat` + - :meth:`~Client.kick_chat_member` + - :meth:`~Client.unban_chat_member` + - :meth:`~Client.restrict_chat_member` + - :meth:`~Client.promote_chat_member` + - :meth:`~Client.export_chat_invite_link` + - :meth:`~Client.set_chat_photo` + - :meth:`~Client.delete_chat_photo` + - :meth:`~Client.set_chat_title` + - :meth:`~Client.set_chat_description` + - :meth:`~Client.pin_chat_message` + - :meth:`~Client.unpin_chat_message` + - :meth:`~Client.get_chat` + - :meth:`~Client.get_chat_member` + - :meth:`~Client.get_chat_members` + - :meth:`~Client.get_chat_members_count` + - :meth:`~Client.iter_chat_members` + - :meth:`~Client.get_dialogs` + - :meth:`~Client.iter_dialogs` + - :meth:`~Client.get_dialogs_count` + - :meth:`~Client.restrict_chat` + - :meth:`~Client.update_chat_username` Users ------ +^^^^^ -.. autosummary:: - :nosignatures: +.. hlist:: + :columns: 2 - get_me - get_users - get_user_profile_photos - get_user_profile_photos_count - set_user_profile_photo - delete_user_profile_photos - update_username + - :meth:`~Client.get_me` + - :meth:`~Client.get_users` + - :meth:`~Client.get_user_profile_photos` + - :meth:`~Client.get_user_profile_photos_count` + - :meth:`~Client.set_user_profile_photo` + - :meth:`~Client.delete_user_profile_photos` + - :meth:`~Client.update_username` + - :meth:`~Client.get_user_dc` Contacts --------- +^^^^^^^^ -.. autosummary:: - :nosignatures: +.. hlist:: + :columns: 3 - add_contacts - get_contacts - get_contacts_count - delete_contacts + - :meth:`~Client.add_contacts` + - :meth:`~Client.get_contacts` + - :meth:`~Client.get_contacts_count` + - :meth:`~Client.delete_contacts` Password --------- +^^^^^^^^ -.. autosummary:: - :nosignatures: +.. hlist:: + :columns: 3 - enable_cloud_password - change_cloud_password - remove_cloud_password + - :meth:`~Client.enable_cloud_password` + - :meth:`~Client.change_cloud_password` + - :meth:`~Client.remove_cloud_password` Bots ----- +^^^^ -.. autosummary:: - :nosignatures: +.. hlist:: + :columns: 3 - get_inline_bot_results - send_inline_bot_result - answer_callback_query - answer_inline_query - request_callback_answer - send_game - set_game_score - get_game_high_scores + - :meth:`~Client.get_inline_bot_results` + - :meth:`~Client.send_inline_bot_result` + - :meth:`~Client.answer_callback_query` + - :meth:`~Client.answer_inline_query` + - :meth:`~Client.request_callback_answer` + - :meth:`~Client.send_game` + - :meth:`~Client.set_game_score` + - :meth:`~Client.get_game_high_scores` + +----- + +Details +------- .. Utilities - --------- - -.. automethod:: pyrogram.Client.start() -.. automethod:: pyrogram.Client.stop() -.. automethod:: pyrogram.Client.restart() -.. automethod:: pyrogram.Client.idle() -.. automethod:: pyrogram.Client.run() -.. automethod:: pyrogram.Client.add_handler() -.. automethod:: pyrogram.Client.remove_handler() -.. automethod:: pyrogram.Client.send() -.. automethod:: pyrogram.Client.resolve_peer() -.. automethod:: pyrogram.Client.save_file() -.. automethod:: pyrogram.Client.stop_transmission() +.. automethod:: Client.start() +.. automethod:: Client.stop() +.. automethod:: Client.restart() +.. automethod:: Client.idle() +.. automethod:: Client.run() +.. automethod:: Client.add_handler() +.. automethod:: Client.remove_handler() +.. automethod:: Client.send() +.. automethod:: Client.resolve_peer() +.. automethod:: Client.save_file() +.. automethod:: Client.stop_transmission() .. Messages - -------- - -.. automethod:: pyrogram.Client.send_message() -.. automethod:: pyrogram.Client.forward_messages() -.. automethod:: pyrogram.Client.send_photo() -.. automethod:: pyrogram.Client.send_audio() -.. automethod:: pyrogram.Client.send_document() -.. automethod:: pyrogram.Client.send_sticker() -.. automethod:: pyrogram.Client.send_video() -.. automethod:: pyrogram.Client.send_animation() -.. automethod:: pyrogram.Client.send_voice() -.. automethod:: pyrogram.Client.send_video_note() -.. automethod:: pyrogram.Client.send_media_group() -.. automethod:: pyrogram.Client.send_location() -.. automethod:: pyrogram.Client.send_venue() -.. automethod:: pyrogram.Client.send_contact() -.. automethod:: pyrogram.Client.send_cached_media() -.. automethod:: pyrogram.Client.send_chat_action() -.. automethod:: pyrogram.Client.edit_message_text() -.. automethod:: pyrogram.Client.edit_message_caption() -.. automethod:: pyrogram.Client.edit_message_reply_markup() -.. automethod:: pyrogram.Client.edit_message_media() -.. automethod:: pyrogram.Client.delete_messages() -.. automethod:: pyrogram.Client.get_messages() -.. automethod:: pyrogram.Client.get_history() -.. automethod:: pyrogram.Client.get_history_count() -.. automethod:: pyrogram.Client.iter_history() -.. automethod:: pyrogram.Client.send_poll() -.. automethod:: pyrogram.Client.vote_poll() -.. automethod:: pyrogram.Client.stop_poll() -.. automethod:: pyrogram.Client.retract_vote() -.. automethod:: pyrogram.Client.download_media() +.. automethod:: Client.send_message() +.. automethod:: Client.forward_messages() +.. automethod:: Client.send_photo() +.. automethod:: Client.send_audio() +.. automethod:: Client.send_document() +.. automethod:: Client.send_sticker() +.. automethod:: Client.send_video() +.. automethod:: Client.send_animation() +.. automethod:: Client.send_voice() +.. automethod:: Client.send_video_note() +.. automethod:: Client.send_media_group() +.. automethod:: Client.send_location() +.. automethod:: Client.send_venue() +.. automethod:: Client.send_contact() +.. automethod:: Client.send_cached_media() +.. automethod:: Client.send_chat_action() +.. automethod:: Client.edit_message_text() +.. automethod:: Client.edit_message_caption() +.. automethod:: Client.edit_message_reply_markup() +.. automethod:: Client.edit_message_media() +.. automethod:: Client.delete_messages() +.. automethod:: Client.get_messages() +.. automethod:: Client.get_history() +.. automethod:: Client.get_history_count() +.. automethod:: Client.iter_history() +.. automethod:: Client.send_poll() +.. automethod:: Client.vote_poll() +.. automethod:: Client.stop_poll() +.. automethod:: Client.retract_vote() +.. automethod:: Client.download_media() .. Chats - ----- - -.. automethod:: pyrogram.Client.join_chat() -.. automethod:: pyrogram.Client.leave_chat() -.. automethod:: pyrogram.Client.kick_chat_member() -.. automethod:: pyrogram.Client.unban_chat_member() -.. automethod:: pyrogram.Client.restrict_chat_member() -.. automethod:: pyrogram.Client.promote_chat_member() -.. automethod:: pyrogram.Client.export_chat_invite_link() -.. automethod:: pyrogram.Client.set_chat_photo() -.. automethod:: pyrogram.Client.delete_chat_photo() -.. automethod:: pyrogram.Client.set_chat_title() -.. automethod:: pyrogram.Client.set_chat_description() -.. automethod:: pyrogram.Client.pin_chat_message() -.. automethod:: pyrogram.Client.unpin_chat_message() -.. automethod:: pyrogram.Client.get_chat() -.. automethod:: pyrogram.Client.get_chat_member() -.. automethod:: pyrogram.Client.get_chat_members() -.. automethod:: pyrogram.Client.get_chat_members_count() -.. automethod:: pyrogram.Client.iter_chat_members() -.. automethod:: pyrogram.Client.get_dialogs() -.. automethod:: pyrogram.Client.iter_dialogs() -.. automethod:: pyrogram.Client.get_dialogs_count() -.. automethod:: pyrogram.Client.restrict_chat() -.. automethod:: pyrogram.Client.update_chat_username() +.. automethod:: Client.join_chat() +.. automethod:: Client.leave_chat() +.. automethod:: Client.kick_chat_member() +.. automethod:: Client.unban_chat_member() +.. automethod:: Client.restrict_chat_member() +.. automethod:: Client.promote_chat_member() +.. automethod:: Client.export_chat_invite_link() +.. automethod:: Client.set_chat_photo() +.. automethod:: Client.delete_chat_photo() +.. automethod:: Client.set_chat_title() +.. automethod:: Client.set_chat_description() +.. automethod:: Client.pin_chat_message() +.. automethod:: Client.unpin_chat_message() +.. automethod:: Client.get_chat() +.. automethod:: Client.get_chat_member() +.. automethod:: Client.get_chat_members() +.. automethod:: Client.get_chat_members_count() +.. automethod:: Client.iter_chat_members() +.. automethod:: Client.get_dialogs() +.. automethod:: Client.iter_dialogs() +.. automethod:: Client.get_dialogs_count() +.. automethod:: Client.restrict_chat() +.. automethod:: Client.update_chat_username() .. Users - ----- - -.. automethod:: pyrogram.Client.get_me() -.. automethod:: pyrogram.Client.get_users() -.. automethod:: pyrogram.Client.get_user_profile_photos() -.. automethod:: pyrogram.Client.get_user_profile_photos_count() -.. automethod:: pyrogram.Client.set_user_profile_photo() -.. automethod:: pyrogram.Client.delete_user_profile_photos() -.. automethod:: pyrogram.Client.update_username() +.. automethod:: Client.get_me() +.. automethod:: Client.get_users() +.. automethod:: Client.get_user_profile_photos() +.. automethod:: Client.get_user_profile_photos_count() +.. automethod:: Client.set_user_profile_photo() +.. automethod:: Client.delete_user_profile_photos() +.. automethod:: Client.update_username() +.. automethod:: Client.get_user_dc() .. Contacts - -------- - -.. automethod:: pyrogram.Client.add_contacts() -.. automethod:: pyrogram.Client.get_contacts() -.. automethod:: pyrogram.Client.get_contacts_count() -.. automethod:: pyrogram.Client.delete_contacts() +.. automethod:: Client.add_contacts() +.. automethod:: Client.get_contacts() +.. automethod:: Client.get_contacts_count() +.. automethod:: Client.delete_contacts() .. Password - -------- - -.. automethod:: pyrogram.Client.enable_cloud_password() -.. automethod:: pyrogram.Client.change_cloud_password() -.. automethod:: pyrogram.Client.remove_cloud_password() +.. automethod:: Client.enable_cloud_password() +.. automethod:: Client.change_cloud_password() +.. automethod:: Client.remove_cloud_password() .. Bots - ---- - -.. automethod:: pyrogram.Client.get_inline_bot_results() -.. automethod:: pyrogram.Client.send_inline_bot_result() -.. automethod:: pyrogram.Client.answer_callback_query() -.. automethod:: pyrogram.Client.answer_inline_query() -.. automethod:: pyrogram.Client.request_callback_answer() -.. automethod:: pyrogram.Client.send_game() -.. automethod:: pyrogram.Client.set_game_score() -.. automethod:: pyrogram.Client.get_game_high_scores() +.. automethod:: Client.get_inline_bot_results() +.. automethod:: Client.send_inline_bot_result() +.. automethod:: Client.answer_callback_query() +.. automethod:: Client.answer_inline_query() +.. automethod:: Client.request_callback_answer() +.. automethod:: Client.send_game() +.. automethod:: Client.set_game_score() +.. automethod:: Client.get_game_high_scores() diff --git a/docs/source/api/types.rst b/docs/source/api/types.rst index d911520c..d264eaa2 100644 --- a/docs/source/api/types.rst +++ b/docs/source/api/types.rst @@ -15,102 +15,108 @@ All Pyrogram types listed here are accessible through the main package directly. .. currentmodule:: pyrogram +Index +----- + Users & Chats -------------- +^^^^^^^^^^^^^ -.. autosummary:: - :nosignatures: +.. hlist:: + :columns: 5 - User - UserStatus - Chat - ChatPreview - ChatPhoto - ChatMember - ChatMembers - ChatPermissions - Dialog - Dialogs + - :class:`User` + - :class:`UserStatus` + - :class:`Chat` + - :class:`ChatPreview` + - :class:`ChatPhoto` + - :class:`ChatMember` + - :class:`ChatMembers` + - :class:`ChatPermissions` + - :class:`Dialog` + - :class:`Dialogs` Messages & Media ----------------- +^^^^^^^^^^^^^^^^ -.. autosummary:: - :nosignatures: +.. hlist:: + :columns: 5 - Message - Messages - MessageEntity - Photo - PhotoSize - UserProfilePhotos - Audio - Document - Animation - Video - Voice - VideoNote - Contact - Location - Venue - Sticker - Game - Poll - PollOption + - :class:`Message` + - :class:`Messages` + - :class:`MessageEntity` + - :class:`Photo` + - :class:`PhotoSize` + - :class:`UserProfilePhotos` + - :class:`Audio` + - :class:`Document` + - :class:`Animation` + - :class:`Video` + - :class:`Voice` + - :class:`VideoNote` + - :class:`Contact` + - :class:`Location` + - :class:`Venue` + - :class:`Sticker` + - :class:`Game` + - :class:`Poll` + - :class:`PollOption` Keyboards ---------- +^^^^^^^^^ -.. autosummary:: - :nosignatures: +.. hlist:: + :columns: 4 - ReplyKeyboardMarkup - KeyboardButton - ReplyKeyboardRemove - InlineKeyboardMarkup - InlineKeyboardButton - ForceReply - CallbackQuery - GameHighScore - GameHighScores - CallbackGame + - :class:`ReplyKeyboardMarkup` + - :class:`KeyboardButton` + - :class:`ReplyKeyboardRemove` + - :class:`InlineKeyboardMarkup` + - :class:`InlineKeyboardButton` + - :class:`ForceReply` + - :class:`CallbackQuery` + - :class:`GameHighScore` + - :class:`GameHighScores` + - :class:`CallbackGame` Input Media ------------ +^^^^^^^^^^^ -.. autosummary:: - :nosignatures: +.. hlist:: + :columns: 4 - InputMedia - InputMediaPhoto - InputMediaVideo - InputMediaAudio - InputMediaAnimation - InputMediaDocument - InputPhoneContact + - :class:`InputMedia` + - :class:`InputMediaPhoto` + - :class:`InputMediaVideo` + - :class:`InputMediaAudio` + - :class:`InputMediaAnimation` + - :class:`InputMediaDocument` + - :class:`InputPhoneContact` Inline Mode ------------- +^^^^^^^^^^^ -.. autosummary:: - :nosignatures: +.. hlist:: + :columns: 3 - InlineQuery - InlineQueryResult - InlineQueryResultArticle + - :class:`InlineQuery` + - :class:`InlineQueryResult` + - :class:`InlineQueryResultArticle` InputMessageContent -------------------- +^^^^^^^^^^^^^^^^^^^ -.. autosummary:: - :nosignatures: +.. hlist:: + :columns: 3 - InputMessageContent - InputTextMessageContent + - :class:`InputMessageContent` + - :class:`InputTextMessageContent` + +----- + +Details +------- .. User & Chats - ------------ - .. autoclass:: User() .. autoclass:: UserStatus() .. autoclass:: Chat() @@ -123,8 +129,6 @@ InputMessageContent .. autoclass:: Dialogs() .. Messages & Media - ---------------- - .. autoclass:: Message() .. autoclass:: Messages() .. autoclass:: MessageEntity() @@ -146,8 +150,6 @@ InputMessageContent .. autoclass:: PollOption() .. Keyboards - --------- - .. autoclass:: ReplyKeyboardMarkup() .. autoclass:: KeyboardButton() .. autoclass:: ReplyKeyboardRemove() @@ -160,8 +162,6 @@ InputMessageContent .. autoclass:: CallbackGame() .. Input Media - ----------- - .. autoclass:: InputMedia() .. autoclass:: InputMediaPhoto() .. autoclass:: InputMediaVideo() @@ -171,14 +171,10 @@ InputMessageContent .. autoclass:: InputPhoneContact() .. Inline Mode - ----------- - .. autoclass:: InlineQuery() .. autoclass:: InlineQueryResult() .. autoclass:: InlineQueryResultArticle() .. InputMessageContent - ------------------- - .. autoclass:: InputMessageContent() .. autoclass:: InputTextMessageContent() diff --git a/docs/source/conf.py b/docs/source/conf.py index e079ec68..7ddeaa94 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -43,7 +43,6 @@ autodoc_member_order = "bysource" version = __version__ release = version -version_rst = ".. |version| replace:: {}".format(version) templates_path = ["_templates"] @@ -61,7 +60,8 @@ html_theme_options = { "collapse_navigation": True, "sticky_navigation": False, "logo_only": True, - "display_version": True + "display_version": True, + "style_external_links": True } html_logo = "_images/pyrogram.png" diff --git a/docs/source/faq.rst b/docs/source/faq.rst index b42332cd..7d7e9032 100644 --- a/docs/source/faq.rst +++ b/docs/source/faq.rst @@ -17,10 +17,9 @@ What is Pyrogram? **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 applications for both user and bot identities (bot API alternative) via the -`MTProto API`_ with the Python programming language. +:doc:`MTProto API ` with the Python programming language. .. _Telegram: https://telegram.org -.. _MTProto API: topics/mtproto-vs-botapi#what-is-the-mtproto-api Where does the name come from? ------------------------------ @@ -47,19 +46,17 @@ Why Pyrogram? - **Type-hinted**: Exposed Pyrogram types and method parameters are all type-hinted. - **Updated**, to make use of the latest Telegram API version and features. - **Bot API-like**: Similar to the Bot API in its simplicity, but much more powerful and detailed. -- **Pluggable**: The `Smart Plugin`_ system allows to write components with minimal boilerplate code. -- **Comprehensive**: Execute any `advanced action`_ an official client is able to do, and even more. +- **Pluggable**: The :doc:`Smart Plugin ` system allows to write components with minimal + boilerplate code. +- **Comprehensive**: Execute any :doc:`advanced action ` an official client is able to do, and + even more. .. _TgCrypto: https://github.com/pyrogram/tgcrypto -.. _Smart Plugin: topics/smart-plugins -.. _advanced action: topics/advanced-usage What can MTProto do more than the Bot API? ------------------------------------------ -For a detailed answer, please refer to the `MTProto vs. Bot API`_ page. - -.. _MTProto vs. Bot API: topics/mtproto-vs-botapi +For a detailed answer, please refer to the :doc:`MTProto vs. Bot API ` page. Why do I need an API key for bots? ---------------------------------- @@ -97,9 +94,9 @@ Telegram is slowly changing some server's internals and it's doing it in such a inevitably. Not only this, but it seems that the new, hypothetical, file ids could also possibly expire at anytime, thus losing the *persistence* feature. -This change will most likely affect the official `Bot API `_ too -(unless Telegram implements some workarounds server-side to keep backwards compatibility, which Pyrogram could in turn -make use of) and we can expect a proper notice from Telegram. +This change will most likely affect the official :doc:`Bot API ` too (unless Telegram +implements some workarounds server-side to keep backwards compatibility, which Pyrogram could in turn make use of) and +we can expect a proper notice from Telegram. Can I use multiple clients at once on the same account? ------------------------------------------------------- @@ -125,8 +122,8 @@ from the beginning every time, and use one separate session for each parallel cl I started a client and nothing happens! --------------------------------------- -If you are connecting from Russia, China or Iran `you need a proxy`_, because Telegram could be partially or -totally blocked in those countries. +If you are connecting from Russia, China or Iran :doc:`you need a proxy `, because Telegram could be +partially or totally blocked in those countries. Another possible cause might be network issues, either yours or Telegram's. To confirm this, add the following code on the top of your script and run it again. You should see some error mentioning a socket timeout or an unreachable network @@ -146,8 +143,6 @@ fails or not: - DC4: ``149.154.167.91`` - DC5: ``91.108.56.149`` -.. _you need a proxy: topics/proxy - I keep getting PEER_ID_INVALID error! ------------------------------------------- @@ -182,20 +177,5 @@ recover@telegram.org, contact `@smstelegram`_ on Twitter or use `this form`_. .. _@smstelegram: https://twitter.com/smstelegram .. _this form: https://telegram.org/support -About the License ------------------ - -.. image:: https://www.gnu.org/graphics/lgplv3-with-text-154x68.png - :align: left - -Pyrogram is free software and is currently licensed under the terms of the -`GNU Lesser General Public License v3 or later (LGPLv3+)`_. In short: you may use, redistribute and/or modify it -provided that modifications are described and licensed for free under LGPLv3+. - -In other words: you can use and integrate Pyrogram into your own code --- either open source, under the same or -different license, or even proprietary --- without being required to release the source code of your own applications. -However, any modifications to the library itself are required to be published for free under the same LGPLv3+ license. - -.. _GNU Lesser General Public License v3 or later (LGPLv3+): https://github.com/pyrogram/pyrogram/blob/develop/COPYING.lesser .. _Bug Report: https://github.com/pyrogram/pyrogram/issues/new?labels=bug&template=bug_report.md .. _Feature Request: https://github.com/pyrogram/pyrogram/issues/new?labels=enhancement&template=feature_request.md diff --git a/docs/source/glossary.rst b/docs/source/glossary.rst index 5f00cbfd..72d308b7 100644 --- a/docs/source/glossary.rst +++ b/docs/source/glossary.rst @@ -18,7 +18,7 @@ general. Some words may as well link to dedicated articles in case the topic is API key A secret code used to authenticate and/or authorize a specific application to Telegram in order for it to control how the API is being used, for example, to prevent abuses of the API. - `More on API keys `_. + :doc:`More on API keys `. DC Also known as *data center*, is a place where lots of computer systems are housed and used together in order to @@ -30,21 +30,21 @@ general. Some words may as well link to dedicated articles in case the topic is RPCError An error caused by an RPC which must be returned in place of the successful result in order to let the caller - know something went wrong. `More on RPCError `_. + know something went wrong. :doc:`More on RPCError `. MTProto The name of the custom-made, open and encrypted protocol by Telegram, implemented in Pyrogram. - `More on MTProto `_. + :doc:`More on MTProto `. MTProto API The Telegram main API Pyrogram makes use of, which is able to connect both users and normal bots to Telegram using MTProto as application layer protocol and execute any method Telegram provides from its public TL-schema. - `More on MTProto API `_. + :doc:`More on MTProto API `. Bot API The Telegram Bot API that is able to only connect normal bots only to Telegram using HTTP as application layer protocol and allows to execute a sub-set of the main Telegram API. - `More on Bot API `_. + :doc:`More on Bot API `. Pyrogrammer A developer that uses Pyrogram to build Telegram applications. @@ -65,11 +65,11 @@ general. Some words may as well link to dedicated articles in case the topic is Handler An object that wraps around a callback function that is *actually meant* to be registered into the framework, which will then be able to handle a specific kind of events, such as a new incoming message, for example. - `More on Handlers `_. + :doc:`More on Handlers `. Decorator Also known as *function decorator*, in Python, is a callable object that is used to modify another function. Decorators in Pyrogram are used to automatically register callback functions for handling updates. - `More on Decorators `_. + :doc:`More on Decorators `. .. _Feature Request: https://github.com/pyrogram/pyrogram/issues/new?labels=enhancement&template=feature_request.md diff --git a/docs/source/index.rst b/docs/source/index.rst index de91015f..b99fcf3d 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -42,10 +42,9 @@ Welcome to Pyrogram **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 -`MTProto API`_. +:doc:`MTProto API `. .. _Telegram: https://telegram.org -.. _MTProto API: topics/mtproto-vs-botapi#what-is-the-mtproto-api How the Documentation is Organized ---------------------------------- @@ -60,15 +59,10 @@ First Steps .. hlist:: :columns: 2 - - `Quick Start`_: Overview to get you started quickly. - - `Calling Methods`_: How to call Pyrogram's methods. - - `Handling Updates`_: How to handle Telegram updates. - - `Error Handling`_: How to handle API errors correctly. - -.. _Quick Start: intro/quickstart -.. _Calling Methods: start/invoking -.. _Handling Updates: start/updates -.. _Error Handling: start/errors + - :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 ------------- @@ -76,15 +70,10 @@ API Reference .. hlist:: :columns: 2 - - `Pyrogram Client`_: Reference details about the Client class. - - `Available Methods`_: List of available high-level methods. - - `Available Types`_: List of available high-level types. - - `Bound Methods`_: List of convenient bound methods. - -.. _Pyrogram Client: ./api/client -.. _Available Methods: api/methods -.. _Available Types: api/types -.. _Bound Methods: api/bound-methods + - :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 ---- @@ -92,17 +81,12 @@ Meta .. hlist:: :columns: 2 - - `Pyrogram FAQ`_: Answers to common Pyrogram questions. - - `Pyrogram Glossary`_: List of words with brief explanations. - - `Release Notes`_: Release notes for Pyrogram releases. - - `Powered by Pyrogram`_: Collection of Pyrogram Projects. - - `Support Pyrogram`_: Ways to show your appreciation. - -.. _Pyrogram FAQ: faq -.. _Pyrogram Glossary: glossary -.. _Release Notes: releases -.. _Powered by Pyrogram: powered-by -.. _Support Pyrogram: support-pyrogram + - :doc:`Pyrogram FAQ `: Answers to common Pyrogram questions. + - :doc:`Pyrogram Glossary `: List of words with brief explanations. + - :doc:`Release Notes `: Release notes for Pyrogram releases. + - :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. .. toctree:: :hidden: @@ -163,10 +147,13 @@ Meta releases powered-by support-pyrogram + license .. toctree:: :hidden: :caption: Telegram API telegram/functions/index - telegram/types/index \ No newline at end of file + telegram/types/index + +Last updated on |today| \ No newline at end of file diff --git a/docs/source/intro/install.rst b/docs/source/intro/install.rst index fe804e79..82ab4c0b 100644 --- a/docs/source/intro/install.rst +++ b/docs/source/intro/install.rst @@ -20,7 +20,7 @@ Install Pyrogram $ pip3 install -U pyrogram -- or, with TgCrypto_ as extra requirement (recommended): +- or, with :doc:`TgCrypto <../topics/tgcrypto>` as extra requirement (recommended): .. code-block:: text @@ -89,5 +89,4 @@ If no error shows up you are good to go. >>> pyrogram.__version__ '|version|' -.. _TgCrypto: ../topics/tgcrypto .. _`Github repo`: http://github.com/pyrogram/pyrogram diff --git a/docs/source/intro/quickstart.rst b/docs/source/intro/quickstart.rst index 1aa7989e..a7a7e377 100644 --- a/docs/source/intro/quickstart.rst +++ b/docs/source/intro/quickstart.rst @@ -43,7 +43,7 @@ Enjoy the API That was just a quick overview that barely scratched the surface! In the next few pages of the introduction, we'll take a much more in-depth look of what we have just done above. -Feeling eager to continue? You can take a shortcut to `Calling Methods`_ and come back later to learn some more details. +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 -.. _Calling Methods: ../start/invoking \ No newline at end of file diff --git a/docs/source/intro/setup.rst b/docs/source/intro/setup.rst index 9c0cc6d4..6273b2b2 100644 --- a/docs/source/intro/setup.rst +++ b/docs/source/intro/setup.rst @@ -1,8 +1,8 @@ Project Setup ============= -We have just `installed Pyrogram`_. In this page we'll discuss what you need to do in order to set up a project with -the library. Let's see how it's done. +We have just :doc:`installed Pyrogram `. In this page we'll discuss what you need to do in order to set up a +project with the library. Let's see how it's done. API Keys -------- @@ -26,7 +26,7 @@ The very first step requires you to obtain a valid Telegram API key (API id/hash Configuration ------------- -Having the API key from the `previous step <#api-keys>`_ in handy, we can now begin to configure a Pyrogram project. +Having the API key from the previous step in handy, we can now begin to configure a Pyrogram project. There are two ways to do so, and you can choose what fits better for you: - First option (recommended): create a new ``config.ini`` file at the root of your working directory, copy-paste the @@ -57,5 +57,3 @@ There are two ways to do so, and you can choose what fits better for you: To keep code snippets clean and concise, from now on it is assumed you are making use of the ``config.ini`` file, thus, the *api_id* and *api_hash* parameters usage won't be shown anymore. - -.. _installed Pyrogram: install.html diff --git a/docs/source/license.rst b/docs/source/license.rst new file mode 100644 index 00000000..1c8d99d1 --- /dev/null +++ b/docs/source/license.rst @@ -0,0 +1,15 @@ +About the License +================= + +.. image:: https://www.gnu.org/graphics/lgplv3-with-text-154x68.png + :align: left + +Pyrogram is free software and is currently licensed under the terms of the +`GNU Lesser General Public License v3 or later (LGPLv3+)`_. In short: you may use, redistribute and/or modify it +provided that modifications are described and licensed for free under LGPLv3+. + +In other words: you can use and integrate Pyrogram into your own code --- either open source, under the same or +different license, or even proprietary --- without being required to release the source code of your own applications. +However, any modifications to the library itself are required to be published for free under the same LGPLv3+ license. + +.. _GNU Lesser General Public License v3 or later (LGPLv3+): https://github.com/pyrogram/pyrogram/blob/develop/COPYING.lesser \ No newline at end of file diff --git a/docs/source/start/auth.rst b/docs/source/start/auth.rst index e00b08a0..79264bfa 100644 --- a/docs/source/start/auth.rst +++ b/docs/source/start/auth.rst @@ -1,7 +1,7 @@ Authorization ============= -Once a `project is set up`_, you will still have to follow a few steps before you can actually use Pyrogram to make +Once a :doc:`project is set up <../intro/setup>`, you will still have to follow a few steps before you can actually use Pyrogram to make API calls. This section provides all the information you need in order to authorize yourself as user or bot. User Authorization @@ -9,8 +9,8 @@ User Authorization In order to use the API, Telegram requires that users be authorized via their phone numbers. Pyrogram automatically manages this process, all you need to do is create an instance of the -:class:`Client ` class by passing to it a ``session_name`` of your choice (e.g.: "my_account") and call -the :meth:`run() ` method: +:class:`~pyrogram.Client` class by passing to it a ``session_name`` of your choice (e.g.: "my_account") and call +the :meth:`~pyrogram.Client.run` method: .. code-block:: python @@ -47,7 +47,7 @@ Bot Authorization Bots are a special kind of users that are authorized via their tokens (instead of phone numbers), which are created by the `Bot Father`_. Bot tokens replace the users' phone numbers only — you still need to -`configure a Telegram API key <../intro/setup#configuration>`_ with Pyrogram, even when using bots. +:doc:`configure a Telegram API key <../intro/setup>` with Pyrogram, even when using bots. The authorization process is automatically managed. All you need to do is choose a ``session_name`` (can be anything, usually your bot username) and pass your bot token using the ``bot_token`` parameter. The session file will be named @@ -64,6 +64,5 @@ after the session name, which will be ``my_bot.session`` for the example below. app.run() -.. _project is set up: ../intro/setup .. _Country Code: https://en.wikipedia.org/wiki/List_of_country_calling_codes .. _Bot Father: https://t.me/botfather \ No newline at end of file diff --git a/docs/source/start/invoking.rst b/docs/source/start/invoking.rst index ef9bc373..1357cd7b 100644 --- a/docs/source/start/invoking.rst +++ b/docs/source/start/invoking.rst @@ -1,8 +1,8 @@ Calling Methods =============== -At this point, we have successfully `installed Pyrogram`_ and authorized_ our account; we are now aiming towards the -core of the library. It's time to start playing with the API! +At this point, we have successfully :doc:`installed Pyrogram <../intro/install>` and :doc:`authorized ` our +account; we are now aiming towards the core of the library. It's time to start playing with the API! Basic Usage ----------- @@ -63,8 +63,8 @@ Context Manager --------------- You can also use Pyrogram's Client in a context manager with the ``with`` statement. The client will automatically -:meth:`start() ` and :meth:`stop() ` gracefully, even in case of unhandled -exceptions in your code. The example above can be therefore rewritten in a much nicer way: +:meth:`~pyrogram.Client.start` and :meth:`~pyrogram.Client.stop` gracefully, even in case of unhandled exceptions in +your code. The example above can be therefore rewritten in a much nicer way: .. code-block:: python @@ -79,6 +79,3 @@ exceptions in your code. The example above can be therefore rewritten in a much app.send_sticker("me", "CAADBAADyg4AAvLQYAEYD4F7vcZ43AI") More examples can be found on `GitHub `_. - -.. _installed Pyrogram: ../intro/install.html -.. _authorized: ../intro/setup.html diff --git a/docs/source/start/updates.rst b/docs/source/start/updates.rst index a0f2ca0c..b6838ad3 100644 --- a/docs/source/start/updates.rst +++ b/docs/source/start/updates.rst @@ -1,8 +1,8 @@ Handling Updates ================ -Calling `API methods`_ sequentially is cool, but how to react when, for example, a new message arrives? This page deals -with updates and how to handle such events in Pyrogram. Let's have a look at how they work. +Calling :doc:`API methods ` sequentially is cool, but how to react when, for example, a new message arrives? +This page deals with updates and how to handle such events in Pyrogram. Let's have a look at how they work. Defining Updates ---------------- @@ -10,7 +10,7 @@ Defining Updates First, let's define what are these updates. As hinted already, updates are simply events that happen in your Telegram account (incoming messages, new members join, bot button presses, etc...), which are meant to notify you about a new specific state that has changed. These updates are handled by registering one or more callback functions in your app -using `Handlers <../api/handlers>`_. +using :doc:`Handlers <../api/handlers>`. Each handler deals with a specific event and once a matching update arrives from Telegram, your registered callback function will be called back by the framework and its body executed. @@ -18,17 +18,16 @@ function will be called back by the framework and its body executed. Registering a Handler --------------------- -To explain how handlers work let's have a look at the most used one, the -:obj:`MessageHandler `, which will be in charge for handling :obj:`Message ` -updates coming from all around your chats. Every other handler shares the same setup logic; you should not have troubles -settings them up once you learn from this section. +To explain how handlers work let's have a look at the most used one, the :class:`~pyrogram.MessageHandler`, which will +be in charge for handling :class:`~pyrogram.Message` updates coming from all around your chats. Every other handler shares +the same setup logic; you should not have troubles settings them up once you learn from this section. Using add_handler() ------------------- -The :meth:`add_handler() ` method takes any handler instance that wraps around your defined -callback function and registers it in your Client. Here's a full example that prints out the content of a message as -soon as it arrives: +The :meth:`~pyrogram.Client.add_handler` method takes any handler instance that wraps around your defined callback +function and registers it in your Client. Here's a full example that prints out the content of a message as soon as it +arrives: .. code-block:: python @@ -55,24 +54,23 @@ call that function by passing the client instance and the new message instance a def my_function(client, message): print(message) -Second one: the :obj:`MessageHandler `. This object tells Pyrogram the function we defined -above must only handle updates that are in form of a :obj:`Message `: +Second one: the :class:`~pyrogram.MessageHandler`. This object tells Pyrogram the function we defined above must only +handle updates that are in form of a :class:`~pyrogram.Message`: .. code-block:: python my_handler = MessageHandler(my_function) -Third: the method :meth:`add_handler() `. This method is used to actually register the -handler and let Pyrogram know it needs to be taken into consideration when new updates arrive and the internal -dispatching phase begins. +Third: the method :meth:`~pyrogram.Client.add_handler`. This method is used to actually register the handler and let +Pyrogram know it needs to be taken into consideration when new updates arrive and the internal dispatching phase begins. .. code-block:: python app.add_handler(my_handler) -Last one, the :meth:`run() ` method. What this does is simply call -:meth:`start() ` and a special method :meth:`idle() ` that keeps your main -scripts alive until you press ``CTRL+C``; the client will be automatically stopped after that. +Last one, the :meth:`~pyrogram.Client.run` method. What this does is simply call :meth:`~pyrogram.Client.start` and a +special method :meth:`~pyrogram.Client.idle` that keeps your main scripts alive until you press ``CTRL+C``; the client +will be automatically stopped after that. .. code-block:: python @@ -82,7 +80,7 @@ Using Decorators ---------------- All of the above will become quite verbose, especially in case you have lots of handlers to register. A much nicer way -to do so is by decorating your callback function with the :meth:`on_message() ` decorator. +to do so is by decorating your callback function with the :meth:`~pyrogram.Client.on_message` decorator. .. code-block:: python @@ -108,5 +106,3 @@ to do so is by decorating your callback function with the :meth:`on_message()

` and facade +:doc:`types <../api/types>`, exists to provide a much easier interface to the undocumented and often confusing Telegram +API. In this section, you'll be shown the alternative way of communicating with Telegram using Pyrogram: the main "raw" Telegram API with its functions and types. @@ -11,7 +12,7 @@ Telegram Raw API ---------------- If you can't find a high-level method for your needs or if you want complete, low-level access to the whole -Telegram API, you have to use the raw :mod:`functions ` and :mod:`types `. +Telegram API, you have to use the raw :mod:`~pyrogram.api.functions` and :mod:`~pyrogram.api.types`. As already hinted, raw functions and types can be really confusing, mainly because people don't realize soon enough they accept *only* the right types and that all required parameters must be filled in. This section will therefore explain @@ -21,24 +22,25 @@ some pitfalls to take into consideration when working with the raw API. Every available high-level methods in Pyrogram is built on top of these raw functions. - Nothing stops you from using the raw functions only, but they are rather complex and `plenty of them`_ are already - re-implemented by providing a much simpler and cleaner interface which is very similar to the Bot API (yet much more - powerful). + Nothing stops you from using the raw functions only, but they are rather complex and + :doc:`plenty of them <../api/methods>` are already re-implemented by providing a much simpler and cleaner interface + which is very similar to the Bot API (yet much more powerful). If you think a raw function should be wrapped and added as a high-level method, feel free to ask in our Community_! Invoking Functions ^^^^^^^^^^^^^^^^^^ -Unlike the methods_ found in Pyrogram's API, which can be called in the usual simple way, functions to be invoked from -the raw Telegram API have a different way of usage and are more complex. +Unlike the :doc:`methods <../api/methods>` found in Pyrogram's API, which can be called in the usual simple way, +functions to be invoked from the raw Telegram API have a different way of usage and are more complex. -First of all, both `raw functions`_ and `raw types`_ live in their respective packages (and sub-packages): -``pyrogram.api.functions``, ``pyrogram.api.types``. They all exist as Python classes, meaning you need to create an -instance of each every time you need them and fill them in with the correct values using named arguments. +First of all, both :doc:`raw functions <../telegram/functions/index>` and :doc:`raw types <../telegram/types/index>` live in their +respective packages (and sub-packages): ``pyrogram.api.functions``, ``pyrogram.api.types``. They all exist as Python +classes, meaning you need to create an instance of each every time you need them and fill them in with the correct +values using named arguments. -Next, to actually invoke the raw function you have to use the :meth:`send() ` method provided by -the Client class and pass the function object you created. +Next, to actually invoke the raw function you have to use the :meth:`~pyrogram.Client.send` method provided by the +Client class and pass the function object you created. Here's some examples: @@ -101,12 +103,12 @@ sending messages with IDs only thanks to cached access hashes. There are three different InputPeer types, one for each kind of Telegram entity. Whenever an InputPeer is needed you must pass one of these: - - :obj:`InputPeerUser <../telegram/types/InputPeerUser>` - Users - - :obj:`InputPeerChat <../telegram/types/InputPeerChat>` - Basic Chats - - :obj:`InputPeerChannel <../telegram/types/InputPeerChannel>` - Either Channels or Supergroups + - :class:`~pyrogram.api.types.InputPeerUser` - Users + - :class:`~pyrogram.api.types.InputPeerChat` - Basic Chats + - :class:`~pyrogram.api.types.InputPeerChannel` - Either Channels or Supergroups But you don't necessarily have to manually instantiate each object because, luckily for you, Pyrogram already provides -:meth:`resolve_peer() ` as a convenience utility method that returns the correct InputPeer +:meth:`~pyrogram.Client.resolve_peer` as a convenience utility method that returns the correct InputPeer by accepting a peer ID only. Another thing to take into consideration about chat IDs is the way they are represented: they are all integers and @@ -125,9 +127,4 @@ For example, given the ID *123456789*, here's how Pyrogram can tell entities apa So, every time you take a raw ID, make sure to translate it into the correct ID when you want to use it with an high-level method. -.. _methods: ../api/methods -.. _types: ../api/types -.. _plenty of them: ../api/methods -.. _raw functions: ../telegram/functions -.. _raw types: ../telegram/types .. _Community: https://t.me/Pyrogram \ No newline at end of file diff --git a/docs/source/topics/auto-auth.rst b/docs/source/topics/auto-auth.rst index b5f3a94a..abeaf1fb 100644 --- a/docs/source/topics/auto-auth.rst +++ b/docs/source/topics/auto-auth.rst @@ -3,7 +3,7 @@ Auto Authorization Manually writing phone number, phone code and password on the terminal every time you want to login can be tedious. Pyrogram is able to automate both **Log In** and **Sign Up** processes, all you need to do is pass the relevant -parameters when creating a new :class:`Client `. +parameters when creating a new :class:`~pyrogram.Client`. .. note:: If you omit any of the optional parameter required for the authorization, Pyrogram will ask you to manually write it. For instance, if you don't want to set a ``last_name`` when creating a new account you diff --git a/docs/source/topics/bots-interaction.rst b/docs/source/topics/bots-interaction.rst index de7925a2..ad993050 100644 --- a/docs/source/topics/bots-interaction.rst +++ b/docs/source/topics/bots-interaction.rst @@ -7,8 +7,7 @@ Inline Bots ----------- - If a bot accepts inline queries, you can call it by using - :meth:`get_inline_bot_results() ` to get the list of its inline results - for a query: + :meth:`~pyrogram.Client.get_inline_bot_results` to get the list of its inline results for a query: .. code-block:: python @@ -24,7 +23,7 @@ Inline Bots results list. - After you retrieved the bot results, you can use - :meth:`send_inline_bot_result() ` to send a chosen result to any chat: + :meth:`~pyrogram.Client.send_inline_bot_result` to send a chosen result to any chat: .. code-block:: python diff --git a/docs/source/topics/filters.rst b/docs/source/topics/filters.rst index cb2e2a4c..7ff02ffc 100644 --- a/docs/source/topics/filters.rst +++ b/docs/source/topics/filters.rst @@ -4,7 +4,7 @@ Using Filters So far we've seen how to register a callback function that executes every time a specific update comes from the server, but there's much more than that to come. -Here we'll discuss about :class:`Filters `. Filters enable a fine-grain control over what kind of +Here we'll discuss about :class:`~pyrogram.Filters`. Filters enable a fine-grain control over what kind of updates are allowed or not to be passed in your callback functions, based on their inner details. Single Filters @@ -12,7 +12,7 @@ Single Filters Let's start right away with a simple example: -- This example will show you how to **only** handle messages containing an :obj:`Audio ` object and +- This example will show you how to **only** handle messages containing an :class:`~pyrogram.Audio` object and ignore any other message. Filters are passed as the first argument of the decorator: .. code-block:: python @@ -69,7 +69,7 @@ Here are some examples: Advanced Filters ---------------- -Some filters, like :meth:`command() ` or :meth:`regex() ` +Some filters, like :meth:`~pyrogram.Filters.command` or :meth:`~pyrogram.Filters.regex` can also accept arguments: - Message is either a */start* or */help* **command**. @@ -109,18 +109,18 @@ More handlers using different filters can also live together. Custom Filters -------------- -Pyrogram already provides lots of built-in :class:`Filters ` to work with, but in case you can't find +Pyrogram already provides lots of built-in :class:`~pyrogram.Filters` to work with, but in case you can't find a specific one for your needs or want to build a custom filter by yourself (to be used in a different kind of handler, -for example) you can use :meth:`Filters.create() `. +for example) you can use :meth:`~pyrogram.Filters.create`. .. note:: - At the moment, the built-in filters are intended to be used with the :obj:`MessageHandler ` - only. + + At the moment, the built-in filters are intended to be used with the :class:`~pyrogram.MessageHandler` only. An example to demonstrate how custom filters work is to show how to create and use one for the -:obj:`CallbackQueryHandler `. Note that callback queries updates are only received by -bots; create and `authorize your bot <../start/Setup.html#bot-authorization>`_, then send a message with an inline -keyboard to yourself. This allows you to test your filter by pressing the inline button: +:class:`~pyrogram.CallbackQueryHandler`. Note that callback queries updates are only received by bots; create and +:doc:`authorize your bot <../start/auth>`, then send a message with an inline keyboard to yourself. This allows you to +test your filter by pressing the inline button: .. code-block:: python @@ -137,7 +137,7 @@ keyboard to yourself. This allows you to test your filter by pressing the inline Basic Filters ^^^^^^^^^^^^^ -For this basic filter we will be using only the first two parameters of :meth:`Filters.create() `. +For this basic filter we will be using only the first two parameters of :meth:`~pyrogram.Filters.create`. The code below creates a simple filter for hardcoded, static callback data. This filter will only allow callback queries containing "Pyrogram" as data, that is, the function *func* you pass returns True in case the callback query data @@ -175,7 +175,7 @@ Filters with Arguments ^^^^^^^^^^^^^^^^^^^^^^ A much cooler filter would be one that accepts "Pyrogram" or any other data as argument at usage time. -A dynamic filter like this will make use of the third parameter of :meth:`Filters.create() `. +A dynamic filter like this will make use of the third parameter of :meth:`~pyrogram.Filters.create`. This is how a dynamic custom filter looks like: diff --git a/docs/source/topics/more-on-updates.rst b/docs/source/topics/more-on-updates.rst index cb319ee1..c3737b38 100644 --- a/docs/source/topics/more-on-updates.rst +++ b/docs/source/topics/more-on-updates.rst @@ -1,7 +1,8 @@ More on Updates =============== -Here we'll show some advanced usages when working with `update handlers`_ and `filters`_. +Here we'll show some advanced usages when working with :doc:`update handlers <../start/updates>` and +:doc:`filters `. Handler Groups -------------- @@ -44,7 +45,7 @@ Or, if you want ``just_text`` to be fired *before* ``text_or_sticker`` (note ``- def just_text(client, message): print("Just Text") -With :meth:`add_handler() ` (without decorators) the same can be achieved with: +With :meth:`~pyrogram.Client.add_handler` (without decorators) the same can be achieved with: .. code-block:: python @@ -217,6 +218,3 @@ The output of both (equivalent) examples will be: 0 1 2 - -.. _`update handlers`: ../start/updates -.. _`filters`: filters \ No newline at end of file diff --git a/docs/source/topics/serialize.rst b/docs/source/topics/serialize.rst index 32208199..a238f8dc 100644 --- a/docs/source/topics/serialize.rst +++ b/docs/source/topics/serialize.rst @@ -9,7 +9,8 @@ For Humans - str(obj) --------------------- If you want a nicely formatted, human readable JSON representation of any object in the API -- namely, any object from -`Pyrogram types`_, `raw functions`_ and `raw types`_ -- you can use use ``str(obj)``. +:doc:`Pyrogram types <../api/types>`, :doc:`raw functions <../telegram/functions/index>` and +:doc:`raw types <../telegram/types/index>` -- you can use use ``str(obj)``. .. code-block:: python @@ -25,10 +26,6 @@ If you want a nicely formatted, human readable JSON representation of any object When using ``print()`` you don't actually need to use ``str()`` on the object because it is called automatically, we have done that above just to show you how to explicitly convert a Pyrogram object to JSON. -.. _Pyrogram types: ../api/types -.. _raw functions: ../telegram/functions -.. _raw types: ../telegram/types - For Machines - repr(obj) ------------------------ diff --git a/docs/source/topics/session-settings.rst b/docs/source/topics/session-settings.rst index 91e3f050..dd777bda 100644 --- a/docs/source/topics/session-settings.rst +++ b/docs/source/topics/session-settings.rst @@ -5,7 +5,7 @@ As you may probably know, Telegram allows users (and bots) having more than one in the system at the same time. Briefly explaining, sessions are simply new logins in your account. They can be reviewed in the settings of an official -app (or by invoking `GetAuthorizations <../telegram/functions/account/GetAuthorizations.html>`_ with Pyrogram). They +app (or by invoking :class:`~pyrogram.api.functions.account.GetAuthorizations` with Pyrogram). They store some useful information such as the client who's using them and from which country and IP address. .. figure:: https://i.imgur.com/YaqtMLO.png diff --git a/docs/source/topics/smart-plugins.rst b/docs/source/topics/smart-plugins.rst index 9f1592d1..8e59b971 100644 --- a/docs/source/topics/smart-plugins.rst +++ b/docs/source/topics/smart-plugins.rst @@ -65,8 +65,8 @@ after importing your modules, like this: app.run() This is already nice and doesn't add *too much* boilerplate code, but things can get boring still; you have to -manually ``import``, manually :meth:`add_handler() ` and manually instantiate each -:obj:`MessageHandler ` object because **you can't use those cool decorators** for your +manually ``import``, manually :meth:`~pyrogram.Client.add_handler` and manually instantiate each +:class:`~pyrogram.MessageHandler` object because **you can't use those cool decorators** for your functions. So, what if you could? Smart Plugins solve this issue by taking care of handlers registration automatically. Using Smart Plugins @@ -80,7 +80,7 @@ Setting up your Pyrogram project to accommodate Smart Plugins is pretty straight .. note:: - This is the same example application `as shown above <#introduction>`_, written using the Smart Plugin system. + This is the same example application as shown above, written using the Smart Plugin system. .. code-block:: text :emphasize-lines: 2, 3 @@ -156,7 +156,7 @@ found inside each module will be, instead, loaded in the order they are defined, .. note:: Remember: there can be at most one handler, within a group, dealing with a specific update. Plugins with overlapping - filters included a second time will not work. Learn more at `More on Updates `_. + filters included a second time will not work. Learn more at :doc:`More on Updates `. This default loading behaviour is usually enough, but sometimes you want to have more control on what to include (or exclude) and in which exact order to load plugins. The way to do this is to make use of ``include`` and ``exclude`` @@ -288,9 +288,8 @@ also organized in subfolders: Load/Unload Plugins at Runtime ------------------------------ -In the `previous section <#specifying-the-plugins-to-include>`_ we've explained how to specify which plugins to load and -which to ignore before your Client starts. Here we'll show, instead, how to unload and load again a previously -registered plugin at runtime. +In the previous section we've explained how to specify which plugins to load and which to ignore before your Client +starts. Here we'll show, instead, how to unload and load again a previously registered plugin at runtime. Each function decorated with the usual ``on_message`` decorator (or any other decorator that deals with Telegram updates ) will be modified in such a way that, when you reference them later on, they will be actually pointing to a tuple of @@ -318,7 +317,7 @@ Unloading ^^^^^^^^^ In order to unload a plugin, or any other handler, all you need to do is obtain a reference to it by importing the -relevant module and call :meth:`remove_handler() ` Client's method with your function +relevant module and call :meth:`~pyrogram.Client.remove_handler` Client's method with your function name preceded by the star ``*`` operator as argument. Example: - ``main.py`` @@ -343,7 +342,7 @@ Loading ^^^^^^^ Similarly to the unloading process, in order to load again a previously unloaded plugin you do the same, but this time -using :meth:`add_handler() ` instead. Example: +using :meth:`~pyrogram.Client.add_handler` instead. Example: - ``main.py`` diff --git a/docs/source/topics/text-formatting.rst b/docs/source/topics/text-formatting.rst index 8f2292d0..bc74d562 100644 --- a/docs/source/topics/text-formatting.rst +++ b/docs/source/topics/text-formatting.rst @@ -12,7 +12,7 @@ Markdown Style -------------- To use this mode, pass "markdown" in the *parse_mode* field when using -:obj:`send_message() `. Use the following syntax in your message: +:meth:`~pyrogram.Client.send_message`. Use the following syntax in your message: .. code-block:: text @@ -34,7 +34,7 @@ To use this mode, pass "markdown" in the *parse_mode* field when using HTML Style ---------- -To use this mode, pass "html" in the *parse_mode* field when using :obj:`send_message() `. +To use this mode, pass "html" in the *parse_mode* field when using :meth:`~pyrogram.Client.send_message`. The following tags are currently supported: .. code-block:: text diff --git a/pyrogram/client/methods/chats/set_chat_photo.py b/pyrogram/client/methods/chats/set_chat_photo.py index 4a2f6cf1..79cceb7e 100644 --- a/pyrogram/client/methods/chats/set_chat_photo.py +++ b/pyrogram/client/methods/chats/set_chat_photo.py @@ -51,7 +51,7 @@ class SetChatPhoto(BaseClient): Raises: RPCError: In case of a Telegram RPC error. - ``ValueError`` if a chat_id belongs to user. + ValueError: if a chat_id belongs to user. """ peer = self.resolve_peer(chat_id) diff --git a/pyrogram/client/types/messages_and_media/message.py b/pyrogram/client/types/messages_and_media/message.py index 09cb9ca3..f8d161c2 100644 --- a/pyrogram/client/types/messages_and_media/message.py +++ b/pyrogram/client/types/messages_and_media/message.py @@ -110,7 +110,7 @@ class Message(PyrogramType, Update): new_chat_photo, delete_chat_photo, group_chat_created, supergroup_chat_created, channel_chat_created, migrate_to_chat_id, migrate_from_chat_id, pinned_message. - media (``bool`` *optional*): + media (``bool``, *optional*): The message is a media message. A media message has one and only one of these fields set: audio, document, photo, sticker, video, animation, voice, video_note, contact, location, venue. From 4eaa891836914d3ad1012b74eef1d9f2f7fb972a Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Tue, 28 May 2019 19:50:21 +0200 Subject: [PATCH 05/50] Update API schema to Layer 100 --- compiler/api/source/main_api.tl | 127 +++++++++++++++++++++----------- 1 file changed, 84 insertions(+), 43 deletions(-) diff --git a/compiler/api/source/main_api.tl b/compiler/api/source/main_api.tl index 61c9faf6..43b02e80 100644 --- a/compiler/api/source/main_api.tl +++ b/compiler/api/source/main_api.tl @@ -22,10 +22,13 @@ inputPeerSelf#7da07ec9 = InputPeer; inputPeerChat#179be863 chat_id:int = InputPeer; inputPeerUser#7b8e7de6 user_id:int access_hash:long = InputPeer; inputPeerChannel#20adaef8 channel_id:int access_hash:long = InputPeer; +inputPeerUserFromMessage#17bae2e6 peer:InputPeer msg_id:int user_id:int = InputPeer; +inputPeerChannelFromMessage#9c95f7bb peer:InputPeer msg_id:int channel_id:int = InputPeer; inputUserEmpty#b98886cf = InputUser; inputUserSelf#f7c1b13f = InputUser; inputUser#d8292816 user_id:int access_hash:long = InputUser; +inputUserFromMessage#2d117597 peer:InputPeer msg_id:int user_id:int = InputUser; inputPhoneContact#f392b7f4 client_id:long phone:string first_name:string last_name:string = InputContact; @@ -60,9 +63,12 @@ inputPhoto#3bb3b94a id:long access_hash:long file_reference:bytes = InputPhoto; inputFileLocation#dfdaabe1 volume_id:long local_id:int secret:long file_reference:bytes = InputFileLocation; inputEncryptedFileLocation#f5235d55 id:long access_hash:long = InputFileLocation; -inputDocumentFileLocation#196683d9 id:long access_hash:long file_reference:bytes = InputFileLocation; +inputDocumentFileLocation#bad07584 id:long access_hash:long file_reference:bytes thumb_size:string = InputFileLocation; inputSecureFileLocation#cbc7ee28 id:long access_hash:long = InputFileLocation; inputTakeoutFileLocation#29be5899 = InputFileLocation; +inputPhotoFileLocation#40181ffe id:long access_hash:long file_reference:bytes thumb_size:string = InputFileLocation; +inputPeerPhotoFileLocation#27d69997 flags:# big:flags.0?true peer:InputPeer volume_id:long local_id:int = InputFileLocation; +inputStickerSetThumb#dbaeae9 stickerset:InputStickerSet volume_id:long local_id:int = InputFileLocation; peerUser#9db1bc6d user_id:int = Peer; peerChat#bad0e5bb chat_id:int = Peer; @@ -79,14 +85,11 @@ storage.fileMov#4b09ebbc = storage.FileType; storage.fileMp4#b3cea0e4 = storage.FileType; storage.fileWebp#1081464c = storage.FileType; -fileLocationUnavailable#7c596b46 volume_id:long local_id:int secret:long = FileLocation; -fileLocation#91d11eb dc_id:int volume_id:long local_id:int secret:long file_reference:bytes = FileLocation; - userEmpty#200250ba id:int = User; -user#2e13f4c3 flags:# self:flags.10?true contact:flags.11?true mutual_contact:flags.12?true deleted:flags.13?true bot:flags.14?true bot_chat_history:flags.15?true bot_nochats:flags.16?true verified:flags.17?true restricted:flags.18?true min:flags.20?true bot_inline_geo:flags.21?true support:flags.23?true id:int access_hash:flags.0?long first_name:flags.1?string last_name:flags.2?string username:flags.3?string phone:flags.4?string photo:flags.5?UserProfilePhoto status:flags.6?UserStatus bot_info_version:flags.14?int restriction_reason:flags.18?string bot_inline_placeholder:flags.19?string lang_code:flags.22?string = User; +user#2e13f4c3 flags:# self:flags.10?true contact:flags.11?true mutual_contact:flags.12?true deleted:flags.13?true bot:flags.14?true bot_chat_history:flags.15?true bot_nochats:flags.16?true verified:flags.17?true restricted:flags.18?true min:flags.20?true bot_inline_geo:flags.21?true support:flags.23?true scam:flags.24?true id:int access_hash:flags.0?long first_name:flags.1?string last_name:flags.2?string username:flags.3?string phone:flags.4?string photo:flags.5?UserProfilePhoto status:flags.6?UserStatus bot_info_version:flags.14?int restriction_reason:flags.18?string bot_inline_placeholder:flags.19?string lang_code:flags.22?string = User; userProfilePhotoEmpty#4f11bae1 = UserProfilePhoto; -userProfilePhoto#d559d8c8 photo_id:long photo_small:FileLocation photo_big:FileLocation = UserProfilePhoto; +userProfilePhoto#ecd75d8c photo_id:long photo_small:FileLocation photo_big:FileLocation dc_id:int = UserProfilePhoto; userStatusEmpty#9d05049 = UserStatus; userStatusOnline#edb93949 expires:int = UserStatus; @@ -98,11 +101,11 @@ userStatusLastMonth#77ebc742 = UserStatus; chatEmpty#9ba2d800 id:int = Chat; chat#3bda1bde flags:# creator:flags.0?true kicked:flags.1?true left:flags.2?true deactivated:flags.5?true id:int title:string photo:ChatPhoto participants_count:int date:int version:int migrated_to:flags.6?InputChannel admin_rights:flags.14?ChatAdminRights default_banned_rights:flags.18?ChatBannedRights = Chat; chatForbidden#7328bdb id:int title:string = Chat; -channel#4df30834 flags:# creator:flags.0?true left:flags.2?true broadcast:flags.5?true verified:flags.7?true megagroup:flags.8?true restricted:flags.9?true signatures:flags.11?true min:flags.12?true id:int access_hash:flags.13?long title:string username:flags.6?string photo:ChatPhoto date:int version:int restriction_reason:flags.9?string admin_rights:flags.14?ChatAdminRights banned_rights:flags.15?ChatBannedRights default_banned_rights:flags.18?ChatBannedRights participants_count:flags.17?int = Chat; +channel#4df30834 flags:# creator:flags.0?true left:flags.2?true broadcast:flags.5?true verified:flags.7?true megagroup:flags.8?true restricted:flags.9?true signatures:flags.11?true min:flags.12?true scam:flags.19?true has_link:flags.20?true id:int access_hash:flags.13?long title:string username:flags.6?string photo:ChatPhoto date:int version:int restriction_reason:flags.9?string admin_rights:flags.14?ChatAdminRights banned_rights:flags.15?ChatBannedRights default_banned_rights:flags.18?ChatBannedRights participants_count:flags.17?int = Chat; channelForbidden#289da732 flags:# broadcast:flags.5?true megagroup:flags.8?true id:int access_hash:long title:string until_date:flags.16?int = Chat; -chatFull#22a235da flags:# can_set_username:flags.7?true id:int about:string participants:ChatParticipants chat_photo:flags.2?Photo notify_settings:PeerNotifySettings exported_invite:ExportedChatInvite bot_info:flags.3?Vector pinned_msg_id:flags.6?int = ChatFull; -channelFull#1c87a71a flags:# can_view_participants:flags.3?true can_set_username:flags.6?true can_set_stickers:flags.7?true hidden_prehistory:flags.10?true can_view_stats:flags.12?true id:int about:string participants_count:flags.0?int admins_count:flags.1?int kicked_count:flags.2?int banned_count:flags.2?int online_count:flags.13?int read_inbox_max_id:int read_outbox_max_id:int unread_count:int chat_photo:Photo notify_settings:PeerNotifySettings exported_invite:ExportedChatInvite bot_info:Vector migrated_from_chat_id:flags.4?int migrated_from_max_id:flags.4?int pinned_msg_id:flags.5?int stickerset:flags.8?StickerSet available_min_id:flags.9?int = ChatFull; +chatFull#1b7c9db3 flags:# can_set_username:flags.7?true id:int about:string participants:ChatParticipants chat_photo:flags.2?Photo notify_settings:PeerNotifySettings exported_invite:ExportedChatInvite bot_info:flags.3?Vector pinned_msg_id:flags.6?int folder_id:flags.11?int = ChatFull; +channelFull#9882e516 flags:# can_view_participants:flags.3?true can_set_username:flags.6?true can_set_stickers:flags.7?true hidden_prehistory:flags.10?true can_view_stats:flags.12?true id:int about:string participants_count:flags.0?int admins_count:flags.1?int kicked_count:flags.2?int banned_count:flags.2?int online_count:flags.13?int read_inbox_max_id:int read_outbox_max_id:int unread_count:int chat_photo:Photo notify_settings:PeerNotifySettings exported_invite:ExportedChatInvite bot_info:Vector migrated_from_chat_id:flags.4?int migrated_from_max_id:flags.4?int pinned_msg_id:flags.5?int stickerset:flags.8?StickerSet available_min_id:flags.9?int folder_id:flags.11?int linked_chat_id:flags.13?int pts:int = ChatFull; chatParticipant#c8d7493e user_id:int inviter_id:int date:int = ChatParticipant; chatParticipantCreator#da13538a user_id:int = ChatParticipant; @@ -112,11 +115,11 @@ chatParticipantsForbidden#fc900c2b flags:# chat_id:int self_participant:flags.0? chatParticipants#3f460fed chat_id:int participants:Vector version:int = ChatParticipants; chatPhotoEmpty#37c1011c = ChatPhoto; -chatPhoto#6153276a photo_small:FileLocation photo_big:FileLocation = ChatPhoto; +chatPhoto#475cdbd5 photo_small:FileLocation photo_big:FileLocation dc_id:int = ChatPhoto; messageEmpty#83e5de54 id:int = Message; -message#44f9b43d flags:# out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true silent:flags.13?true post:flags.14?true from_scheduled:flags.18?true id:int from_id:flags.8?int to_id:Peer fwd_from:flags.2?MessageFwdHeader via_bot_id:flags.11?int reply_to_msg_id:flags.3?int date:int message:string media:flags.9?MessageMedia reply_markup:flags.6?ReplyMarkup entities:flags.7?Vector views:flags.10?int edit_date:flags.15?int post_author:flags.16?string grouped_id:flags.17?long = Message; -messageService#9e19a1f6 flags:# out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true silent:flags.13?true post:flags.14?true id:int from_id:flags.8?int to_id:Peer reply_to_msg_id:flags.3?int date:int action:MessageAction = Message; +message#44f9b43d flags:# out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true silent:flags.13?true post:flags.14?true from_scheduled:flags.18?true legacy:flags.19?true id:int from_id:flags.8?int to_id:Peer fwd_from:flags.2?MessageFwdHeader via_bot_id:flags.11?int reply_to_msg_id:flags.3?int date:int message:string media:flags.9?MessageMedia reply_markup:flags.6?ReplyMarkup entities:flags.7?Vector views:flags.10?int edit_date:flags.15?int post_author:flags.16?string grouped_id:flags.17?long = Message; +messageService#9e19a1f6 flags:# out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true silent:flags.13?true post:flags.14?true legacy:flags.19?true id:int from_id:flags.8?int to_id:Peer reply_to_msg_id:flags.3?int date:int action:MessageAction = Message; messageMediaEmpty#3ded6320 = MessageMedia; messageMediaPhoto#695150d7 flags:# photo:flags.0?Photo ttl_seconds:flags.2?int = MessageMedia; @@ -147,7 +150,7 @@ messageActionHistoryClear#9fbab604 = MessageAction; messageActionGameScore#92a72876 game_id:long score:int = MessageAction; messageActionPaymentSentMe#8f31b327 flags:# currency:string total_amount:long payload:bytes info:flags.0?PaymentRequestedInfo shipping_option_id:flags.1?string charge:PaymentCharge = MessageAction; messageActionPaymentSent#40699cd0 currency:string total_amount:long = MessageAction; -messageActionPhoneCall#80e11a7f flags:# call_id:long reason:flags.0?PhoneCallDiscardReason duration:flags.1?int = MessageAction; +messageActionPhoneCall#80e11a7f flags:# video:flags.2?true call_id:long reason:flags.0?PhoneCallDiscardReason duration:flags.1?int = MessageAction; messageActionScreenshotTaken#4792929b = MessageAction; messageActionCustomAction#fae69f56 message:string = MessageAction; messageActionBotAllowed#abe9affe domain:string = MessageAction; @@ -155,10 +158,11 @@ messageActionSecureValuesSentMe#1b287353 values:Vector credentials: messageActionSecureValuesSent#d95c6154 types:Vector = MessageAction; messageActionContactSignUp#f3f25f76 = MessageAction; -dialog#e4def5db flags:# pinned:flags.2?true unread_mark:flags.3?true peer:Peer top_message:int read_inbox_max_id:int read_outbox_max_id:int unread_count:int unread_mentions_count:int notify_settings:PeerNotifySettings pts:flags.0?int draft:flags.1?DraftMessage = Dialog; +dialog#2c171f72 flags:# pinned:flags.2?true unread_mark:flags.3?true peer:Peer top_message:int read_inbox_max_id:int read_outbox_max_id:int unread_count:int unread_mentions_count:int notify_settings:PeerNotifySettings pts:flags.0?int draft:flags.1?DraftMessage folder_id:flags.4?int = Dialog; +dialogFolder#71bd134c flags:# pinned:flags.2?true folder:Folder peer:Peer top_message:int unread_muted_peers_count:int unread_unmuted_peers_count:int unread_muted_messages_count:int unread_unmuted_messages_count:int = Dialog; photoEmpty#2331b22d id:long = Photo; -photo#9c477dd8 flags:# has_stickers:flags.0?true id:long access_hash:long file_reference:bytes date:int sizes:Vector = Photo; +photo#d07504a5 flags:# has_stickers:flags.0?true id:long access_hash:long file_reference:bytes date:int sizes:Vector dc_id:int = Photo; photoSizeEmpty#e17e23c type:string = PhotoSize; photoSize#77bfb61b type:string location:FileLocation w:int h:int size:int = PhotoSize; @@ -196,7 +200,7 @@ inputReportReasonChildAbuse#adf44ee3 = ReportReason; inputReportReasonOther#e1746d0a text:string = ReportReason; inputReportReasonCopyright#9b89f93a = ReportReason; -userFull#8ea4a881 flags:# blocked:flags.0?true phone_calls_available:flags.4?true phone_calls_private:flags.5?true can_pin_message:flags.7?true user:User about:flags.1?string link:contacts.Link profile_photo:flags.2?Photo notify_settings:PeerNotifySettings bot_info:flags.3?BotInfo pinned_msg_id:flags.6?int common_chats_count:int = UserFull; +userFull#745559cc flags:# blocked:flags.0?true phone_calls_available:flags.4?true phone_calls_private:flags.5?true can_pin_message:flags.7?true user:User about:flags.1?string link:contacts.Link profile_photo:flags.2?Photo notify_settings:PeerNotifySettings bot_info:flags.3?BotInfo pinned_msg_id:flags.6?int common_chats_count:int folder_id:flags.11?int = UserFull; contact#f911c994 user_id:int mutual:Bool = Contact; @@ -221,7 +225,7 @@ messages.dialogsSlice#71e094f3 count:int dialogs:Vector

messages:Vector< messages.dialogsNotModified#f0e3e596 count:int = messages.Dialogs; messages.messages#8c718e87 messages:Vector chats:Vector users:Vector = messages.Messages; -messages.messagesSlice#a6c47aaa flags:# inexact:flags.1?true count:int messages:Vector chats:Vector users:Vector = messages.Messages; +messages.messagesSlice#c8edce1e flags:# inexact:flags.1?true count:int next_rate:flags.0?int messages:Vector chats:Vector users:Vector = messages.Messages; messages.channelMessages#99262e37 flags:# inexact:flags.1?true pts:int count:int messages:Vector chats:Vector users:Vector = messages.Messages; messages.messagesNotModified#74535f21 count:int = messages.Messages; @@ -271,14 +275,14 @@ updateNotifySettings#bec268ef peer:NotifyPeer notify_settings:PeerNotifySettings updateServiceNotification#ebe46819 flags:# popup:flags.0?true inbox_date:flags.1?int type:string message:string media:MessageMedia entities:Vector = Update; updatePrivacy#ee3b272a key:PrivacyKey rules:Vector = Update; updateUserPhone#12b9417b user_id:int phone:string = Update; -updateReadHistoryInbox#9961fd5c peer:Peer max_id:int pts:int pts_count:int = Update; +updateReadHistoryInbox#9c974fdf flags:# folder_id:flags.0?int peer:Peer max_id:int still_unread_count:int pts:int pts_count:int = Update; updateReadHistoryOutbox#2f2f21bf peer:Peer max_id:int pts:int pts_count:int = Update; updateWebPage#7f891213 webpage:WebPage pts:int pts_count:int = Update; updateReadMessagesContents#68c13933 messages:Vector pts:int pts_count:int = Update; updateChannelTooLong#eb0467fb flags:# channel_id:int pts:flags.0?int = Update; updateChannel#b6d45656 channel_id:int = Update; updateNewChannelMessage#62ba04d9 message:Message pts:int pts_count:int = Update; -updateReadChannelInbox#4214f37f channel_id:int max_id:int = Update; +updateReadChannelInbox#330b5424 flags:# folder_id:flags.0?int channel_id:int max_id:int still_unread_count:int pts:int = Update; updateDeleteChannelMessages#c37521c9 channel_id:int messages:Vector pts:int pts_count:int = Update; updateChannelMessageViews#98a12b4b channel_id:int id:int views:int = Update; updateChatParticipantAdmin#b6901959 chat_id:int user_id:int is_admin:Bool version:int = Update; @@ -300,8 +304,8 @@ updateRecentStickers#9a422c20 = Update; updateConfig#a229dd06 = Update; updatePtsChanged#3354678f = Update; updateChannelWebPage#40771900 channel_id:int webpage:WebPage pts:int pts_count:int = Update; -updateDialogPinned#19d27f3c flags:# pinned:flags.0?true peer:DialogPeer = Update; -updatePinnedDialogs#ea4cb65b flags:# order:flags.0?Vector = Update; +updateDialogPinned#6e6fe51c flags:# pinned:flags.0?true folder_id:flags.1?int peer:DialogPeer = Update; +updatePinnedDialogs#fa0f3ca2 flags:# folder_id:flags.1?int order:flags.0?Vector = Update; updateBotWebhookJSON#8317c0c3 data:DataJSON = Update; updateBotWebhookJSONQuery#9b9240a6 query_id:long data:DataJSON timeout:int = Update; updateBotShippingQuery#e0cdc940 query_id:long user_id:int payload:bytes shipping_address:PostAddress = Update; @@ -318,6 +322,7 @@ updateUserPinnedMessage#4c43da18 user_id:int id:int = Update; updateChatPinnedMessage#e10db349 chat_id:int id:int version:int = Update; updateMessagePoll#aca1657b flags:# poll_id:long poll:flags.0?Poll results:PollResults = Update; updateChatDefaultBannedRights#54c01850 peer:Peer default_banned_rights:ChatBannedRights version:int = Update; +updateFolderPeers#19360dc0 folder_peers:Vector pts:int pts_count:int = Update; updates.state#a56c2a3e pts:int qts:int date:int seq:int unread_count:int = updates.State; @@ -344,7 +349,7 @@ upload.fileCdnRedirect#f18cda44 dc_id:int file_token:bytes encryption_key:bytes dcOption#18b7a10d flags:# ipv6:flags.0?true media_only:flags.1?true tcpo_only:flags.2?true cdn:flags.3?true static:flags.4?true id:int ip_address:string port:int secret:flags.10?bytes = DcOption; -config#e6ca25f6 flags:# phonecalls_enabled:flags.1?true default_p2p_contacts:flags.3?true preload_featured_stickers:flags.4?true ignore_phone_entities:flags.5?true revoke_pm_inbox:flags.6?true blocked_mode:flags.8?true pfs_enabled:flags.13?true date:int expires:int test_mode:Bool this_dc:int dc_options:Vector dc_txt_domain_name:string chat_size_max:int megagroup_size_max:int forwarded_count_max:int online_update_period_ms:int offline_blur_timeout_ms:int offline_idle_timeout_ms:int online_cloud_timeout_ms:int notify_cloud_delay_ms:int notify_default_delay_ms:int push_chat_period_ms:int push_chat_limit:int saved_gifs_limit:int edit_time_limit:int revoke_time_limit:int revoke_pm_time_limit:int rating_e_decay:int stickers_recent_limit:int stickers_faved_limit:int channels_read_media_period:int tmp_sessions:flags.0?int pinned_dialogs_count_max:int call_receive_timeout_ms:int call_ring_timeout_ms:int call_connect_timeout_ms:int call_packet_timeout_ms:int me_url_prefix:string autoupdate_url_prefix:flags.7?string gif_search_username:flags.9?string venue_search_username:flags.10?string img_search_username:flags.11?string static_maps_provider:flags.12?string caption_length_max:int message_length_max:int webfile_dc_id:int suggested_lang_code:flags.2?string lang_pack_version:flags.2?int base_lang_pack_version:flags.2?int = Config; +config#330b4067 flags:# phonecalls_enabled:flags.1?true default_p2p_contacts:flags.3?true preload_featured_stickers:flags.4?true ignore_phone_entities:flags.5?true revoke_pm_inbox:flags.6?true blocked_mode:flags.8?true pfs_enabled:flags.13?true date:int expires:int test_mode:Bool this_dc:int dc_options:Vector dc_txt_domain_name:string chat_size_max:int megagroup_size_max:int forwarded_count_max:int online_update_period_ms:int offline_blur_timeout_ms:int offline_idle_timeout_ms:int online_cloud_timeout_ms:int notify_cloud_delay_ms:int notify_default_delay_ms:int push_chat_period_ms:int push_chat_limit:int saved_gifs_limit:int edit_time_limit:int revoke_time_limit:int revoke_pm_time_limit:int rating_e_decay:int stickers_recent_limit:int stickers_faved_limit:int channels_read_media_period:int tmp_sessions:flags.0?int pinned_dialogs_count_max:int pinned_infolder_count_max:int call_receive_timeout_ms:int call_ring_timeout_ms:int call_connect_timeout_ms:int call_packet_timeout_ms:int me_url_prefix:string autoupdate_url_prefix:flags.7?string gif_search_username:flags.9?string venue_search_username:flags.10?string img_search_username:flags.11?string static_maps_provider:flags.12?string caption_length_max:int message_length_max:int webfile_dc_id:int suggested_lang_code:flags.2?string lang_pack_version:flags.2?int base_lang_pack_version:flags.2?int = Config; nearestDc#8e1a1775 country:string this_dc:int nearest_dc:int = NearestDc; @@ -413,6 +418,7 @@ inputPrivacyKeyPhoneCall#fabadc5f = InputPrivacyKey; inputPrivacyKeyPhoneP2P#db9e70d2 = InputPrivacyKey; inputPrivacyKeyForwards#a4dd4c08 = InputPrivacyKey; inputPrivacyKeyProfilePhoto#5719bacc = InputPrivacyKey; +inputPrivacyKeyPhoneNumber#352dafa = InputPrivacyKey; privacyKeyStatusTimestamp#bc2eab30 = PrivacyKey; privacyKeyChatInvite#500e6dfa = PrivacyKey; @@ -420,6 +426,7 @@ privacyKeyPhoneCall#3d662b7b = PrivacyKey; privacyKeyPhoneP2P#39491cc8 = PrivacyKey; privacyKeyForwards#69ec56a3 = PrivacyKey; privacyKeyProfilePhoto#96151fed = PrivacyKey; +privacyKeyPhoneNumber#d19ae46d = PrivacyKey; inputPrivacyValueAllowContacts#d09e07b = InputPrivacyRule; inputPrivacyValueAllowAll#184b35ce = InputPrivacyRule; @@ -427,6 +434,8 @@ inputPrivacyValueAllowUsers#131cc67f users:Vector = InputPrivacyRule; inputPrivacyValueDisallowContacts#ba52007 = InputPrivacyRule; inputPrivacyValueDisallowAll#d66b66c9 = InputPrivacyRule; inputPrivacyValueDisallowUsers#90110467 users:Vector = InputPrivacyRule; +inputPrivacyValueAllowChatParticipants#4c81c1ba chats:Vector = InputPrivacyRule; +inputPrivacyValueDisallowChatParticipants#d82363af chats:Vector = InputPrivacyRule; privacyValueAllowContacts#fffe1bac = PrivacyRule; privacyValueAllowAll#65427b82 = PrivacyRule; @@ -434,8 +443,10 @@ privacyValueAllowUsers#4d5bbe0c users:Vector = PrivacyRule; privacyValueDisallowContacts#f888fa1a = PrivacyRule; privacyValueDisallowAll#8b73e763 = PrivacyRule; privacyValueDisallowUsers#c7f49b7 users:Vector = PrivacyRule; +privacyValueAllowChatParticipants#18be796b chats:Vector = PrivacyRule; +privacyValueDisallowChatParticipants#acae0690 chats:Vector = PrivacyRule; -account.privacyRules#554abb6f rules:Vector users:Vector = account.PrivacyRules; +account.privacyRules#50a04e45 rules:Vector chats:Vector users:Vector = account.PrivacyRules; accountDaysTTL#b8d0afdf days:int = AccountDaysTTL; @@ -459,7 +470,6 @@ messages.affectedMessages#84d19185 pts:int pts_count:int = messages.AffectedMess contactLinkUnknown#5f4f9247 = ContactLink; contactLinkNone#feedd3ad = ContactLink; -contactLinkHasPhone#268f3f59 = ContactLink; contactLinkContact#d502c2d0 = ContactLink; webPageEmpty#eb1477e8 id:long = WebPage; @@ -485,13 +495,13 @@ chatInviteEmpty#69df3769 = ExportedChatInvite; chatInviteExported#fc2e05bc link:string = ExportedChatInvite; chatInviteAlready#5a686d7c chat:Chat = ChatInvite; -chatInvite#db74f558 flags:# channel:flags.0?true broadcast:flags.1?true public:flags.2?true megagroup:flags.3?true title:string photo:ChatPhoto participants_count:int participants:flags.4?Vector = ChatInvite; +chatInvite#dfc2f58e flags:# channel:flags.0?true broadcast:flags.1?true public:flags.2?true megagroup:flags.3?true title:string photo:Photo participants_count:int participants:flags.4?Vector = ChatInvite; inputStickerSetEmpty#ffb62b95 = InputStickerSet; inputStickerSetID#9de7a269 id:long access_hash:long = InputStickerSet; inputStickerSetShortName#861cc8a0 short_name:string = InputStickerSet; -stickerSet#6a90bcb7 flags:# archived:flags.1?true official:flags.2?true masks:flags.3?true installed_date:flags.0?int id:long access_hash:long title:string short_name:string thumb:flags.4?PhotoSize count:int hash:int = StickerSet; +stickerSet#eeb46f27 flags:# archived:flags.1?true official:flags.2?true masks:flags.3?true installed_date:flags.0?int id:long access_hash:long title:string short_name:string thumb:flags.4?PhotoSize thumb_dc_id:flags.4?int count:int hash:int = StickerSet; messages.stickerSet#b60a24a6 set:StickerSet packs:Vector documents:Vector = messages.StickerSet; @@ -507,6 +517,8 @@ keyboardButtonRequestGeoLocation#fc796b3f text:string = KeyboardButton; keyboardButtonSwitchInline#568a748 flags:# same_peer:flags.0?true text:string query:string = KeyboardButton; keyboardButtonGame#50f41ccf text:string = KeyboardButton; keyboardButtonBuy#afd93fbb text:string = KeyboardButton; +keyboardButtonUrlAuth#10b78d29 flags:# text:string fwd_text:flags.0?string url:string button_id:int = KeyboardButton; +inputKeyboardButtonUrlAuth#d02e7fd4 flags:# request_write_access:flags.0?true text:string fwd_text:flags.1?string url:string bot:InputUser = KeyboardButton; keyboardButtonRow#77608b83 buttons:Vector = KeyboardButtonRow; @@ -533,13 +545,14 @@ messageEntityCashtag#4c4e743f offset:int length:int = MessageEntity; inputChannelEmpty#ee8c1e86 = InputChannel; inputChannel#afeb712e channel_id:int access_hash:long = InputChannel; +inputChannelFromMessage#2a286531 peer:InputPeer msg_id:int channel_id:int = InputChannel; contacts.resolvedPeer#7f077ad9 peer:Peer chats:Vector users:Vector = contacts.ResolvedPeer; messageRange#ae30253 min_id:int max_id:int = MessageRange; updates.channelDifferenceEmpty#3e11affb flags:# final:flags.0?true pts:int timeout:flags.1?int = updates.ChannelDifference; -updates.channelDifferenceTooLong#6a9d7b35 flags:# final:flags.0?true pts:int timeout:flags.1?int top_message:int read_inbox_max_id:int read_outbox_max_id:int unread_count:int unread_mentions_count:int messages:Vector chats:Vector users:Vector = updates.ChannelDifference; +updates.channelDifferenceTooLong#a4bcc6fe flags:# final:flags.0?true timeout:flags.1?int dialog:Dialog messages:Vector chats:Vector users:Vector = updates.ChannelDifference; updates.channelDifference#2064674e flags:# final:flags.0?true pts:int timeout:flags.1?int new_messages:Vector other_updates:Vector chats:Vector users:Vector = updates.ChannelDifference; channelMessagesFilterEmpty#94d42ee7 = ChannelMessagesFilter; @@ -628,6 +641,8 @@ topPeerCategoryCorrespondents#637b7ed = TopPeerCategory; topPeerCategoryGroups#bd17a14a = TopPeerCategory; topPeerCategoryChannels#161d9628 = TopPeerCategory; topPeerCategoryPhoneCalls#1e76a78c = TopPeerCategory; +topPeerCategoryForwardUsers#a8406ca9 = TopPeerCategory; +topPeerCategoryForwardChats#fbeec0f0 = TopPeerCategory; topPeerCategoryPeers#fb834291 category:TopPeerCategory count:int peers:Vector = TopPeerCategoryPeers; @@ -767,11 +782,11 @@ inputStickerSetItem#ffa0a496 flags:# document:InputDocument emoji:string mask_co inputPhoneCall#1e36fded id:long access_hash:long = InputPhoneCall; phoneCallEmpty#5366c915 id:long = PhoneCall; -phoneCallWaiting#1b8f4ad1 flags:# id:long access_hash:long date:int admin_id:int participant_id:int protocol:PhoneCallProtocol receive_date:flags.0?int = PhoneCall; -phoneCallRequested#83761ce4 id:long access_hash:long date:int admin_id:int participant_id:int g_a_hash:bytes protocol:PhoneCallProtocol = PhoneCall; -phoneCallAccepted#6d003d3f id:long access_hash:long date:int admin_id:int participant_id:int g_b:bytes protocol:PhoneCallProtocol = PhoneCall; -phoneCall#e6f9ddf3 flags:# p2p_allowed:flags.5?true id:long access_hash:long date:int admin_id:int participant_id:int g_a_or_b:bytes key_fingerprint:long protocol:PhoneCallProtocol connection:PhoneConnection alternative_connections:Vector start_date:int = PhoneCall; -phoneCallDiscarded#50ca4de1 flags:# need_rating:flags.2?true need_debug:flags.3?true id:long reason:flags.0?PhoneCallDiscardReason duration:flags.1?int = PhoneCall; +phoneCallWaiting#1b8f4ad1 flags:# video:flags.5?true id:long access_hash:long date:int admin_id:int participant_id:int protocol:PhoneCallProtocol receive_date:flags.0?int = PhoneCall; +phoneCallRequested#87eabb53 flags:# video:flags.5?true id:long access_hash:long date:int admin_id:int participant_id:int g_a_hash:bytes protocol:PhoneCallProtocol = PhoneCall; +phoneCallAccepted#997c454a flags:# video:flags.5?true id:long access_hash:long date:int admin_id:int participant_id:int g_b:bytes protocol:PhoneCallProtocol = PhoneCall; +phoneCall#8742ae7f flags:# p2p_allowed:flags.5?true id:long access_hash:long date:int admin_id:int participant_id:int g_a_or_b:bytes key_fingerprint:long protocol:PhoneCallProtocol connections:Vector start_date:int = PhoneCall; +phoneCallDiscarded#50ca4de1 flags:# need_rating:flags.2?true need_debug:flags.3?true video:flags.5?true id:long reason:flags.0?PhoneCallDiscardReason duration:flags.1?int = PhoneCall; phoneConnection#9d4c17c0 id:long ip:string ipv6:string port:int peer_tag:bytes = PhoneConnection; @@ -797,7 +812,7 @@ langPackLanguage#eeca5ce3 flags:# official:flags.0?true rtl:flags.2?true beta:fl channelAdminLogEventActionChangeTitle#e6dfb825 prev_value:string new_value:string = ChannelAdminLogEventAction; channelAdminLogEventActionChangeAbout#55188a2e prev_value:string new_value:string = ChannelAdminLogEventAction; channelAdminLogEventActionChangeUsername#6a4afc38 prev_value:string new_value:string = ChannelAdminLogEventAction; -channelAdminLogEventActionChangePhoto#b82f55c3 prev_photo:ChatPhoto new_photo:ChatPhoto = ChannelAdminLogEventAction; +channelAdminLogEventActionChangePhoto#434bd2af prev_photo:Photo new_photo:Photo = ChannelAdminLogEventAction; channelAdminLogEventActionToggleInvites#1b7907ae new_value:Bool = ChannelAdminLogEventAction; channelAdminLogEventActionToggleSignatures#26ae0971 new_value:Bool = ChannelAdminLogEventAction; channelAdminLogEventActionUpdatePinned#e9e82c18 message:Message = ChannelAdminLogEventAction; @@ -812,6 +827,7 @@ channelAdminLogEventActionChangeStickerSet#b1c3caa7 prev_stickerset:InputSticker channelAdminLogEventActionTogglePreHistoryHidden#5f5c95f1 new_value:Bool = ChannelAdminLogEventAction; channelAdminLogEventActionDefaultBannedRights#2df5fc0a prev_banned_rights:ChatBannedRights new_banned_rights:ChatBannedRights = ChannelAdminLogEventAction; channelAdminLogEventActionStopPoll#8f079643 message:Message = ChannelAdminLogEventAction; +channelAdminLogEventActionChangeLinkedChat#a26f881b prev_value:int new_value:int = ChannelAdminLogEventAction; channelAdminLogEvent#3b5a3e40 id:long date:int user_id:int action:ChannelAdminLogEventAction = ChannelAdminLogEvent; @@ -843,8 +859,10 @@ inputMessageReplyTo#bad88395 id:int = InputMessage; inputMessagePinned#86872538 = InputMessage; inputDialogPeer#fcaafeb7 peer:InputPeer = InputDialogPeer; +inputDialogPeerFolder#64600527 folder_id:int = InputDialogPeer; dialogPeer#e56dbf05 peer:Peer = DialogPeer; +dialogPeerFolder#514519e2 folder_id:int = DialogPeer; messages.foundStickerSetsNotModified#d54b65d = messages.FoundStickerSets; messages.foundStickerSets#5108d648 hash:int sets:Vector = messages.FoundStickerSets; @@ -1000,6 +1018,22 @@ emojiKeywordsDifference#5cc761bd lang_code:string from_version:int version:int k emojiURL#a575739d url:string = EmojiURL; +emojiLanguage#b3fb5361 lang_code:string = EmojiLanguage; + +fileLocationToBeDeprecated#bc7fc6cd volume_id:long local_id:int = FileLocation; + +folder#ff544e65 flags:# autofill_new_broadcasts:flags.0?true autofill_public_groups:flags.1?true autofill_new_correspondents:flags.2?true id:int title:string photo:flags.3?ChatPhoto = Folder; + +inputFolderPeer#fbd2c296 peer:InputPeer folder_id:int = InputFolderPeer; + +folderPeer#e9baa668 peer:Peer folder_id:int = FolderPeer; + +messages.searchCounter#e844ebff flags:# inexact:flags.1?true filter:MessagesFilter count:int = messages.SearchCounter; + +urlAuthResultRequest#92d33a0e flags:# request_write_access:flags.0?true bot:User domain:string = UrlAuthResult; +urlAuthResultAccepted#8f8c0e4e url:string = UrlAuthResult; +urlAuthResultDefault#a9d6db1f = UrlAuthResult; + ---functions--- invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X; @@ -1098,14 +1132,14 @@ contacts.unblock#e54100bd id:InputUser = Bool; contacts.getBlocked#f57c350f offset:int limit:int = contacts.Blocked; contacts.search#11f812d8 q:string limit:int = contacts.Found; contacts.resolveUsername#f93ccba3 username:string = contacts.ResolvedPeer; -contacts.getTopPeers#d4982db5 flags:# correspondents:flags.0?true bots_pm:flags.1?true bots_inline:flags.2?true phone_calls:flags.3?true groups:flags.10?true channels:flags.15?true offset:int limit:int hash:int = contacts.TopPeers; +contacts.getTopPeers#d4982db5 flags:# correspondents:flags.0?true bots_pm:flags.1?true bots_inline:flags.2?true phone_calls:flags.3?true forward_users:flags.4?true forward_chats:flags.5?true groups:flags.10?true channels:flags.15?true offset:int limit:int hash:int = contacts.TopPeers; contacts.resetTopPeerRating#1ae373ac category:TopPeerCategory peer:InputPeer = Bool; contacts.resetSaved#879537f1 = Bool; contacts.getSaved#82f1e39f = Vector; contacts.toggleTopPeers#8514bdda enabled:Bool = Bool; messages.getMessages#63c66506 id:Vector = messages.Messages; -messages.getDialogs#b098aee6 flags:# exclude_pinned:flags.0?true offset_date:int offset_id:int offset_peer:InputPeer limit:int hash:int = messages.Dialogs; +messages.getDialogs#a0ee3b73 flags:# exclude_pinned:flags.0?true folder_id:flags.1?int offset_date:int offset_id:int offset_peer:InputPeer limit:int hash:int = messages.Dialogs; messages.getHistory#dcbb8260 peer:InputPeer offset_id:int offset_date:int add_offset:int limit:int max_id:int min_id:int hash:int = messages.Messages; messages.search#8614ef68 flags:# peer:InputPeer q:string from_id:flags.0?InputUser filter:MessagesFilter min_date:int max_date:int offset_id:int add_offset:int limit:int max_id:int min_id:int hash:int = messages.Messages; messages.readHistory#e306d3a peer:InputPeer max_id:int = messages.AffectedMessages; @@ -1152,7 +1186,7 @@ messages.startBot#e6df7378 bot:InputUser peer:InputPeer random_id:long start_par messages.getMessagesViews#c4c8a55d peer:InputPeer id:Vector increment:Bool = Vector; messages.editChatAdmin#a9e69f2e chat_id:int user_id:InputUser is_admin:Bool = Bool; messages.migrateChat#15a3b8e3 chat_id:int = Updates; -messages.searchGlobal#9e3cacb0 q:string offset_date:int offset_peer:InputPeer offset_id:int limit:int = messages.Messages; +messages.searchGlobal#f79c611 q:string offset_rate:int offset_peer:InputPeer offset_id:int limit:int = messages.Messages; messages.reorderStickerSets#78337739 flags:# masks:flags.0?true order:Vector = Bool; messages.getDocumentByHash#338e2464 sha256:bytes size:int mime_type:string = Document; messages.searchGifs#bf9a776b q:string offset:int = messages.FoundGifs; @@ -1185,8 +1219,8 @@ messages.getCommonChats#d0a48c4 user_id:InputUser max_id:int limit:int = message messages.getAllChats#eba80ff0 except_ids:Vector = messages.Chats; messages.getWebPage#32ca8f91 url:string hash:int = WebPage; messages.toggleDialogPin#a731e257 flags:# pinned:flags.0?true peer:InputDialogPeer = Bool; -messages.reorderPinnedDialogs#5b51d63f flags:# force:flags.0?true order:Vector = Bool; -messages.getPinnedDialogs#e254d64e = messages.PeerDialogs; +messages.reorderPinnedDialogs#3b1adf37 flags:# force:flags.0?true folder_id:int order:Vector = Bool; +messages.getPinnedDialogs#d6b94df2 folder_id:int = messages.PeerDialogs; messages.setBotShippingResults#e5f672fa flags:# query_id:long error:flags.0?string shipping_options:flags.1?Vector = Bool; messages.setBotPrecheckoutResults#9c2dd95 flags:# success:flags.1?true query_id:long error:flags.0?string = Bool; messages.uploadMedia#519bc2b1 peer:InputPeer media:InputMedia = MessageMedia; @@ -1212,7 +1246,11 @@ messages.editChatAbout#def60797 peer:InputPeer about:string = Bool; messages.editChatDefaultBannedRights#a5866b41 peer:InputPeer banned_rights:ChatBannedRights = Updates; messages.getEmojiKeywords#35a0e062 lang_code:string = EmojiKeywordsDifference; messages.getEmojiKeywordsDifference#1508b6af lang_code:string from_version:int = EmojiKeywordsDifference; +messages.getEmojiKeywordsLanguages#4e9963b2 lang_codes:Vector = Vector; messages.getEmojiURL#d5b10c26 lang_code:string = EmojiURL; +messages.getSearchCounters#732eef00 peer:InputPeer filters:Vector = Vector; +messages.requestUrlAuth#e33f5613 peer:InputPeer msg_id:int button_id:int = UrlAuthResult; +messages.acceptUrlAuth#f729ea98 flags:# write_allowed:flags.0?true peer:InputPeer msg_id:int button_id:int = UrlAuthResult; updates.getState#edd4882a = updates.State; updates.getDifference#25939651 flags:# pts:int pts_total_limit:flags.0?int date:int qts:int = updates.Difference; @@ -1281,6 +1319,9 @@ channels.readMessageContents#eab5dc38 channel:InputChannel id:Vector = Bool channels.deleteHistory#af369d42 channel:InputChannel max_id:int = Bool; channels.togglePreHistoryHidden#eabbb94c channel:InputChannel enabled:Bool = Updates; channels.getLeftChannels#8341ecc0 offset:int = messages.Chats; +channels.getGroupsForDiscussion#f5dad378 = messages.Chats; +channels.getBroadcastsForDiscussion#1a87f304 = messages.Chats; +channels.setDiscussionGroup#40582bb2 broadcast:InputChannel group:InputChannel = Bool; bots.sendCustomRequest#aa2769ed custom_method:string params:DataJSON = DataJSON; bots.answerWebhookJSONQuery#e6213f4d query_id:long data:DataJSON = Bool; @@ -1298,11 +1339,11 @@ stickers.changeStickerPosition#ffb6d4ca sticker:InputDocument position:int = mes stickers.addStickerToSet#8653febe stickerset:InputStickerSet sticker:InputStickerSetItem = messages.StickerSet; phone.getCallConfig#55451fa9 = DataJSON; -phone.requestCall#5b95b3d4 user_id:InputUser random_id:int g_a_hash:bytes protocol:PhoneCallProtocol = phone.PhoneCall; +phone.requestCall#42ff96ed flags:# video:flags.0?true user_id:InputUser random_id:int g_a_hash:bytes protocol:PhoneCallProtocol = phone.PhoneCall; phone.acceptCall#3bd2b4a0 peer:InputPhoneCall g_b:bytes protocol:PhoneCallProtocol = phone.PhoneCall; phone.confirmCall#2efe1722 peer:InputPhoneCall g_a:bytes key_fingerprint:long protocol:PhoneCallProtocol = phone.PhoneCall; phone.receivedCall#17d54f61 peer:InputPhoneCall = Bool; -phone.discardCall#78d413a6 peer:InputPhoneCall duration:int reason:PhoneCallDiscardReason connection_id:long = Updates; +phone.discardCall#b2cbc1c0 flags:# video:flags.0?true peer:InputPhoneCall duration:int reason:PhoneCallDiscardReason connection_id:long = Updates; phone.setCallRating#59ead627 flags:# user_initiative:flags.0?true peer:InputPhoneCall rating:int comment:string = Updates; phone.saveCallDebug#277add7e peer:InputPhoneCall debug:DataJSON = Bool; @@ -1312,7 +1353,7 @@ langpack.getDifference#cd984aa5 lang_pack:string lang_code:string from_version:i langpack.getLanguages#42c6978f lang_pack:string = Vector; langpack.getLanguage#6a596502 lang_pack:string lang_code:string = LangPackLanguage; -// LAYER 97 +folders.editPeerFolders#6847d0ab folder_peers:Vector = Updates; +folders.deleteFolder#1c295881 folder_id:int = Updates; -// Ports -channels.exportInvite#c7560885 channel:InputChannel = ExportedChatInvite; \ No newline at end of file +// LAYER 100 \ No newline at end of file From c2424029b57e50a3587476900ee842b97feec947 Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Wed, 29 May 2019 09:37:50 +0200 Subject: [PATCH 06/50] Fix dialogs after L100 update --- pyrogram/client/client.py | 4 ++-- pyrogram/client/methods/chats/get_dialogs.py | 2 +- pyrogram/client/methods/chats/get_dialogs_count.py | 2 +- pyrogram/client/methods/chats/iter_dialogs.py | 2 +- pyrogram/client/types/user_and_chats/dialog.py | 2 +- pyrogram/client/types/user_and_chats/dialogs.py | 12 ++++++++++-- 6 files changed, 16 insertions(+), 8 deletions(-) diff --git a/pyrogram/client/client.py b/pyrogram/client/client.py index 8c1e3001..0d1cde19 100644 --- a/pyrogram/client/client.py +++ b/pyrogram/client/client.py @@ -313,7 +313,7 @@ class Client(Methods, BaseClient): self.get_initial_dialogs() self.get_contacts() else: - self.send(functions.messages.GetPinnedDialogs()) + self.send(functions.messages.GetPinnedDialogs(folder_id=0)) self.get_initial_dialogs_chunk() else: self.send(functions.updates.GetState()) @@ -1325,7 +1325,7 @@ class Client(Methods, BaseClient): return r def get_initial_dialogs(self): - self.send(functions.messages.GetPinnedDialogs()) + self.send(functions.messages.GetPinnedDialogs(folder_id=0)) dialogs = self.get_initial_dialogs_chunk() offset_date = utils.get_offset_date(dialogs) diff --git a/pyrogram/client/methods/chats/get_dialogs.py b/pyrogram/client/methods/chats/get_dialogs.py index 605ee782..948a7642 100644 --- a/pyrogram/client/methods/chats/get_dialogs.py +++ b/pyrogram/client/methods/chats/get_dialogs.py @@ -62,7 +62,7 @@ class GetDialogs(BaseClient): while True: try: if pinned_only: - r = self.send(functions.messages.GetPinnedDialogs()) + r = self.send(functions.messages.GetPinnedDialogs(folder_id=0)) else: r = self.send( functions.messages.GetDialogs( diff --git a/pyrogram/client/methods/chats/get_dialogs_count.py b/pyrogram/client/methods/chats/get_dialogs_count.py index b9b0970a..c804709d 100644 --- a/pyrogram/client/methods/chats/get_dialogs_count.py +++ b/pyrogram/client/methods/chats/get_dialogs_count.py @@ -36,7 +36,7 @@ class GetDialogsCount(BaseClient): """ if pinned_only: - return len(self.send(functions.messages.GetPinnedDialogs()).dialogs) + return len(self.send(functions.messages.GetPinnedDialogs(folder_id=0)).dialogs) else: r = self.send( functions.messages.GetDialogs( diff --git a/pyrogram/client/methods/chats/iter_dialogs.py b/pyrogram/client/methods/chats/iter_dialogs.py index 1209a5df..976a49df 100644 --- a/pyrogram/client/methods/chats/iter_dialogs.py +++ b/pyrogram/client/methods/chats/iter_dialogs.py @@ -26,7 +26,7 @@ class IterDialogs(BaseClient): def iter_dialogs( self, offset_date: int = 0, - limit: int = 0 + limit: int = None ) -> Generator["pyrogram.Dialog", None, None]: """Iterate through a user's dialogs sequentially. diff --git a/pyrogram/client/types/user_and_chats/dialog.py b/pyrogram/client/types/user_and_chats/dialog.py index fc691ab6..4b900012 100644 --- a/pyrogram/client/types/user_and_chats/dialog.py +++ b/pyrogram/client/types/user_and_chats/dialog.py @@ -69,7 +69,7 @@ class Dialog(PyrogramType): self.is_pinned = is_pinned @staticmethod - def _parse(client, dialog, messages, users, chats) -> "Dialog": + def _parse(client, dialog: types.Dialog, messages, users, chats) -> "Dialog": chat_id = dialog.peer if isinstance(chat_id, types.PeerUser): diff --git a/pyrogram/client/types/user_and_chats/dialogs.py b/pyrogram/client/types/user_and_chats/dialogs.py index 0d6a0935..862fcf22 100644 --- a/pyrogram/client/types/user_and_chats/dialogs.py +++ b/pyrogram/client/types/user_and_chats/dialogs.py @@ -51,7 +51,7 @@ class Dialogs(PyrogramType): self.dialogs = dialogs @staticmethod - def _parse(client, dialogs) -> "Dialogs": + def _parse(client, dialogs: types.messages.Dialogs) -> "Dialogs": users = {i.id: i for i in dialogs.users} chats = {i.id: i for i in dialogs.chats} @@ -72,8 +72,16 @@ class Dialogs(PyrogramType): messages[chat_id] = Message._parse(client, message, users, chats) + parsed_dialogs = [] + + for dialog in dialogs.dialogs: + if not isinstance(dialog, types.Dialog): + continue + + parsed_dialogs.append(Dialog._parse(client, dialog, messages, users, chats)) + return Dialogs( total_count=getattr(dialogs, "count", len(dialogs.dialogs)), - dialogs=[Dialog._parse(client, dialog, messages, users, chats) for dialog in dialogs.dialogs], + dialogs=parsed_dialogs, client=client ) From 1390797f5853bb64a3e8f79ae673f932d1a272f1 Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Wed, 29 May 2019 09:41:04 +0200 Subject: [PATCH 07/50] Rename delete_user_profile_photos to just delete_photos. It's implied an user can only delete own photos. --- .../users/{delete_user_profile_photos.py => delete_photos.py} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename pyrogram/client/methods/users/{delete_user_profile_photos.py => delete_photos.py} (96%) diff --git a/pyrogram/client/methods/users/delete_user_profile_photos.py b/pyrogram/client/methods/users/delete_photos.py similarity index 96% rename from pyrogram/client/methods/users/delete_user_profile_photos.py rename to pyrogram/client/methods/users/delete_photos.py index 305fd554..30b3b533 100644 --- a/pyrogram/client/methods/users/delete_user_profile_photos.py +++ b/pyrogram/client/methods/users/delete_photos.py @@ -24,8 +24,8 @@ from pyrogram.api import functions, types from ...ext import BaseClient -class DeleteUserProfilePhotos(BaseClient): - def delete_user_profile_photos( +class DeletePhotos(BaseClient): + def delete_photos( self, id: Union[str, List[str]] ) -> bool: From 83cd82838642425d1bd2137f9a5ead7280d28c1c Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Wed, 29 May 2019 09:41:59 +0200 Subject: [PATCH 08/50] Rename get_user_profile_photos_count to get_user_photos_count --- ..._user_profile_photos_count.py => get_user_photos_count.py} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename pyrogram/client/methods/users/{get_user_profile_photos_count.py => get_user_photos_count.py} (93%) diff --git a/pyrogram/client/methods/users/get_user_profile_photos_count.py b/pyrogram/client/methods/users/get_user_photos_count.py similarity index 93% rename from pyrogram/client/methods/users/get_user_profile_photos_count.py rename to pyrogram/client/methods/users/get_user_photos_count.py index 7870d003..3bbaf55b 100644 --- a/pyrogram/client/methods/users/get_user_profile_photos_count.py +++ b/pyrogram/client/methods/users/get_user_photos_count.py @@ -22,8 +22,8 @@ from pyrogram.api import functions, types from ...ext import BaseClient -class GetUserProfilePhotosCount(BaseClient): - def get_user_profile_photos_count(self, user_id: Union[int, str]) -> int: +class GetUserPhotosCount(BaseClient): + def get_user_photos_count(self, user_id: Union[int, str]) -> int: """Get the total count of profile pictures for a user. Parameters: From 86a4f63d37f267c5a9ba250df3a95bcbe9dc508a Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Wed, 29 May 2019 09:42:55 +0200 Subject: [PATCH 09/50] Rename set_user_profile_photo to set_photo Users can only set a photo for themselves. --- .../methods/users/{set_user_profile_photo.py => set_photo.py} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename pyrogram/client/methods/users/{set_user_profile_photo.py => set_photo.py} (95%) diff --git a/pyrogram/client/methods/users/set_user_profile_photo.py b/pyrogram/client/methods/users/set_photo.py similarity index 95% rename from pyrogram/client/methods/users/set_user_profile_photo.py rename to pyrogram/client/methods/users/set_photo.py index bc056466..cd7f955d 100644 --- a/pyrogram/client/methods/users/set_user_profile_photo.py +++ b/pyrogram/client/methods/users/set_photo.py @@ -20,8 +20,8 @@ from pyrogram.api import functions from ...ext import BaseClient -class SetUserProfilePhoto(BaseClient): - def set_user_profile_photo( +class SetPhoto(BaseClient): + def set_photo( self, photo: str ) -> bool: From 09d012b696555e9530fd47a2c29e8b5dabe605c4 Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Wed, 29 May 2019 09:43:33 +0200 Subject: [PATCH 10/50] Rename get_user_profile_photos to get_user_photos --- .../{get_user_profile_photos.py => get_user_photos.py} | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) rename pyrogram/client/methods/users/{get_user_profile_photos.py => get_user_photos.py} (88%) diff --git a/pyrogram/client/methods/users/get_user_profile_photos.py b/pyrogram/client/methods/users/get_user_photos.py similarity index 88% rename from pyrogram/client/methods/users/get_user_profile_photos.py rename to pyrogram/client/methods/users/get_user_photos.py index ab58dbec..e134a502 100644 --- a/pyrogram/client/methods/users/get_user_profile_photos.py +++ b/pyrogram/client/methods/users/get_user_photos.py @@ -23,13 +23,13 @@ from pyrogram.api import functions from ...ext import BaseClient -class GetUserProfilePhotos(BaseClient): - def get_user_profile_photos( +class GetUserPhotos(BaseClient): + def get_user_photos( self, user_id: Union[int, str], offset: int = 0, limit: int = 100 - ) -> "pyrogram.UserProfilePhotos": + ) -> "pyrogram.Photos": """Get a list of profile pictures for a user. Parameters: @@ -47,12 +47,12 @@ class GetUserProfilePhotos(BaseClient): Values between 1—100 are accepted. Defaults to 100. Returns: - :obj:`UserProfilePhotos`: On success, an object containing a list of the profile photos is returned. + :obj:`Photos`: On success, an object containing a list of the profile photos is returned. Raises: RPCError: In case of a Telegram RPC error. """ - return pyrogram.UserProfilePhotos._parse( + return pyrogram.Photos._parse( self, self.send( functions.photos.GetUserPhotos( From 38de4299c511046b866abd0b32d2db5c9575a16c Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Wed, 29 May 2019 09:43:48 +0200 Subject: [PATCH 11/50] Add get_user_dc method --- pyrogram/client/methods/users/__init__.py | 16 ++++++++-------- pyrogram/client/methods/users/get_user_dc.py | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/pyrogram/client/methods/users/__init__.py b/pyrogram/client/methods/users/__init__.py index a33a0f0c..bbc2df23 100644 --- a/pyrogram/client/methods/users/__init__.py +++ b/pyrogram/client/methods/users/__init__.py @@ -16,24 +16,24 @@ # You should have received a copy of the GNU Lesser General Public License # along with Pyrogram. If not, see . -from .delete_user_profile_photos import DeleteUserProfilePhotos +from .delete_photos import DeletePhotos from .get_me import GetMe from .get_user_dc import GetUserDC -from .get_user_profile_photos import GetUserProfilePhotos -from .get_user_profile_photos_count import GetUserProfilePhotosCount +from .get_user_photos import GetUserPhotos +from .get_user_photos_count import GetUserPhotosCount from .get_users import GetUsers -from .set_user_profile_photo import SetUserProfilePhoto +from .set_photo import SetPhoto from .update_username import UpdateUsername class Users( - GetUserProfilePhotos, - SetUserProfilePhoto, - DeleteUserProfilePhotos, + GetUserPhotos, + SetPhoto, + DeletePhotos, GetUsers, GetMe, UpdateUsername, - GetUserProfilePhotosCount, + GetUserPhotosCount, GetUserDC ): pass diff --git a/pyrogram/client/methods/users/get_user_dc.py b/pyrogram/client/methods/users/get_user_dc.py index 27631e95..49596c11 100644 --- a/pyrogram/client/methods/users/get_user_dc.py +++ b/pyrogram/client/methods/users/get_user_dc.py @@ -46,7 +46,7 @@ class GetUserDC(BaseClient): r = r[0] if r.photo: - if isinstance(r.photo.photo_small, types.FileLocation): - return r.photo.photo_small.dc_id + if isinstance(r.photo, types.UserProfilePhoto): + return r.photo.dc_id return None From 41d5a13b5f99ea65c5a36959f78bc8cd2c511712 Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Wed, 29 May 2019 09:44:57 +0200 Subject: [PATCH 12/50] Extend Chat and User types with new fields is_verified, is_restricted, is_scam and is_support (user only) --- pyrogram/client/types/user_and_chats/chat.py | 44 ++++++++++++++++---- pyrogram/client/types/user_and_chats/user.py | 33 +++++++++++++-- 2 files changed, 65 insertions(+), 12 deletions(-) diff --git a/pyrogram/client/types/user_and_chats/chat.py b/pyrogram/client/types/user_and_chats/chat.py index e45814ea..10cc10a7 100644 --- a/pyrogram/client/types/user_and_chats/chat.py +++ b/pyrogram/client/types/user_and_chats/chat.py @@ -35,6 +35,16 @@ class Chat(PyrogramType): type (``str``): Type of chat, can be either "private", "bot", "group", "supergroup" or "channel". + is_verified (``bool``, *optional*): + True, if this chat has been verified by Telegram. Supergroups and channels only. + + is_restricted (``bool``, *optional*): + True, if this chat has been restricted. Supergroups and channels only. + See *restriction_reason* for details. + + is_scam (``bool``, *optional*): + True, if this chat has been flagged for scam. Supergroups and channels only. + title (``str``, *optional*): Title, for supergroups, channels and basic group chats. @@ -75,15 +85,16 @@ class Chat(PyrogramType): restriction_reason (``str``, *optional*): The reason why this chat might be unavailable to some users. + This field is available only in case *is_restricted* is True. permissions (:obj:`ChatPermissions ` *optional*): Information about the chat default permissions, for groups and supergroups. """ __slots__ = [ - "id", "type", "title", "username", "first_name", "last_name", "photo", "description", "invite_link", - "pinned_message", "sticker_set_name", "can_set_sticker_set", "members_count", "restriction_reason", - "permissions" + "id", "type", "is_verified", "is_restricted", "is_scam", "title", "username", "first_name", "last_name", + "photo", "description", "invite_link", "pinned_message", "sticker_set_name", "can_set_sticker_set", + "members_count", "restriction_reason", "permissions" ] def __init__( @@ -92,6 +103,9 @@ class Chat(PyrogramType): client: "pyrogram.BaseClient" = None, id: int, type: str, + is_verified: bool = None, + is_restricted: bool = None, + is_scam: bool = None, title: str = None, username: str = None, first_name: str = None, @@ -110,6 +124,9 @@ class Chat(PyrogramType): self.id = id self.type = type + self.is_verified = is_verified + self.is_restricted = is_restricted + self.is_scam = is_scam self.title = title self.username = username self.first_name = first_name @@ -126,36 +143,45 @@ class Chat(PyrogramType): @staticmethod def _parse_user_chat(client, user: types.User) -> "Chat": + peer_id = user.id + return Chat( - id=user.id, + id=peer_id, type="bot" if user.bot else "private", username=user.username, first_name=user.first_name, last_name=user.last_name, - photo=ChatPhoto._parse(client, user.photo), + photo=ChatPhoto._parse(client, user.photo, peer_id), restriction_reason=user.restriction_reason, client=client ) @staticmethod def _parse_chat_chat(client, chat: types.Chat) -> "Chat": + peer_id = -chat.id + return Chat( - id=-chat.id, + id=peer_id, type="group", title=chat.title, - photo=ChatPhoto._parse(client, getattr(chat, "photo", None)), + photo=ChatPhoto._parse(client, getattr(chat, "photo", None), peer_id), permissions=ChatPermissions._parse(getattr(chat, "default_banned_rights", None)), client=client ) @staticmethod def _parse_channel_chat(client, channel: types.Channel) -> "Chat": + peer_id = int("-100" + str(channel.id)) + return Chat( - id=int("-100" + str(channel.id)), + id=peer_id, type="supergroup" if channel.megagroup else "channel", + is_verified=getattr(channel, "verified", None), + is_restricted=getattr(channel, "restricted", None), + is_scam=getattr(channel, "scam", None), title=channel.title, username=getattr(channel, "username", None), - photo=ChatPhoto._parse(client, getattr(channel, "photo", None)), + photo=ChatPhoto._parse(client, getattr(channel, "photo", None), peer_id), restriction_reason=getattr(channel, "restriction_reason", None), permissions=ChatPermissions._parse(getattr(channel, "default_banned_rights", None)), client=client diff --git a/pyrogram/client/types/user_and_chats/user.py b/pyrogram/client/types/user_and_chats/user.py index 455b4a4d..ae631df1 100644 --- a/pyrogram/client/types/user_and_chats/user.py +++ b/pyrogram/client/types/user_and_chats/user.py @@ -45,6 +45,19 @@ class User(PyrogramType): is_bot (``bool``): True, if this user is a bot. + is_verified (``bool``): + True, if this user has been verified by Telegram. + + is_restricted (``bool``): + True, if this user has been restricted. Bots only. + See *restriction_reason* for details. + + is_support (``bool``): + True, if this user is part of the Telegram support team. + + is_scam (``bool``): + True, if this user has been flagged for scam. + first_name (``str``): User's or bot's first name. @@ -68,11 +81,13 @@ class User(PyrogramType): restriction_reason (``str``, *optional*): The reason why this bot might be unavailable to some users. + This field is available only in case *is_restricted* is True. """ __slots__ = [ - "id", "is_self", "is_contact", "is_mutual_contact", "is_deleted", "is_bot", "first_name", "last_name", "status", - "username", "language_code", "phone_number", "photo", "restriction_reason" + "id", "is_self", "is_contact", "is_mutual_contact", "is_deleted", "is_bot", "is_verified", "is_restricted", + "is_support", "is_scam", "first_name", "last_name", "status", "username", "language_code", "phone_number", + "photo", "restriction_reason" ] def __init__( @@ -85,6 +100,10 @@ class User(PyrogramType): is_mutual_contact: bool, is_deleted: bool, is_bot: bool, + is_verified: bool, + is_restricted: bool, + is_support: bool, + is_scam: bool, first_name: str, last_name: str = None, status: UserStatus = None, @@ -102,6 +121,10 @@ class User(PyrogramType): self.is_mutual_contact = is_mutual_contact self.is_deleted = is_deleted self.is_bot = is_bot + self.is_verified = is_verified + self.is_restricted = is_restricted + self.is_support = is_support + self.is_scam = is_scam self.first_name = first_name self.last_name = last_name self.status = status @@ -123,13 +146,17 @@ class User(PyrogramType): is_mutual_contact=user.mutual_contact, is_deleted=user.deleted, is_bot=user.bot, + is_verified=user.verified, + is_restricted=user.restricted, + is_support=user.support, + is_scam=user.scam, first_name=user.first_name, last_name=user.last_name, status=UserStatus._parse(client, user.status, user.id, user.bot), username=user.username, language_code=user.lang_code, phone_number=user.phone, - photo=ChatPhoto._parse(client, user.photo), + photo=ChatPhoto._parse(client, user.photo, user.id), restriction_reason=user.restriction_reason, client=client ) From 807dcb67be8914ca2907dd9e4a382032faf605d9 Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Wed, 29 May 2019 09:46:21 +0200 Subject: [PATCH 13/50] Hide phone numbers and show human-friendly date formats when printing --- pyrogram/client/types/pyrogram_type.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/pyrogram/client/types/pyrogram_type.py b/pyrogram/client/types/pyrogram_type.py index ed50efbc..9a04c636 100644 --- a/pyrogram/client/types/pyrogram_type.py +++ b/pyrogram/client/types/pyrogram_type.py @@ -17,6 +17,7 @@ # along with Pyrogram. If not, see . from collections import OrderedDict +from datetime import datetime from json import dumps import pyrogram @@ -46,9 +47,15 @@ class PyrogramType: try: return OrderedDict( [("_", "pyrogram." + obj.__class__.__name__)] - + [(attr, getattr(obj, attr)) - for attr in obj.__slots__ - if getattr(obj, attr) is not None] + + [ + (attr, "*" * len(getattr(obj, attr))) + if attr == "phone_number" + else (attr, str(datetime.fromtimestamp(getattr(obj, attr)))) + if attr.endswith("date") + else (attr, getattr(obj, attr)) + for attr in obj.__slots__ + if getattr(obj, attr) is not None + ] ) except AttributeError: return repr(obj) From aaa569a08dca9c075779c1230577fc0a69643866 Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Wed, 29 May 2019 09:47:14 +0200 Subject: [PATCH 14/50] Revamp Thumbnail type (ex PhotoSize) --- .../{photo_size.py => thumbnail.py} | 65 ++++++++++++------- 1 file changed, 40 insertions(+), 25 deletions(-) rename pyrogram/client/types/messages_and_media/{photo_size.py => thumbnail.py} (53%) diff --git a/pyrogram/client/types/messages_and_media/photo_size.py b/pyrogram/client/types/messages_and_media/thumbnail.py similarity index 53% rename from pyrogram/client/types/messages_and_media/photo_size.py rename to pyrogram/client/types/messages_and_media/thumbnail.py index 9f64ae6a..0ff15e66 100644 --- a/pyrogram/client/types/messages_and_media/photo_size.py +++ b/pyrogram/client/types/messages_and_media/thumbnail.py @@ -17,15 +17,16 @@ # along with Pyrogram. If not, see . from struct import pack -from typing import List, Union +from typing import Union, List import pyrogram from pyrogram.api import types from pyrogram.client.ext.utils import encode +from .stripped_thumbnail import StrippedThumbnail from ..pyrogram_type import PyrogramType -class PhotoSize(PyrogramType): +class Thumbnail(PyrogramType): """One size of a photo or a file/sticker thumbnail. Parameters: @@ -61,30 +62,44 @@ class PhotoSize(PyrogramType): self.file_size = file_size @staticmethod - def _parse(client, thumbs: List) -> Union["PhotoSize", None]: - if not thumbs: + def _parse( + client, + media: Union[types.Photo, types.Document] + ) -> Union[List[Union[StrippedThumbnail, "Thumbnail"]], None]: + if isinstance(media, types.Photo): + raw_thumbnails = media.sizes[:-1] + media_type = 0 + elif isinstance(media, types.Document): + raw_thumbnails = media.thumbs + media_type = 14 + + if not raw_thumbnails: + return None + else: return None - photo_size = thumbs[-1] + thumbnails = [] - if not isinstance(photo_size, (types.PhotoSize, types.PhotoCachedSize, types.PhotoStrippedSize)): - return None - - loc = photo_size.location - - if not isinstance(loc, types.FileLocation): - return None - - return PhotoSize( - file_id=encode( - pack( - " Date: Wed, 29 May 2019 09:47:43 +0200 Subject: [PATCH 15/50] Add StrippedThumbnail type Still a WIP --- .../messages_and_media/stripped_thumbnail.py | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 pyrogram/client/types/messages_and_media/stripped_thumbnail.py diff --git a/pyrogram/client/types/messages_and_media/stripped_thumbnail.py b/pyrogram/client/types/messages_and_media/stripped_thumbnail.py new file mode 100644 index 00000000..31638fc2 --- /dev/null +++ b/pyrogram/client/types/messages_and_media/stripped_thumbnail.py @@ -0,0 +1,49 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-2019 Dan Tès +# +# This file is part of Pyrogram. +# +# Pyrogram is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pyrogram is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Pyrogram. If not, see . + +import pyrogram +from pyrogram.api import types +from ..pyrogram_type import PyrogramType + + +class StrippedThumbnail(PyrogramType): + """A stripped thumbnail + + Parameters: + data (``bytes``): + Thumbnail data + """ + + __slots__ = ["data"] + + def __init__( + self, + *, + client: "pyrogram.BaseClient" = None, + data: bytes, + ): + super().__init__(client) + + self.data = data + + @staticmethod + def _parse(client, stripped_thumbnail: types.PhotoStrippedSize) -> "StrippedThumbnail": + return StrippedThumbnail( + data=stripped_thumbnail.bytes, + client=client + ) From fda456cd1ee31c84a66e0bfbd06f29809571f75e Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Wed, 29 May 2019 09:49:13 +0200 Subject: [PATCH 16/50] Rename UserProfilePhotos to just Photos for brevity and elegance --- .../{user_profile_photos.py => photos.py} | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) rename pyrogram/client/types/messages_and_media/{user_profile_photos.py => photos.py} (92%) diff --git a/pyrogram/client/types/messages_and_media/user_profile_photos.py b/pyrogram/client/types/messages_and_media/photos.py similarity index 92% rename from pyrogram/client/types/messages_and_media/user_profile_photos.py rename to pyrogram/client/types/messages_and_media/photos.py index 628831d5..1d5b193e 100644 --- a/pyrogram/client/types/messages_and_media/user_profile_photos.py +++ b/pyrogram/client/types/messages_and_media/photos.py @@ -23,7 +23,7 @@ from .photo import Photo from ..pyrogram_type import PyrogramType -class UserProfilePhotos(PyrogramType): +class Photos(PyrogramType): """Contains a user's profile pictures. Parameters: @@ -49,8 +49,8 @@ class UserProfilePhotos(PyrogramType): self.photos = photos @staticmethod - def _parse(client, photos) -> "UserProfilePhotos": - return UserProfilePhotos( + def _parse(client, photos) -> "Photos": + return Photos( total_count=getattr(photos, "count", len(photos.photos)), photos=[Photo._parse(client, photo) for photo in photos.photos], client=client From b217bf37845c5a4b92a2f45613697dd0f5a0ddb3 Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Wed, 29 May 2019 09:49:50 +0200 Subject: [PATCH 17/50] Refactor ChatPhoto to accommodate L100 changes --- .../client/types/user_and_chats/chat_photo.py | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/pyrogram/client/types/user_and_chats/chat_photo.py b/pyrogram/client/types/user_and_chats/chat_photo.py index 08e43138..1885eff2 100644 --- a/pyrogram/client/types/user_and_chats/chat_photo.py +++ b/pyrogram/client/types/user_and_chats/chat_photo.py @@ -50,31 +50,24 @@ class ChatPhoto(PyrogramType): self.big_file_id = big_file_id @staticmethod - def _parse(client, chat_photo: types.UserProfilePhoto or types.ChatPhoto): + def _parse(client, chat_photo: types.UserProfilePhoto or types.ChatPhoto, peer_id: int): if not isinstance(chat_photo, (types.UserProfilePhoto, types.ChatPhoto)): return None - if not isinstance(chat_photo.photo_small, types.FileLocation): - return None - - if not isinstance(chat_photo.photo_big, types.FileLocation): - return None - - photo_id = getattr(chat_photo, "photo_id", 0) loc_small = chat_photo.photo_small loc_big = chat_photo.photo_big return ChatPhoto( small_file_id=encode( pack( - " Date: Wed, 29 May 2019 09:50:41 +0200 Subject: [PATCH 18/50] Update all media types' thumbnails They are now a List of Thumbnail objects --- .../types/messages_and_media/__init__.py | 7 +- .../types/messages_and_media/animation.py | 27 +++--- .../client/types/messages_and_media/audio.py | 29 ++++--- .../types/messages_and_media/document.py | 21 ++--- .../client/types/messages_and_media/photo.py | 82 ++++++++----------- .../types/messages_and_media/sticker.py | 21 ++--- .../client/types/messages_and_media/video.py | 29 ++++--- .../types/messages_and_media/video_note.py | 17 ++-- 8 files changed, 122 insertions(+), 111 deletions(-) diff --git a/pyrogram/client/types/messages_and_media/__init__.py b/pyrogram/client/types/messages_and_media/__init__.py index ae4386d0..d312611b 100644 --- a/pyrogram/client/types/messages_and_media/__init__.py +++ b/pyrogram/client/types/messages_and_media/__init__.py @@ -26,11 +26,12 @@ from .message import Message from .message_entity import MessageEntity from .messages import Messages from .photo import Photo -from .photo_size import PhotoSize from .poll import Poll from .poll_option import PollOption from .sticker import Sticker -from .user_profile_photos import UserProfilePhotos +from .stripped_thumbnail import StrippedThumbnail +from .thumbnail import Thumbnail +from .photos import Photos from .venue import Venue from .video import Video from .video_note import VideoNote @@ -38,5 +39,5 @@ from .voice import Voice __all__ = [ "Animation", "Audio", "Contact", "Document", "Game", "Location", "Message", "MessageEntity", "Messages", "Photo", - "PhotoSize", "Poll", "PollOption", "Sticker", "UserProfilePhotos", "Venue", "Video", "VideoNote", "Voice" + "Thumbnail", "StrippedThumbnail", "Poll", "PollOption", "Sticker", "Photos", "Venue", "Video", "VideoNote", "Voice" ] diff --git a/pyrogram/client/types/messages_and_media/animation.py b/pyrogram/client/types/messages_and_media/animation.py index cd6e03ab..d729c3ac 100644 --- a/pyrogram/client/types/messages_and_media/animation.py +++ b/pyrogram/client/types/messages_and_media/animation.py @@ -17,10 +17,11 @@ # along with Pyrogram. If not, see . from struct import pack +from typing import List import pyrogram from pyrogram.api import types -from .photo_size import PhotoSize +from .thumbnail import Thumbnail from ..pyrogram_type import PyrogramType from ...ext.utils import encode @@ -41,9 +42,6 @@ class Animation(PyrogramType): duration (``int``): Duration of the animation in seconds as defined by sender. - thumb (:obj:`PhotoSize `, *optional*): - Animation thumbnail. - file_name (``str``, *optional*): Animation file name. @@ -55,9 +53,12 @@ class Animation(PyrogramType): date (``int``, *optional*): Date the animation was sent in Unix time. + + thumbnails (List of :obj:`Thumbnail`, *optional*): + Animation thumbnails. """ - __slots__ = ["file_id", "thumb", "file_name", "mime_type", "file_size", "date", "width", "height", "duration"] + __slots__ = ["file_id", "file_name", "mime_type", "file_size", "date", "width", "height", "duration", "thumbnails"] def __init__( self, @@ -67,16 +68,15 @@ class Animation(PyrogramType): width: int, height: int, duration: int, - thumb: PhotoSize = None, file_name: str = None, mime_type: str = None, file_size: int = None, - date: int = None + date: int = None, + thumbnails: List[Thumbnail] = None, ): super().__init__(client) self.file_id = file_id - self.thumb = thumb self.file_name = file_name self.mime_type = mime_type self.file_size = file_size @@ -84,10 +84,15 @@ class Animation(PyrogramType): self.width = width self.height = height self.duration = duration + self.thumbnails = thumbnails @staticmethod - def _parse(client, animation: types.Document, video_attributes: types.DocumentAttributeVideo, - file_name: str) -> "Animation": + def _parse( + client, + animation: types.Document, + video_attributes: types.DocumentAttributeVideo, + file_name: str + ) -> "Animation": return Animation( file_id=encode( pack( @@ -101,10 +106,10 @@ class Animation(PyrogramType): width=getattr(video_attributes, "w", 0), height=getattr(video_attributes, "h", 0), duration=getattr(video_attributes, "duration", 0), - thumb=PhotoSize._parse(client, animation.thumbs), mime_type=animation.mime_type, file_size=animation.size, file_name=file_name, date=animation.date, + thumbnails=Thumbnail._parse(client, animation), client=client ) diff --git a/pyrogram/client/types/messages_and_media/audio.py b/pyrogram/client/types/messages_and_media/audio.py index 76181a22..ccea2f3c 100644 --- a/pyrogram/client/types/messages_and_media/audio.py +++ b/pyrogram/client/types/messages_and_media/audio.py @@ -17,10 +17,11 @@ # along with Pyrogram. If not, see . from struct import pack +from typing import List import pyrogram from pyrogram.api import types -from .photo_size import PhotoSize +from .thumbnail import Thumbnail from ..pyrogram_type import PyrogramType from ...ext.utils import encode @@ -35,9 +36,6 @@ class Audio(PyrogramType): duration (``int``): Duration of the audio in seconds as defined by sender. - thumb (:obj:`PhotoSize`, *optional*): - Thumbnail of the music file album cover. - file_name (``str``, *optional*): Audio file name. @@ -55,9 +53,14 @@ class Audio(PyrogramType): title (``str``, *optional*): Title of the audio as defined by sender or by audio tags. + + thumbnails (List of :obj:`Thumbnail`, *optional*): + Thumbnails of the music file album cover. """ - __slots__ = ["file_id", "thumb", "file_name", "mime_type", "file_size", "date", "duration", "performer", "title"] + __slots__ = [ + "file_id", "file_name", "mime_type", "file_size", "date", "duration", "performer", "title", "thumbnails" + ] def __init__( self, @@ -65,18 +68,17 @@ class Audio(PyrogramType): client: "pyrogram.BaseClient" = None, file_id: str, duration: int, - thumb: PhotoSize = None, file_name: str = None, mime_type: str = None, file_size: int = None, date: int = None, performer: str = None, - title: str = None + title: str = None, + thumbnails: List[Thumbnail] = None, ): super().__init__(client) self.file_id = file_id - self.thumb = thumb self.file_name = file_name self.mime_type = mime_type self.file_size = file_size @@ -84,10 +86,15 @@ class Audio(PyrogramType): self.duration = duration self.performer = performer self.title = title + self.thumbnails = thumbnails @staticmethod - def _parse(client, audio: types.Document, audio_attributes: types.DocumentAttributeAudio, - file_name: str) -> "Audio": + def _parse( + client, + audio: types.Document, + audio_attributes: types.DocumentAttributeAudio, + file_name: str + ) -> "Audio": return Audio( file_id=encode( pack( @@ -103,8 +110,8 @@ class Audio(PyrogramType): title=audio_attributes.title, mime_type=audio.mime_type, file_size=audio.size, - thumb=PhotoSize._parse(client, audio.thumbs), file_name=file_name, date=audio.date, + thumbnails=Thumbnail._parse(client, audio), client=client ) diff --git a/pyrogram/client/types/messages_and_media/document.py b/pyrogram/client/types/messages_and_media/document.py index 394d5e14..654516e8 100644 --- a/pyrogram/client/types/messages_and_media/document.py +++ b/pyrogram/client/types/messages_and_media/document.py @@ -17,10 +17,11 @@ # along with Pyrogram. If not, see . from struct import pack +from typing import List import pyrogram from pyrogram.api import types -from .photo_size import PhotoSize +from .thumbnail import Thumbnail from ..pyrogram_type import PyrogramType from ...ext.utils import encode @@ -32,9 +33,6 @@ class Document(PyrogramType): file_id (``str``): Unique file identifier. - thumb (:obj:`PhotoSize`, *optional*): - Document thumbnail as defined by sender. - file_name (``str``, *optional*): Original filename as defined by sender. @@ -46,29 +44,32 @@ class Document(PyrogramType): date (``int``, *optional*): Date the document was sent in Unix time. + + thumbnails (List of :obj:`Thumbnail`, *optional*): + Document thumbnails as defined by sender. """ - __slots__ = ["file_id", "thumb", "file_name", "mime_type", "file_size", "date"] + __slots__ = ["file_id", "file_name", "mime_type", "file_size", "date", "thumbnails"] def __init__( self, *, client: "pyrogram.BaseClient" = None, file_id: str, - thumb: PhotoSize = None, file_name: str = None, mime_type: str = None, file_size: int = None, - date: int = None + date: int = None, + thumbnails: List[Thumbnail] = None, ): super().__init__(client) self.file_id = file_id - self.thumb = thumb self.file_name = file_name self.mime_type = mime_type self.file_size = file_size - self.date = date + self.date = date, + self.thumbnails = thumbnails @staticmethod def _parse(client, document: types.Document, file_name: str) -> "Document": @@ -82,10 +83,10 @@ class Document(PyrogramType): document.access_hash ) ), - thumb=PhotoSize._parse(client, document.thumbs), file_name=file_name, mime_type=document.mime_type, file_size=document.size, date=document.date, + thumbnails=Thumbnail._parse(client, document), client=client ) diff --git a/pyrogram/client/types/messages_and_media/photo.py b/pyrogram/client/types/messages_and_media/photo.py index 8d60d59a..ca42c3eb 100644 --- a/pyrogram/client/types/messages_and_media/photo.py +++ b/pyrogram/client/types/messages_and_media/photo.py @@ -16,13 +16,12 @@ # You should have received a copy of the GNU Lesser General Public License # along with Pyrogram. If not, see . -from base64 import b64encode from struct import pack from typing import List import pyrogram from pyrogram.api import types -from .photo_size import PhotoSize +from .thumbnail import Thumbnail from ..pyrogram_type import PyrogramType from ...ext.utils import encode @@ -31,74 +30,65 @@ class Photo(PyrogramType): """A Photo. Parameters: - id (``str``): + file_id (``str``): Unique identifier for this photo. + width (``int``): + Photo width. + + height (``int``): + Photo height. + + file_size (``int``): + File size. + date (``int``): Date the photo was sent in Unix time. - sizes (List of :obj:`PhotoSize`): + thumbnails (List of :obj:`Thumbnail`): Available sizes of this photo. """ - __slots__ = ["id", "date", "sizes"] + __slots__ = ["file_id", "width", "height", "file_size", "date", "thumbnails"] def __init__( self, *, client: "pyrogram.BaseClient" = None, - id: str, + file_id: str, + width: int, + height: int, + file_size: int, date: int, - sizes: List[PhotoSize] + thumbnails: List[Thumbnail] ): super().__init__(client) - self.id = id + self.file_id = file_id + self.width = width + self.height = height + self.file_size = file_size self.date = date - self.sizes = sizes + self.thumbnails = thumbnails @staticmethod - def _parse(client, photo: types.Photo): + def _parse(client, photo: types.Photo) -> "Photo": if isinstance(photo, types.Photo): - raw_sizes = photo.sizes - sizes = [] - - for raw_size in raw_sizes: - if isinstance(raw_size, (types.PhotoSize, types.PhotoCachedSize)): - if isinstance(raw_size, types.PhotoSize): - file_size = raw_size.size - elif isinstance(raw_size, types.PhotoCachedSize): - file_size = len(raw_size.bytes) - else: - file_size = 0 - - loc = raw_size.location - - if isinstance(loc, types.FileLocation): - size = PhotoSize( - file_id=encode( - pack( - ". from struct import pack +from typing import List import pyrogram from pyrogram.api import types -from .photo_size import PhotoSize +from .thumbnail import Thumbnail from ..pyrogram_type import PyrogramType from ...ext.utils import encode @@ -41,9 +42,6 @@ class Video(PyrogramType): duration (``int``): Duration of the video in seconds as defined by sender. - thumb (:obj:`PhotoSize`, *optional*): - Video thumbnail. - file_name (``str``, *optional*): Video file name. @@ -58,11 +56,14 @@ class Video(PyrogramType): date (``int``, *optional*): Date the video was sent in Unix time. + + thumbnails (List of :obj:`Thumbnail`, *optional*): + Video thumbnails. """ __slots__ = [ - "file_id", "width", "height", "duration", "thumb", "file_name", "mime_type", "supports_streaming", "file_size", - "date" + "file_id", "width", "height", "duration", "file_name", "mime_type", "supports_streaming", "file_size", "date", + "thumbnails" ] def __init__( @@ -73,12 +74,12 @@ class Video(PyrogramType): width: int, height: int, duration: int, - thumb: PhotoSize = None, file_name: str = None, mime_type: str = None, supports_streaming: bool = None, file_size: int = None, - date: int = None + date: int = None, + thumbnails: List[Thumbnail] = None ): super().__init__(client) @@ -86,16 +87,20 @@ class Video(PyrogramType): self.width = width self.height = height self.duration = duration - self.thumb = thumb self.file_name = file_name self.mime_type = mime_type self.supports_streaming = supports_streaming self.file_size = file_size self.date = date + self.thumbnails = thumbnails @staticmethod - def _parse(client, video: types.Document, video_attributes: types.DocumentAttributeVideo, - file_name: str) -> "Video": + def _parse( + client, + video: types.Document, + video_attributes: types.DocumentAttributeVideo, + file_name: str + ) -> "Video": return Video( file_id=encode( pack( @@ -109,11 +114,11 @@ class Video(PyrogramType): width=video_attributes.w, height=video_attributes.h, duration=video_attributes.duration, - thumb=PhotoSize._parse(client, video.thumbs), file_name=file_name, mime_type=video.mime_type, supports_streaming=video_attributes.supports_streaming, file_size=video.size, date=video.date, + thumbnails=Thumbnail._parse(client, video), client=client ) diff --git a/pyrogram/client/types/messages_and_media/video_note.py b/pyrogram/client/types/messages_and_media/video_note.py index 133ccae0..34f5972f 100644 --- a/pyrogram/client/types/messages_and_media/video_note.py +++ b/pyrogram/client/types/messages_and_media/video_note.py @@ -17,10 +17,11 @@ # along with Pyrogram. If not, see . from struct import pack +from typing import List import pyrogram from pyrogram.api import types -from .photo_size import PhotoSize +from .thumbnail import Thumbnail from ..pyrogram_type import PyrogramType from ...ext.utils import encode @@ -38,9 +39,6 @@ class VideoNote(PyrogramType): duration (``int``): Duration of the video in seconds as defined by sender. - thumb (:obj:`PhotoSize`, *optional*): - Video thumbnail. - mime_type (``str``, *optional*): MIME type of the file as defined by sender. @@ -49,9 +47,12 @@ class VideoNote(PyrogramType): date (``int``, *optional*): Date the video note was sent in Unix time. + + thumbnails (List of :obj:`Thumbnail`, *optional*): + Video thumbnails. """ - __slots__ = ["file_id", "thumb", "mime_type", "file_size", "date", "length", "duration"] + __slots__ = ["file_id", "mime_type", "file_size", "date", "length", "duration", "thumbnails"] def __init__( self, @@ -60,7 +61,7 @@ class VideoNote(PyrogramType): file_id: str, length: int, duration: int, - thumb: PhotoSize = None, + thumbnails: List[Thumbnail] = None, mime_type: str = None, file_size: int = None, date: int = None @@ -68,12 +69,12 @@ class VideoNote(PyrogramType): super().__init__(client) self.file_id = file_id - self.thumb = thumb self.mime_type = mime_type self.file_size = file_size self.date = date self.length = length self.duration = duration + self.thumbnails = thumbnails @staticmethod def _parse(client, video_note: types.Document, video_attributes: types.DocumentAttributeVideo) -> "VideoNote": @@ -89,9 +90,9 @@ class VideoNote(PyrogramType): ), length=video_attributes.w, duration=video_attributes.duration, - thumb=PhotoSize._parse(client, video_note.thumbs), file_size=video_note.size, mime_type=video_note.mime_type, date=video_note.date, + thumbnails=Thumbnail._parse(client, video_note), client=client ) From 55599e33c67d7a67eb1a3a227d05975df25fdb35 Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Wed, 29 May 2019 10:40:37 +0200 Subject: [PATCH 19/50] Rework download_media to accommodate L100 changes --- pyrogram/client/client.py | 152 +++++++++--------- pyrogram/client/ext/base_client.py | 10 +- .../client/methods/messages/download_media.py | 131 +++++++++------ 3 files changed, 166 insertions(+), 127 deletions(-) diff --git a/pyrogram/client/client.py b/pyrogram/client/client.py index 0d1cde19..468413b0 100644 --- a/pyrogram/client/client.py +++ b/pyrogram/client/client.py @@ -17,7 +17,6 @@ # along with Pyrogram. If not, see . import base64 -import binascii import json import logging import math @@ -25,7 +24,6 @@ import mimetypes import os import re import shutil -import struct import tempfile import threading import time @@ -49,7 +47,7 @@ from pyrogram.errors import ( PhoneNumberUnoccupied, PhoneCodeInvalid, PhoneCodeHashEmpty, PhoneCodeExpired, PhoneCodeEmpty, SessionPasswordNeeded, PasswordHashInvalid, FloodWait, PeerIdInvalid, FirstnameInvalid, PhoneNumberBanned, - VolumeLocNotFound, UserMigrate, FileIdInvalid, ChannelPrivate, PhoneNumberOccupied, + VolumeLocNotFound, UserMigrate, ChannelPrivate, PhoneNumberOccupied, PasswordRecoveryNa, PasswordEmpty ) from pyrogram.session import Auth, Session @@ -829,85 +827,59 @@ class Client(Methods, BaseClient): log.debug("{} started".format(name)) while True: - media = self.download_queue.get() + packet = self.download_queue.get() - if media is None: + if packet is None: break temp_file_path = "" final_file_path = "" try: - media, file_name, done, progress, progress_args, path = media - - file_id = media.file_id - size = media.file_size + data, file_name, done, progress, progress_args, path = packet + data = data # type: BaseClient.FileData directory, file_name = os.path.split(file_name) directory = directory or "downloads" - try: - decoded = utils.decode(file_id) - fmt = " 24 else " 24: - volume_id = unpacked[4] - secret = unpacked[5] - local_id = unpacked[6] + if not data.file_name: + guessed_extension = self.guess_extension(data.mime_type) - media_type_str = Client.MEDIA_TYPE_ID.get(media_type, None) - - if media_type_str is None: - raise FileIdInvalid("Unknown media type: {}".format(unpacked[0])) - - file_name = file_name or getattr(media, "file_name", None) - - if not file_name: - guessed_extension = self.guess_extension(media.mime_type) - - if media_type in (0, 1, 2): + if data.media_type in (0, 1, 2, 14): extension = ".jpg" - elif media_type == 3: + elif data.media_type == 3: extension = guessed_extension or ".ogg" - elif media_type in (4, 10, 13): + elif data.media_type in (4, 10, 13): extension = guessed_extension or ".mp4" - elif media_type == 5: + elif data.media_type == 5: extension = guessed_extension or ".zip" - elif media_type == 8: + elif data.media_type == 8: extension = guessed_extension or ".webp" - elif media_type == 9: + elif data.media_type == 9: extension = guessed_extension or ".mp3" else: continue file_name = "{}_{}_{}{}".format( media_type_str, - datetime.fromtimestamp( - getattr(media, "date", None) or time.time() - ).strftime("%Y-%m-%d_%H-%M-%S"), + datetime.fromtimestamp(data.date or time.time()).strftime("%Y-%m-%d_%H-%M-%S"), self.rnd_id(), extension ) temp_file_path = self.get_file( - dc_id=dc_id, - id=id, - access_hash=access_hash, - volume_id=volume_id, - local_id=local_id, - secret=secret, - size=size, + media_type=data.media_type, + dc_id=data.dc_id, + file_id=data.file_id, + access_hash=data.access_hash, + thumb_size=data.thumb_size, + peer_id=data.peer_id, + volume_id=data.volume_id, + local_id=data.local_id, + file_size=data.file_size, + is_big=data.is_big, progress=progress, progress_args=progress_args ) @@ -1549,16 +1521,21 @@ class Client(Methods, BaseClient): finally: session.stop() - def get_file(self, - dc_id: int, - id: int = None, - access_hash: int = None, - volume_id: int = None, - local_id: int = None, - secret: int = None, - size: int = None, - progress: callable = None, - progress_args: tuple = ()) -> str: + def get_file( + self, + media_type: int, + dc_id: int, + file_id: int, + access_hash: int, + thumb_size: str, + peer_id: int, + volume_id: int, + local_id: int, + file_size: int, + is_big: bool, + progress: callable, + progress_args: tuple = () + ) -> str: with self.media_sessions_lock: session = self.media_sessions.get(dc_id, None) @@ -1599,18 +1576,33 @@ class Client(Methods, BaseClient): self.media_sessions[dc_id] = session - if volume_id: # Photos are accessed by volume_id, local_id, secret - location = types.InputFileLocation( + if media_type == 1: + location = types.InputPeerPhotoFileLocation( + peer=self.resolve_peer(peer_id), volume_id=volume_id, local_id=local_id, - secret=secret, - file_reference=b"" + big=is_big or None ) - else: # Any other file can be more easily accessed by id and access_hash - location = types.InputDocumentFileLocation( - id=id, + elif media_type in (0, 2): + location = types.InputPhotoFileLocation( + id=file_id, access_hash=access_hash, - file_reference=b"" + file_reference=b"", + thumb_size=thumb_size + ) + elif media_type == 14: + location = types.InputDocumentFileLocation( + id=file_id, + access_hash=access_hash, + file_reference=b"", + thumb_size=thumb_size + ) + else: + location = types.InputDocumentFileLocation( + id=file_id, + access_hash=access_hash, + file_reference=b"", + thumb_size="" ) limit = 1024 * 1024 @@ -1641,7 +1633,14 @@ class Client(Methods, BaseClient): offset += limit if progress: - progress(self, min(offset, size) if size != 0 else offset, size, *progress_args) + progress( + self, + min(offset, file_size) + if file_size != 0 + else offset, + file_size, + *progress_args + ) r = session.send( functions.upload.GetFile( @@ -1723,7 +1722,14 @@ class Client(Methods, BaseClient): offset += limit if progress: - progress(self, min(offset, size) if size != 0 else offset, size, *progress_args) + progress( + self, + min(offset, file_size) + if file_size != 0 + else offset, + file_size, + *progress_args + ) if len(chunk) < limit: break diff --git a/pyrogram/client/ext/base_client.py b/pyrogram/client/ext/base_client.py index a3816bdf..3397c8d3 100644 --- a/pyrogram/client/ext/base_client.py +++ b/pyrogram/client/ext/base_client.py @@ -19,6 +19,7 @@ import os import platform import re +from collections import namedtuple from queue import Queue from threading import Lock @@ -56,7 +57,7 @@ class BaseClient: CONFIG_FILE = "./config.ini" MEDIA_TYPE_ID = { - 0: "thumbnail", + 0: "photo_thumbnail", 1: "chat_photo", 2: "photo", 3: "voice", @@ -65,7 +66,8 @@ class BaseClient: 8: "sticker", 9: "audio", 10: "animation", - 13: "video_note" + 13: "video_note", + 14: "document_thumbnail" } mime_types_to_extensions = {} @@ -82,6 +84,10 @@ class BaseClient: mime_types_to_extensions[mime_type] = " ".join(extensions) + fields = ("media_type", "dc_id", "file_id", "access_hash", "thumb_size", "peer_id", "volume_id", "local_id", + "is_big", "file_size", "mime_type", "file_name", "date") + FileData = namedtuple("FileData", fields, defaults=(None,) * len(fields)) + def __init__(self): self.is_bot = None self.dc_id = None diff --git a/pyrogram/client/methods/messages/download_media.py b/pyrogram/client/methods/messages/download_media.py index c21a95bf..bba5afd5 100644 --- a/pyrogram/client/methods/messages/download_media.py +++ b/pyrogram/client/methods/messages/download_media.py @@ -16,11 +16,14 @@ # You should have received a copy of the GNU Lesser General Public License # along with Pyrogram. If not, see . +import binascii +import struct from threading import Event from typing import Union import pyrogram -from pyrogram.client.ext import BaseClient +from pyrogram.client.ext import BaseClient, utils +from pyrogram.errors import FileIdInvalid class DownloadMedia(BaseClient): @@ -81,67 +84,91 @@ class DownloadMedia(BaseClient): ``ValueError`` if the message doesn't contain any downloadable media """ error_message = "This message doesn't contain any downloadable media" + available_media = ("audio", "document", "photo", "sticker", "animation", "video", "voice", "video_note") + + file_size = None + mime_type = None + date = None if isinstance(message, pyrogram.Message): - if message.photo: - media = pyrogram.Document( - file_id=message.photo.sizes[-1].file_id, - file_size=message.photo.sizes[-1].file_size, - mime_type="", - date=message.photo.date, - client=self - ) - elif message.audio: - media = message.audio - elif message.document: - media = message.document - elif message.video: - media = message.video - elif message.voice: - media = message.voice - elif message.video_note: - media = message.video_note - elif message.sticker: - media = message.sticker - elif message.animation: - media = message.animation + for kind in available_media: + media = getattr(message, kind, None) + + if media is not None: + break else: raise ValueError(error_message) - elif isinstance(message, ( - pyrogram.Photo, - pyrogram.PhotoSize, - pyrogram.Audio, - pyrogram.Document, - pyrogram.Video, - pyrogram.Voice, - pyrogram.VideoNote, - pyrogram.Sticker, - pyrogram.Animation - )): - if isinstance(message, pyrogram.Photo): - media = pyrogram.Document( - file_id=message.sizes[-1].file_id, - file_size=message.sizes[-1].file_size, - mime_type="", - date=message.date, - client=self + else: + media = message + + if isinstance(media, str): + file_id_str = media + else: + file_id_str = media.file_id + file_name = getattr(media, "file_name", "") + file_size = getattr(media, "file_size", None) + mime_type = getattr(media, "mime_type", None) + date = getattr(media, "date", None) + + data = self.FileData( + file_name=file_name, + file_size=file_size, + mime_type=mime_type, + date=date + ) + + def get_existing_attributes() -> dict: + return dict(filter(lambda x: x[1] is not None, data._asdict().items())) + + try: + decoded = utils.decode(file_id_str) + media_type = decoded[0] + + if media_type == 1: + unpacked = struct.unpack(" Date: Wed, 29 May 2019 10:40:48 +0200 Subject: [PATCH 20/50] Update docs --- docs/source/api/methods.rst | 18 +++++++++--------- docs/source/api/types.rst | 8 ++++---- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/docs/source/api/methods.rst b/docs/source/api/methods.rst index 7614918e..760c332b 100644 --- a/docs/source/api/methods.rst +++ b/docs/source/api/methods.rst @@ -107,14 +107,14 @@ Users ^^^^^ .. hlist:: - :columns: 2 + :columns: 3 - :meth:`~Client.get_me` - :meth:`~Client.get_users` - - :meth:`~Client.get_user_profile_photos` - - :meth:`~Client.get_user_profile_photos_count` - - :meth:`~Client.set_user_profile_photo` - - :meth:`~Client.delete_user_profile_photos` + - :meth:`~Client.get_user_photos` + - :meth:`~Client.get_user_photos_count` + - :meth:`~Client.set_photo` + - :meth:`~Client.delete_photos` - :meth:`~Client.update_username` - :meth:`~Client.get_user_dc` @@ -232,10 +232,10 @@ Details .. Users .. automethod:: Client.get_me() .. automethod:: Client.get_users() -.. automethod:: Client.get_user_profile_photos() -.. automethod:: Client.get_user_profile_photos_count() -.. automethod:: Client.set_user_profile_photo() -.. automethod:: Client.delete_user_profile_photos() +.. automethod:: Client.get_user_photos() +.. automethod:: Client.get_user_photos_count() +.. automethod:: Client.set_photo() +.. automethod:: Client.delete_photos() .. automethod:: Client.update_username() .. automethod:: Client.get_user_dc() diff --git a/docs/source/api/types.rst b/docs/source/api/types.rst index d264eaa2..15f81ae7 100644 --- a/docs/source/api/types.rst +++ b/docs/source/api/types.rst @@ -45,8 +45,8 @@ Messages & Media - :class:`Messages` - :class:`MessageEntity` - :class:`Photo` - - :class:`PhotoSize` - - :class:`UserProfilePhotos` + - :class:`Photos` + - :class:`Thumbnail` - :class:`Audio` - :class:`Document` - :class:`Animation` @@ -133,8 +133,8 @@ Details .. autoclass:: Messages() .. autoclass:: MessageEntity() .. autoclass:: Photo() -.. autoclass:: PhotoSize() -.. autoclass:: UserProfilePhotos() +.. autoclass:: Photos() +.. autoclass:: Thumbnail() .. autoclass:: Audio() .. autoclass:: Document() .. autoclass:: Animation() From 16dbd8d8db248308592b0f940af6b5f2a1e7a18d Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Wed, 29 May 2019 10:41:04 +0200 Subject: [PATCH 21/50] Update development version --- pyrogram/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyrogram/__init__.py b/pyrogram/__init__.py index cbba2fbf..f87b2b0d 100644 --- a/pyrogram/__init__.py +++ b/pyrogram/__init__.py @@ -24,7 +24,7 @@ if sys.version_info[:3] in [(3, 5, 0), (3, 5, 1), (3, 5, 2)]: # Monkey patch the standard "typing" module because Python versions from 3.5.0 to 3.5.2 have a broken one. sys.modules["typing"] = typing -__version__ = "0.13.0" +__version__ = "0.14.0-develop" __license__ = "GNU Lesser General Public License v3 or later (LGPLv3+)" __copyright__ = "Copyright (C) 2017-2019 Dan " From 08d120be7477ba097e64f61e70440f01f9f4e677 Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Wed, 29 May 2019 13:11:48 +0200 Subject: [PATCH 22/50] Add the LAYER attribute to each constructor --- compiler/api/compiler.py | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/api/compiler.py b/compiler/api/compiler.py index 21348336..64e88c9d 100644 --- a/compiler/api/compiler.py +++ b/compiler/api/compiler.py @@ -333,6 +333,7 @@ def start(): docstring_args = "No parameters required." docstring_args = "Attributes:\n ID: ``{}``\n\n ".format(c.id) + docstring_args + docstring_args = "Attributes:\n LAYER: ``{}``\n\n ".format(layer) + docstring_args if c.section == "functions": docstring_args += "\n\n Returns:\n " + get_docstring_arg_type(c.return_type) From 376909f3565cfc3ea2f556873eb38c806747d207 Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Thu, 30 May 2019 14:56:59 +0200 Subject: [PATCH 23/50] Add get_input_media_from_file_id utility method For internal usage --- pyrogram/client/ext/utils.py | 53 ++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/pyrogram/client/ext/utils.py b/pyrogram/client/ext/utils.py index 981752fa..e1959309 100644 --- a/pyrogram/client/ext/utils.py +++ b/pyrogram/client/ext/utils.py @@ -16,8 +16,11 @@ # You should have received a copy of the GNU Lesser General Public License # along with Pyrogram. If not, see . +import struct from base64 import b64decode, b64encode +from typing import Union +from . import BaseClient from ...api import types @@ -82,3 +85,53 @@ def get_offset_date(dialogs): return m.date else: return 0 + + +def get_input_media_from_file_id( + file_id_str: str, + expected_media_type: int = None +) -> Union[types.InputMediaPhoto, types.InputMediaDocument]: + try: + decoded = decode(file_id_str) + except Exception: + raise ValueError("Failed to decode file_id: {}".format(file_id_str)) + else: + media_type = decoded[0] + + if expected_media_type is not None: + if media_type != expected_media_type: + media_type_str = BaseClient.MEDIA_TYPE_ID.get(media_type, None) + expected_media_type_str = BaseClient.MEDIA_TYPE_ID.get(expected_media_type, None) + + raise ValueError( + 'Expected: "{}", got "{}" file_id instead'.format(expected_media_type_str, media_type_str) + ) + + if media_type in (0, 1, 14): + raise ValueError("This file_id can only be used for download: {}".format(file_id_str)) + + if media_type == 2: + unpacked = struct.unpack(" Date: Thu, 30 May 2019 14:57:52 +0200 Subject: [PATCH 24/50] Update send_* methods (for file_ids) --- .../methods/messages/edit_message_media.py | 118 +----------------- .../client/methods/messages/send_animation.py | 27 +--- .../client/methods/messages/send_audio.py | 27 +--- .../methods/messages/send_cached_media.py | 34 +---- .../methods/messages/send_chat_action.py | 2 +- .../client/methods/messages/send_document.py | 27 +--- .../methods/messages/send_media_group.py | 50 +------- .../client/methods/messages/send_photo.py | 28 +---- .../client/methods/messages/send_sticker.py | 27 +--- .../client/methods/messages/send_video.py | 27 +--- .../methods/messages/send_video_note.py | 27 +--- .../client/methods/messages/send_voice.py | 27 +--- 12 files changed, 26 insertions(+), 395 deletions(-) diff --git a/pyrogram/client/methods/messages/edit_message_media.py b/pyrogram/client/methods/messages/edit_message_media.py index b15daa9b..3793c693 100644 --- a/pyrogram/client/methods/messages/edit_message_media.py +++ b/pyrogram/client/methods/messages/edit_message_media.py @@ -16,14 +16,11 @@ # You should have received a copy of the GNU Lesser General Public License # along with Pyrogram. If not, see . -import binascii import os -import struct from typing import Union import pyrogram from pyrogram.api import functions, types -from pyrogram.errors import FileIdInvalid from pyrogram.client.ext import BaseClient, utils from pyrogram.client.types import ( InputMediaPhoto, InputMediaVideo, InputMediaAudio, @@ -94,28 +91,7 @@ class EditMessageMedia(BaseClient): url=media.media ) else: - try: - decoded = utils.decode(media.media) - fmt = " 24 else " 24 else " 24 else " 24 else " 24 else ". -import binascii import os -import struct from typing import Union import pyrogram from pyrogram.api import functions, types -from pyrogram.errors import FileIdInvalid, FilePartMissing from pyrogram.client.ext import BaseClient, utils +from pyrogram.errors import FilePartMissing class SendAnimation(BaseClient): @@ -153,28 +151,7 @@ class SendAnimation(BaseClient): url=animation ) else: - try: - decoded = utils.decode(animation) - fmt = " 24 else ". -import binascii import os -import struct from typing import Union import pyrogram from pyrogram.api import functions, types -from pyrogram.errors import FileIdInvalid, FilePartMissing from pyrogram.client.ext import BaseClient, utils +from pyrogram.errors import FilePartMissing class SendAudio(BaseClient): @@ -153,28 +151,7 @@ class SendAudio(BaseClient): url=audio ) else: - try: - decoded = utils.decode(audio) - fmt = " 24 else ". -import binascii -import struct from typing import Union import pyrogram from pyrogram.api import functions, types -from pyrogram.errors import FileIdInvalid from pyrogram.client.ext import BaseClient, utils @@ -84,39 +81,10 @@ class SendCachedMedia(BaseClient): """ style = self.html if parse_mode.lower() == "html" else self.markdown - try: - decoded = utils.decode(file_id) - fmt = " 24 else ". +import json from typing import Union from pyrogram.api import functions, types from pyrogram.client.ext import BaseClient -import json class ChatAction: diff --git a/pyrogram/client/methods/messages/send_document.py b/pyrogram/client/methods/messages/send_document.py index df202fd7..ff523303 100644 --- a/pyrogram/client/methods/messages/send_document.py +++ b/pyrogram/client/methods/messages/send_document.py @@ -16,15 +16,13 @@ # You should have received a copy of the GNU Lesser General Public License # along with Pyrogram. If not, see . -import binascii import os -import struct from typing import Union import pyrogram from pyrogram.api import functions, types -from pyrogram.errors import FileIdInvalid, FilePartMissing from pyrogram.client.ext import BaseClient, utils +from pyrogram.errors import FilePartMissing class SendDocument(BaseClient): @@ -134,28 +132,7 @@ class SendDocument(BaseClient): url=document ) else: - try: - decoded = utils.decode(document) - fmt = " 24 else ". -import binascii import logging import os -import struct import time from typing import Union, List import pyrogram from pyrogram.api import functions, types -from pyrogram.errors import FileIdInvalid, FloodWait from pyrogram.client.ext import BaseClient, utils +from pyrogram.errors import FloodWait log = logging.getLogger(__name__) @@ -96,28 +94,7 @@ class SendMediaGroup(BaseClient): ) ) else: - try: - decoded = utils.decode(i.media) - fmt = " 24 else " 24 else ". -import binascii import os -import struct from typing import Union import pyrogram from pyrogram.api import functions, types -from pyrogram.errors import FileIdInvalid, FilePartMissing from pyrogram.client.ext import BaseClient, utils +from pyrogram.errors import FilePartMissing class SendPhoto(BaseClient): @@ -129,29 +127,7 @@ class SendPhoto(BaseClient): ttl_seconds=ttl_seconds ) else: - try: - decoded = utils.decode(photo) - fmt = " 24 else ". -import binascii import os -import struct from typing import Union import pyrogram from pyrogram.api import functions, types -from pyrogram.errors import FileIdInvalid, FilePartMissing from pyrogram.client.ext import BaseClient, utils +from pyrogram.errors import FilePartMissing class SendSticker(BaseClient): @@ -114,28 +112,7 @@ class SendSticker(BaseClient): url=sticker ) else: - try: - decoded = utils.decode(sticker) - fmt = " 24 else ". -import binascii import os -import struct from typing import Union import pyrogram from pyrogram.api import functions, types -from pyrogram.errors import FileIdInvalid, FilePartMissing from pyrogram.client.ext import BaseClient, utils +from pyrogram.errors import FilePartMissing class SendVideo(BaseClient): @@ -156,28 +154,7 @@ class SendVideo(BaseClient): url=video ) else: - try: - decoded = utils.decode(video) - fmt = " 24 else ". -import binascii import os -import struct from typing import Union import pyrogram from pyrogram.api import functions, types -from pyrogram.errors import FileIdInvalid, FilePartMissing from pyrogram.client.ext import BaseClient, utils +from pyrogram.errors import FilePartMissing class SendVideoNote(BaseClient): @@ -133,28 +131,7 @@ class SendVideoNote(BaseClient): ] ) else: - try: - decoded = utils.decode(video_note) - fmt = " 24 else ". -import binascii import os -import struct from typing import Union import pyrogram from pyrogram.api import functions, types -from pyrogram.errors import FileIdInvalid, FilePartMissing from pyrogram.client.ext import BaseClient, utils +from pyrogram.errors import FilePartMissing class SendVoice(BaseClient): @@ -132,28 +130,7 @@ class SendVoice(BaseClient): url=voice ) else: - try: - decoded = utils.decode(voice) - fmt = " 24 else " Date: Thu, 30 May 2019 15:23:43 +0200 Subject: [PATCH 25/50] Refactor docstrings --- pyrogram/client/client.py | 8 +++---- pyrogram/client/filters/filters.py | 8 +++---- .../client/handlers/callback_query_handler.py | 4 ++-- .../handlers/deleted_messages_handler.py | 4 ++-- .../client/handlers/disconnect_handler.py | 4 ++-- .../client/handlers/inline_query_handler.py | 4 ++-- pyrogram/client/handlers/message_handler.py | 5 ++--- pyrogram/client/handlers/poll_handler.py | 10 ++++----- .../client/handlers/raw_update_handler.py | 6 +++--- .../client/handlers/user_status_handler.py | 4 ++-- .../methods/chats/export_chat_invite_link.py | 4 ++-- .../client/methods/chats/get_chat_members.py | 2 +- pyrogram/client/methods/chats/get_dialogs.py | 2 +- .../client/methods/chats/iter_chat_members.py | 2 +- pyrogram/client/methods/chats/iter_dialogs.py | 5 +++-- .../client/methods/chats/set_chat_photo.py | 2 +- .../methods/chats/update_chat_username.py | 2 +- .../methods/decorators/on_callback_query.py | 2 +- .../methods/decorators/on_deleted_messages.py | 2 +- .../methods/decorators/on_disconnect.py | 2 +- .../methods/decorators/on_inline_query.py | 2 +- .../client/methods/decorators/on_message.py | 2 +- pyrogram/client/methods/decorators/on_poll.py | 4 ++-- .../methods/decorators/on_raw_update.py | 2 +- .../methods/decorators/on_user_status.py | 2 +- .../client/methods/messages/download_media.py | 2 +- .../client/methods/messages/get_history.py | 2 +- .../client/methods/messages/iter_history.py | 5 +++-- .../client/methods/messages/send_animation.py | 2 +- .../client/methods/messages/send_audio.py | 2 +- .../client/methods/messages/send_document.py | 2 +- .../client/methods/messages/send_photo.py | 2 +- .../client/methods/messages/send_sticker.py | 2 +- .../client/methods/messages/send_video.py | 2 +- .../methods/messages/send_video_note.py | 2 +- .../client/methods/messages/send_voice.py | 2 +- .../client/methods/users/update_username.py | 2 +- .../client/types/inline_mode/inline_query.py | 4 ++-- .../inline_query_result_article.py | 4 ++-- .../todo/inline_query_result_audio.py | 4 ++-- .../inline_query_result_cached_document.py | 4 ++-- .../todo/inline_query_result_cached_gif.py | 4 ++-- .../inline_query_result_cached_sticker.py | 4 ++-- .../todo/inline_query_result_cached_voice.py | 4 ++-- .../todo/inline_query_result_document.py | 4 ++-- .../todo/inline_query_result_game.py | 2 +- .../todo/inline_query_result_photo.py | 4 ++-- .../todo/inline_query_result_venue.py | 4 ++-- .../todo/inline_query_result_video.py | 4 ++-- .../todo/inline_query_result_voice.py | 4 ++-- .../types/input_media/input_phone_contact.py | 2 +- .../types/messages_and_media/message.py | 21 +++++++++---------- .../types/messages_and_media/messages.py | 2 +- pyrogram/client/types/user_and_chats/chat.py | 14 ++++++------- 54 files changed, 105 insertions(+), 105 deletions(-) diff --git a/pyrogram/client/client.py b/pyrogram/client/client.py index 468413b0..e93e3ff8 100644 --- a/pyrogram/client/client.py +++ b/pyrogram/client/client.py @@ -434,9 +434,9 @@ class Client(Methods, BaseClient): def run(self): """Start the Client and automatically idle the main script. - This is a convenience method that literally just calls :meth:`start` and :meth:`idle`. It makes running a client - less verbose, but is not suitable in case you want to run more than one client in a single main script, - since :meth:`idle` will block. + This is a convenience method that literally just calls :meth:`~Client.start` and :meth:`~Client.idle`. It makes + running a client less verbose, but is not suitable in case you want to run more than one client in a single main + script, since :meth:`~Client.idle` will block. Raises: RPCError: In case of a Telegram RPC error. @@ -472,7 +472,7 @@ class Client(Methods, BaseClient): """Remove a previously-registered update handler. Make sure to provide the right group that the handler was added in. You can use - the return value of the :meth:`add_handler` method, a tuple of (handler, group), and + the return value of the :meth:`~Client.add_handler` method, a tuple of (handler, group), and pass it directly. Parameters: diff --git a/pyrogram/client/filters/filters.py b/pyrogram/client/filters/filters.py index 169193a0..9c80d870 100644 --- a/pyrogram/client/filters/filters.py +++ b/pyrogram/client/filters/filters.py @@ -42,7 +42,7 @@ def create(name: str, func: callable, **kwargs) -> type: **kwargs (``any``, *optional*): Any keyword argument you would like to pass. Useful for custom filters that accept parameters (e.g.: - :meth:`Filters.command`, :meth:`Filters.regex`). + :meth:`~Filters.command`, :meth:`~Filters.regex`). """ # TODO: unpack kwargs using **kwargs into the dict itself. For Python 3.5+ only d = {"__call__": func} @@ -56,7 +56,7 @@ class Filters: The Filters listed here are intended to be used with the :obj:`MessageHandler` only. At the moment, if you want to filter updates coming from different `Handlers `_ you have to create - your own filters with :meth:`Filters.create` and use them in the same way. + your own filters with :meth:`~Filters.create` and use them in the same way. """ create = create @@ -219,7 +219,7 @@ class Filters: The command or list of commands as string the filter should look for. Examples: "start", ["start", "help", "settings"]. When a message text containing a command arrives, the command itself and its arguments will be stored in the *command* - field of the :class:`Message`. + field of the :obj:`Message`. prefix (``str`` | ``list``, *optional*): A prefix or a list of prefixes as string the filter should look for. @@ -263,7 +263,7 @@ class Filters: pattern (``str``): The RegEx pattern as string, it will be applied to the text of a message. When a pattern matches, all the `Match Objects `_ - are stored in the *matches* field of the :class:`Message` itself. + are stored in the *matches* field of the :obj:`Message` itself. flags (``int``, *optional*): RegEx flags. diff --git a/pyrogram/client/handlers/callback_query_handler.py b/pyrogram/client/handlers/callback_query_handler.py index feb46cb0..9e17296b 100644 --- a/pyrogram/client/handlers/callback_query_handler.py +++ b/pyrogram/client/handlers/callback_query_handler.py @@ -21,10 +21,10 @@ from .handler import Handler class CallbackQueryHandler(Handler): """The CallbackQuery handler class. Used to handle callback queries coming from inline buttons. - It is intended to be used with :meth:`add_handler() ` + It is intended to be used with :meth:`~Client.add_handler` For a nicer way to register this handler, have a look at the - :meth:`on_callback_query() ` decorator. + :meth:`~Client.on_callback_query` decorator. Parameters: callback (``callable``): diff --git a/pyrogram/client/handlers/deleted_messages_handler.py b/pyrogram/client/handlers/deleted_messages_handler.py index f37caaed..b6651fba 100644 --- a/pyrogram/client/handlers/deleted_messages_handler.py +++ b/pyrogram/client/handlers/deleted_messages_handler.py @@ -22,10 +22,10 @@ from .handler import Handler class DeletedMessagesHandler(Handler): """The deleted Messages handler class. Used to handle deleted messages coming from any chat (private, group, channel). It is intended to be used with - :meth:`add_handler() ` + :meth:`~Client.add_handler` For a nicer way to register this handler, have a look at the - :meth:`on_deleted_messages() ` decorator. + :meth:`~Client.on_deleted_messages` decorator. Parameters: callback (``callable``): diff --git a/pyrogram/client/handlers/disconnect_handler.py b/pyrogram/client/handlers/disconnect_handler.py index b9e6350a..1b4801b2 100644 --- a/pyrogram/client/handlers/disconnect_handler.py +++ b/pyrogram/client/handlers/disconnect_handler.py @@ -21,10 +21,10 @@ from .handler import Handler class DisconnectHandler(Handler): """The Disconnect handler class. Used to handle disconnections. It is intended to be used with - :meth:`add_handler() ` + :meth:~Client.add_handler` For a nicer way to register this handler, have a look at the - :meth:`on_disconnect() ` decorator. + :meth:`~Client.on_disconnect` decorator. Parameters: callback (``callable``): diff --git a/pyrogram/client/handlers/inline_query_handler.py b/pyrogram/client/handlers/inline_query_handler.py index 98a25652..dbd86df7 100644 --- a/pyrogram/client/handlers/inline_query_handler.py +++ b/pyrogram/client/handlers/inline_query_handler.py @@ -21,10 +21,10 @@ from .handler import Handler class InlineQueryHandler(Handler): """The InlineQuery handler class. Used to handle inline queries. - It is intended to be used with :meth:`add_handler() ` + It is intended to be used with :meth:`~Client.add_handler` For a nicer way to register this handler, have a look at the - :meth:`on_inline_query() ` decorator. + :meth:`~Client.on_inline_query` decorator. Parameters: callback (``callable``): diff --git a/pyrogram/client/handlers/message_handler.py b/pyrogram/client/handlers/message_handler.py index 10fff479..ea091ca4 100644 --- a/pyrogram/client/handlers/message_handler.py +++ b/pyrogram/client/handlers/message_handler.py @@ -21,11 +21,10 @@ from .handler import Handler class MessageHandler(Handler): """The Message handler class. Used to handle text, media and service messages coming from - any chat (private, group, channel). It is intended to be used with - :meth:`add_handler() ` + any chat (private, group, channel). It is intended to be used with :meth:`~Client.add_handler` For a nicer way to register this handler, have a look at the - :meth:`on_message() ` decorator. + :meth:`~Client.on_message` decorator. Parameters: callback (``callable``): diff --git a/pyrogram/client/handlers/poll_handler.py b/pyrogram/client/handlers/poll_handler.py index 9e97f2ac..d46fb5be 100644 --- a/pyrogram/client/handlers/poll_handler.py +++ b/pyrogram/client/handlers/poll_handler.py @@ -22,25 +22,25 @@ from .handler import Handler class PollHandler(Handler): """The Poll handler class. Used to handle polls updates. - It is intended to be used with :meth:`add_handler() ` + It is intended to be used with :meth:`~Client.add_handler` For a nicer way to register this handler, have a look at the - :meth:`on_poll() ` decorator. + :meth:`~Client.on_poll` decorator. Parameters: callback (``callable``): Pass a function that will be called when a new poll update arrives. It takes *(client, poll)* as positional arguments (look at the section below for a detailed description). - filters (:obj:`Filters `): + filters (:obj:`Filters`): Pass one or more filters to allow only a subset of polls to be passed in your callback function. Other parameters: - client (:obj:`Client `): + client (:obj:`Client`): The Client itself, useful when you want to call other API methods inside the poll handler. - poll (:obj:`Poll `): + poll (:obj:`Poll`): The received poll. """ diff --git a/pyrogram/client/handlers/raw_update_handler.py b/pyrogram/client/handlers/raw_update_handler.py index f54d59b6..485c6339 100644 --- a/pyrogram/client/handlers/raw_update_handler.py +++ b/pyrogram/client/handlers/raw_update_handler.py @@ -21,10 +21,10 @@ from .handler import Handler class RawUpdateHandler(Handler): """The Raw Update handler class. Used to handle raw updates. It is intended to be used with - :meth:`add_handler() ` + :meth:`~Client.add_handler` For a nicer way to register this handler, have a look at the - :meth:`on_raw_update() ` decorator. + :meth:`~Client.on_raw_update` decorator. Parameters: callback (``callable``): @@ -33,7 +33,7 @@ class RawUpdateHandler(Handler): a detailed description). Other Parameters: - client (:class:`Client`): + client (:obj:`Client`): The Client itself, useful when you want to call other API methods inside the update handler. update (``Update``): diff --git a/pyrogram/client/handlers/user_status_handler.py b/pyrogram/client/handlers/user_status_handler.py index 1250cb19..9b39aab6 100644 --- a/pyrogram/client/handlers/user_status_handler.py +++ b/pyrogram/client/handlers/user_status_handler.py @@ -21,10 +21,10 @@ from .handler import Handler class UserStatusHandler(Handler): """The UserStatus handler class. Used to handle user status updates (user going online or offline). - It is intended to be used with :meth:`add_handler() ` + It is intended to be used with :meth:`~Client.add_handler` For a nicer way to register this handler, have a look at the - :meth:`on_user_status() ` decorator. + :meth:`~Client.on_user_status` decorator. Parameters: callback (``callable``): diff --git a/pyrogram/client/methods/chats/export_chat_invite_link.py b/pyrogram/client/methods/chats/export_chat_invite_link.py index a223a000..26263d53 100644 --- a/pyrogram/client/methods/chats/export_chat_invite_link.py +++ b/pyrogram/client/methods/chats/export_chat_invite_link.py @@ -35,8 +35,8 @@ class ExportChatInviteLink(BaseClient): Each administrator in a chat generates their own invite links. Bots can't use invite links generated by other administrators. If you want your bot to work with invite links, it will need to generate its own link - using this method – after this the link will become available to the bot via the :meth:`get_chat` method. - If your bot needs to generate a new invite link replacing its previous one, use this method again. + using this method – after this the link will become available to the bot via the :meth:`~Client.get_chat` + method. If your bot needs to generate a new invite link replacing its previous one, use this method again. Parameters: chat_id (``int`` | ``str``): diff --git a/pyrogram/client/methods/chats/get_chat_members.py b/pyrogram/client/methods/chats/get_chat_members.py index 10f76dcf..1c966f36 100644 --- a/pyrogram/client/methods/chats/get_chat_members.py +++ b/pyrogram/client/methods/chats/get_chat_members.py @@ -51,7 +51,7 @@ class GetChatMembers(BaseClient): You can get up to 200 chat members at once. A chat can be either a basic group, a supergroup or a channel. You must be admin to retrieve the members list of a channel (also known as "subscribers"). - For a more convenient way of getting chat members see :meth:`iter_chat_members`. + For a more convenient way of getting chat members see :meth:`~Client.iter_chat_members`. Parameters: chat_id (``int`` | ``str``): diff --git a/pyrogram/client/methods/chats/get_dialogs.py b/pyrogram/client/methods/chats/get_dialogs.py index 948a7642..8d5baa15 100644 --- a/pyrogram/client/methods/chats/get_dialogs.py +++ b/pyrogram/client/methods/chats/get_dialogs.py @@ -37,7 +37,7 @@ class GetDialogs(BaseClient): """Get a chunk of the user's dialogs. You can get up to 100 dialogs at once. - For a more convenient way of getting a user's dialogs see :meth:`iter_dialogs`. + For a more convenient way of getting a user's dialogs see :meth:`~Client.iter_dialogs`. Parameters: offset_date (``int``): diff --git a/pyrogram/client/methods/chats/iter_chat_members.py b/pyrogram/client/methods/chats/iter_chat_members.py index 330eed7b..961f6d98 100644 --- a/pyrogram/client/methods/chats/iter_chat_members.py +++ b/pyrogram/client/methods/chats/iter_chat_members.py @@ -47,7 +47,7 @@ class IterChatMembers(BaseClient): ) -> Generator["pyrogram.ChatMember", None, None]: """Iterate through the members of a chat sequentially. - This convenience method does the same as repeatedly calling :meth:`get_chat_members` in a loop, thus saving you + This convenience method does the same as repeatedly calling :meth:`~Client.get_chat_members` in a loop, thus saving you from the hassle of setting up boilerplate code. It is useful for getting the whole members list of a chat with a single call. diff --git a/pyrogram/client/methods/chats/iter_dialogs.py b/pyrogram/client/methods/chats/iter_dialogs.py index 976a49df..e7fb7330 100644 --- a/pyrogram/client/methods/chats/iter_dialogs.py +++ b/pyrogram/client/methods/chats/iter_dialogs.py @@ -30,8 +30,9 @@ class IterDialogs(BaseClient): ) -> Generator["pyrogram.Dialog", None, None]: """Iterate through a user's dialogs sequentially. - This convenience method does the same as repeatedly calling :meth:`get_dialogs` in a loop, thus saving you from - the hassle of setting up boilerplate code. It is useful for getting the whole dialogs list with a single call. + This convenience method does the same as repeatedly calling :meth:`~Client.get_dialogs` in a loop, thus saving + you from the hassle of setting up boilerplate code. It is useful for getting the whole dialogs list with a + single call. Parameters: offset_date (``int``): diff --git a/pyrogram/client/methods/chats/set_chat_photo.py b/pyrogram/client/methods/chats/set_chat_photo.py index 79cceb7e..2baa29fe 100644 --- a/pyrogram/client/methods/chats/set_chat_photo.py +++ b/pyrogram/client/methods/chats/set_chat_photo.py @@ -44,7 +44,7 @@ class SetChatPhoto(BaseClient): Unique identifier (int) or username (str) of the target chat. photo (``str``): - New chat photo. You can pass a :class:`Photo` id or a file path to upload a new photo. + New chat photo. You can pass a :obj:`Photo` id or a file path to upload a new photo. Returns: ``bool``: True on success. diff --git a/pyrogram/client/methods/chats/update_chat_username.py b/pyrogram/client/methods/chats/update_chat_username.py index de5015ea..d06cda61 100644 --- a/pyrogram/client/methods/chats/update_chat_username.py +++ b/pyrogram/client/methods/chats/update_chat_username.py @@ -30,7 +30,7 @@ class UpdateChatUsername(BaseClient): ) -> bool: """Update a channel or a supergroup username. - To update your own username (for users only, not bots) you can use :meth:`update_username`. + To update your own username (for users only, not bots) you can use :meth:`~Client.update_username`. Parameters: chat_id (``int`` | ``str``) diff --git a/pyrogram/client/methods/decorators/on_callback_query.py b/pyrogram/client/methods/decorators/on_callback_query.py index b76655fb..5057f59f 100644 --- a/pyrogram/client/methods/decorators/on_callback_query.py +++ b/pyrogram/client/methods/decorators/on_callback_query.py @@ -32,7 +32,7 @@ class OnCallbackQuery(BaseClient): ) -> callable: """Decorator for handling callback queries. - This does the same thing as :meth:`add_handler` using the :class:`CallbackQueryHandler`. + This does the same thing as :meth:`~Client.add_handler` using the :obj:`CallbackQueryHandler`. Parameters: filters (:obj:`Filters`): diff --git a/pyrogram/client/methods/decorators/on_deleted_messages.py b/pyrogram/client/methods/decorators/on_deleted_messages.py index 7637e6eb..53457b55 100644 --- a/pyrogram/client/methods/decorators/on_deleted_messages.py +++ b/pyrogram/client/methods/decorators/on_deleted_messages.py @@ -32,7 +32,7 @@ class OnDeletedMessages(BaseClient): ) -> callable: """Decorator for handling deleted messages. - This does the same thing as :meth:`add_handler` using the :class:`DeletedMessagesHandler`. + This does the same thing as :meth:`~Client.add_handler` using the :obj:`DeletedMessagesHandler`. Parameters: filters (:obj:`Filters`): diff --git a/pyrogram/client/methods/decorators/on_disconnect.py b/pyrogram/client/methods/decorators/on_disconnect.py index 9305808e..b195ac54 100644 --- a/pyrogram/client/methods/decorators/on_disconnect.py +++ b/pyrogram/client/methods/decorators/on_disconnect.py @@ -25,7 +25,7 @@ class OnDisconnect(BaseClient): def on_disconnect(self=None) -> callable: """Decorator for handling disconnections. - This does the same thing as :meth:`add_handler` using the :class:`DisconnectHandler`. + This does the same thing as :meth:`~Client.add_handler` using the :obj:`DisconnectHandler`. """ def decorator(func: callable) -> Handler: diff --git a/pyrogram/client/methods/decorators/on_inline_query.py b/pyrogram/client/methods/decorators/on_inline_query.py index 58837398..ee7175eb 100644 --- a/pyrogram/client/methods/decorators/on_inline_query.py +++ b/pyrogram/client/methods/decorators/on_inline_query.py @@ -32,7 +32,7 @@ class OnInlineQuery(BaseClient): ) -> callable: """Decorator for handling inline queries. - This does the same thing as :meth:`add_handler` using the :class:`InlineQueryHandler`. + This does the same thing as :meth:`~Client.add_handler` using the :obj:`InlineQueryHandler`. Parameters: filters (:obj:`Filters `): diff --git a/pyrogram/client/methods/decorators/on_message.py b/pyrogram/client/methods/decorators/on_message.py index f590fd12..0f5c836c 100644 --- a/pyrogram/client/methods/decorators/on_message.py +++ b/pyrogram/client/methods/decorators/on_message.py @@ -32,7 +32,7 @@ class OnMessage(BaseClient): ) -> callable: """Decorator for handling messages. - This does the same thing as :meth:`add_handler` using the :class:`MessageHandler`. + This does the same thing as :meth:`~Client.add_handler` using the :obj:`MessageHandler`. Parameters: filters (:obj:`Filters`): diff --git a/pyrogram/client/methods/decorators/on_poll.py b/pyrogram/client/methods/decorators/on_poll.py index de1c1d3d..7442858d 100644 --- a/pyrogram/client/methods/decorators/on_poll.py +++ b/pyrogram/client/methods/decorators/on_poll.py @@ -32,10 +32,10 @@ class OnPoll(BaseClient): ) -> callable: """Decorator for handling poll updates. - This does the same thing as :meth:`add_handler` using the :class:`PollHandler`. + This does the same thing as :meth:`~Client.add_handler` using the :obj:`PollHandler`. Parameters: - filters (:obj:`Filters `): + filters (:obj:`Filters`): Pass one or more filters to allow only a subset of polls to be passed in your function. diff --git a/pyrogram/client/methods/decorators/on_raw_update.py b/pyrogram/client/methods/decorators/on_raw_update.py index 53a0f4cf..e03402ca 100644 --- a/pyrogram/client/methods/decorators/on_raw_update.py +++ b/pyrogram/client/methods/decorators/on_raw_update.py @@ -30,7 +30,7 @@ class OnRawUpdate(BaseClient): ) -> callable: """Decorator for handling raw updates. - This does the same thing as :meth:`add_handler` using the :class:`RawUpdateHandler`. + This does the same thing as :meth:`~Client.add_handler` using the :obj:`RawUpdateHandler`. Parameters: group (``int``, *optional*): diff --git a/pyrogram/client/methods/decorators/on_user_status.py b/pyrogram/client/methods/decorators/on_user_status.py index e7db7b74..bcdcf024 100644 --- a/pyrogram/client/methods/decorators/on_user_status.py +++ b/pyrogram/client/methods/decorators/on_user_status.py @@ -31,7 +31,7 @@ class OnUserStatus(BaseClient): group: int = 0 ) -> callable: """Decorator for handling user status updates. - This does the same thing as :meth:`add_handler` using the :class:`UserStatusHandler`. + This does the same thing as :meth:`~Client.add_handler` using the :obj:`UserStatusHandler`. Parameters: filters (:obj:`Filters`): diff --git a/pyrogram/client/methods/messages/download_media.py b/pyrogram/client/methods/messages/download_media.py index bba5afd5..88c9c2d9 100644 --- a/pyrogram/client/methods/messages/download_media.py +++ b/pyrogram/client/methods/messages/download_media.py @@ -77,7 +77,7 @@ class DownloadMedia(BaseClient): Returns: ``str`` | ``None``: On success, the absolute path of the downloaded file is returned, otherwise, in case - the download failed or was deliberately stopped with :meth:`stop_transmission`, None is returned. + the download failed or was deliberately stopped with :meth:`~Client.stop_transmission`, None is returned. Raises: RPCError: In case of a Telegram RPC error. diff --git a/pyrogram/client/methods/messages/get_history.py b/pyrogram/client/methods/messages/get_history.py index 3933e729..c0810474 100644 --- a/pyrogram/client/methods/messages/get_history.py +++ b/pyrogram/client/methods/messages/get_history.py @@ -41,7 +41,7 @@ class GetHistory(BaseClient): """Retrieve a chunk of the history of a chat. You can get up to 100 messages at once. - For a more convenient way of getting a chat history see :meth:`iter_history`. + For a more convenient way of getting a chat history see :meth:`~Client.iter_history`. Parameters: chat_id (``int`` | ``str``): diff --git a/pyrogram/client/methods/messages/iter_history.py b/pyrogram/client/methods/messages/iter_history.py index 218dd7f5..57da3da5 100644 --- a/pyrogram/client/methods/messages/iter_history.py +++ b/pyrogram/client/methods/messages/iter_history.py @@ -34,8 +34,9 @@ class IterHistory(BaseClient): ) -> Generator["pyrogram.Message", None, None]: """Iterate through a chat history sequentially. - This convenience method does the same as repeatedly calling :meth:`get_history` in a loop, thus saving you from - the hassle of setting up boilerplate code. It is useful for getting the whole chat history with a single call. + This convenience method does the same as repeatedly calling :meth:`~Client.get_history` in a loop, thus saving + you from the hassle of setting up boilerplate code. It is useful for getting the whole chat history with a + single call. Parameters: chat_id (``int`` | ``str``): diff --git a/pyrogram/client/methods/messages/send_animation.py b/pyrogram/client/methods/messages/send_animation.py index 458e3b5f..8a4ec7bd 100644 --- a/pyrogram/client/methods/messages/send_animation.py +++ b/pyrogram/client/methods/messages/send_animation.py @@ -119,7 +119,7 @@ class SendAnimation(BaseClient): Returns: :obj:`Message` | ``None``: On success, the sent animation message is returned, otherwise, in case the upload - is deliberately stopped with :meth:`stop_transmission`, None is returned. + is deliberately stopped with :meth:`~Client.stop_transmission`, None is returned. Raises: RPCError: In case of a Telegram RPC error. diff --git a/pyrogram/client/methods/messages/send_audio.py b/pyrogram/client/methods/messages/send_audio.py index 1c8f7ec5..7b218a66 100644 --- a/pyrogram/client/methods/messages/send_audio.py +++ b/pyrogram/client/methods/messages/send_audio.py @@ -121,7 +121,7 @@ class SendAudio(BaseClient): Returns: :obj:`Message` | ``None``: On success, the sent audio message is returned, otherwise, in case the upload - is deliberately stopped with :meth:`stop_transmission`, None is returned. + is deliberately stopped with :meth:`~Client.stop_transmission`, None is returned. Raises: RPCError: In case of a Telegram RPC error. diff --git a/pyrogram/client/methods/messages/send_document.py b/pyrogram/client/methods/messages/send_document.py index ff523303..da012b2c 100644 --- a/pyrogram/client/methods/messages/send_document.py +++ b/pyrogram/client/methods/messages/send_document.py @@ -107,7 +107,7 @@ class SendDocument(BaseClient): Returns: :obj:`Message` | ``None``: On success, the sent document message is returned, otherwise, in case the upload - is deliberately stopped with :meth:`stop_transmission`, None is returned. + is deliberately stopped with :meth:`~Client.stop_transmission`, None is returned. Raises: RPCError: In case of a Telegram RPC error. diff --git a/pyrogram/client/methods/messages/send_photo.py b/pyrogram/client/methods/messages/send_photo.py index 5e7cb35d..c1fd33d8 100644 --- a/pyrogram/client/methods/messages/send_photo.py +++ b/pyrogram/client/methods/messages/send_photo.py @@ -106,7 +106,7 @@ class SendPhoto(BaseClient): Returns: :obj:`Message` | ``None``: On success, the sent photo message is returned, otherwise, in case the upload - is deliberately stopped with :meth:`stop_transmission`, None is returned. + is deliberately stopped with :meth:`~Client.stop_transmission`, None is returned. Raises: RPCError: In case of a Telegram RPC error. diff --git a/pyrogram/client/methods/messages/send_sticker.py b/pyrogram/client/methods/messages/send_sticker.py index 6a3d2b4b..4f7a99ff 100644 --- a/pyrogram/client/methods/messages/send_sticker.py +++ b/pyrogram/client/methods/messages/send_sticker.py @@ -91,7 +91,7 @@ class SendSticker(BaseClient): Returns: :obj:`Message` | ``None``: On success, the sent sticker message is returned, otherwise, in case the upload - is deliberately stopped with :meth:`stop_transmission`, None is returned. + is deliberately stopped with :meth:`~Client.stop_transmission`, None is returned. Raises: RPCError: In case of a Telegram RPC error. """ diff --git a/pyrogram/client/methods/messages/send_video.py b/pyrogram/client/methods/messages/send_video.py index dc9229e8..4e1201fc 100644 --- a/pyrogram/client/methods/messages/send_video.py +++ b/pyrogram/client/methods/messages/send_video.py @@ -123,7 +123,7 @@ class SendVideo(BaseClient): Returns: :obj:`Message` | ``None``: On success, the sent video message is returned, otherwise, in case the upload - is deliberately stopped with :meth:`stop_transmission`, None is returned. + is deliberately stopped with :meth:`~Client.stop_transmission`, None is returned. Raises: RPCError: In case of a Telegram RPC error. diff --git a/pyrogram/client/methods/messages/send_video_note.py b/pyrogram/client/methods/messages/send_video_note.py index 9372dd9a..7bb8803b 100644 --- a/pyrogram/client/methods/messages/send_video_note.py +++ b/pyrogram/client/methods/messages/send_video_note.py @@ -106,7 +106,7 @@ class SendVideoNote(BaseClient): Returns: :obj:`Message` | ``None``: On success, the sent video note message is returned, otherwise, in case the - pload is deliberately stopped with :meth:`stop_transmission`, None is returned. + pload is deliberately stopped with :meth:`~Client.stop_transmission`, None is returned. Raises: RPCError: In case of a Telegram RPC error. diff --git a/pyrogram/client/methods/messages/send_voice.py b/pyrogram/client/methods/messages/send_voice.py index 759a5421..9dace1e0 100644 --- a/pyrogram/client/methods/messages/send_voice.py +++ b/pyrogram/client/methods/messages/send_voice.py @@ -104,7 +104,7 @@ class SendVoice(BaseClient): Returns: :obj:`Message` | ``None``: On success, the sent voice message is returned, otherwise, in case the upload - is deliberately stopped with :meth:`stop_transmission`, None is returned. + is deliberately stopped with :meth:`~Client.stop_transmission`, None is returned. Raises: RPCError: In case of a Telegram RPC error. diff --git a/pyrogram/client/methods/users/update_username.py b/pyrogram/client/methods/users/update_username.py index 65b86174..002dbf75 100644 --- a/pyrogram/client/methods/users/update_username.py +++ b/pyrogram/client/methods/users/update_username.py @@ -31,7 +31,7 @@ class UpdateUsername(BaseClient): This method only works for users, not bots. Bot usernames must be changed via Bot Support or by recreating them from scratch using BotFather. To update a channel or supergroup username you can use - :meth:`update_chat_username`. + :meth:`~Client.update_chat_username`. Parameters: username (``str`` | ``None``): diff --git a/pyrogram/client/types/inline_mode/inline_query.py b/pyrogram/client/types/inline_mode/inline_query.py index 4d1c9a16..1985a0c0 100644 --- a/pyrogram/client/types/inline_mode/inline_query.py +++ b/pyrogram/client/types/inline_mode/inline_query.py @@ -92,7 +92,7 @@ class InlineQuery(PyrogramType, Update): switch_pm_text: str = "", switch_pm_parameter: str = "" ): - """Bound method *answer* of :obj:`InlineQuery `. + """Bound method *answer* of :obj:`InlineQuery`. Use this method as a shortcut for: @@ -109,7 +109,7 @@ class InlineQuery(PyrogramType, Update): inline_query.answer([...]) Parameters: - results (List of :obj:`InlineQueryResult `): + results (List of :obj:`InlineQueryResult`): A list of results for the inline query. cache_time (``int``, *optional*): diff --git a/pyrogram/client/types/inline_mode/inline_query_result_article.py b/pyrogram/client/types/inline_mode/inline_query_result_article.py index 8543eb4c..ad0be9e4 100644 --- a/pyrogram/client/types/inline_mode/inline_query_result_article.py +++ b/pyrogram/client/types/inline_mode/inline_query_result_article.py @@ -34,10 +34,10 @@ class InlineQueryResultArticle(InlineQueryResult): title (``str``): Title for the result. - input_message_content (:obj:`InputMessageContent `): + input_message_content (:obj:`InputMessageContent`): Content of the message to be sent. - reply_markup (:obj:`InlineKeyboardMarkup `, *optional*): + reply_markup (:obj:`InlineKeyboardMarkup`, *optional*): Inline keyboard attached to the message. url (``str``, *optional*): diff --git a/pyrogram/client/types/inline_mode/todo/inline_query_result_audio.py b/pyrogram/client/types/inline_mode/todo/inline_query_result_audio.py index 0ef30b20..6ca0478a 100644 --- a/pyrogram/client/types/inline_mode/todo/inline_query_result_audio.py +++ b/pyrogram/client/types/inline_mode/todo/inline_query_result_audio.py @@ -50,10 +50,10 @@ class InlineQueryResultAudio(PyrogramType): audio_duration (``int`` ``32-bit``, optional): Audio duration in seconds. - reply_markup (:obj:`InlineKeyboardMarkup `, optional): + reply_markup (:obj:`InlineKeyboardMarkup`, optional): Inline keyboard attached to the message. - input_message_content (:obj:`InputMessageContent `, optional): + input_message_content (:obj:`InputMessageContent`, optional): Content of the message to be sent instead of the audio. """ diff --git a/pyrogram/client/types/inline_mode/todo/inline_query_result_cached_document.py b/pyrogram/client/types/inline_mode/todo/inline_query_result_cached_document.py index e2873638..ad6cb9af 100644 --- a/pyrogram/client/types/inline_mode/todo/inline_query_result_cached_document.py +++ b/pyrogram/client/types/inline_mode/todo/inline_query_result_cached_document.py @@ -47,10 +47,10 @@ class InlineQueryResultCachedDocument(PyrogramType): parse_mode (``str``, optional): Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or inline URLs in the media caption. - reply_markup (:obj:`InlineKeyboardMarkup `, optional): + reply_markup (:obj:`InlineKeyboardMarkup`, optional): Inline keyboard attached to the message. - input_message_content (:obj:`InputMessageContent `, optional): + input_message_content (:obj:`InputMessageContent`, optional): Content of the message to be sent instead of the file. """ diff --git a/pyrogram/client/types/inline_mode/todo/inline_query_result_cached_gif.py b/pyrogram/client/types/inline_mode/todo/inline_query_result_cached_gif.py index 8b523dbd..1c836f20 100644 --- a/pyrogram/client/types/inline_mode/todo/inline_query_result_cached_gif.py +++ b/pyrogram/client/types/inline_mode/todo/inline_query_result_cached_gif.py @@ -44,10 +44,10 @@ class InlineQueryResultCachedGif(PyrogramType): parse_mode (``str``, optional): Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or inline URLs in the media caption. - reply_markup (:obj:`InlineKeyboardMarkup `, optional): + reply_markup (:obj:`InlineKeyboardMarkup`, optional): Inline keyboard attached to the message. - input_message_content (:obj:`InputMessageContent `, optional): + input_message_content (:obj:`InputMessageContent`, optional): Content of the message to be sent instead of the GIF animation. """ diff --git a/pyrogram/client/types/inline_mode/todo/inline_query_result_cached_sticker.py b/pyrogram/client/types/inline_mode/todo/inline_query_result_cached_sticker.py index 06944deb..4711cd72 100644 --- a/pyrogram/client/types/inline_mode/todo/inline_query_result_cached_sticker.py +++ b/pyrogram/client/types/inline_mode/todo/inline_query_result_cached_sticker.py @@ -35,10 +35,10 @@ class InlineQueryResultCachedSticker(PyrogramType): sticker_file_id (``str``): A valid file identifier of the sticker. - reply_markup (:obj:`InlineKeyboardMarkup `, optional): + reply_markup (:obj:`InlineKeyboardMarkup`, optional): Inline keyboard attached to the message. - input_message_content (:obj:`InputMessageContent `, optional): + input_message_content (:obj:`InputMessageContent`, optional): Content of the message to be sent instead of the sticker. """ diff --git a/pyrogram/client/types/inline_mode/todo/inline_query_result_cached_voice.py b/pyrogram/client/types/inline_mode/todo/inline_query_result_cached_voice.py index 3f8bb6a3..3091cf65 100644 --- a/pyrogram/client/types/inline_mode/todo/inline_query_result_cached_voice.py +++ b/pyrogram/client/types/inline_mode/todo/inline_query_result_cached_voice.py @@ -44,10 +44,10 @@ class InlineQueryResultCachedVoice(PyrogramType): parse_mode (``str``, optional): Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or inline URLs in the media caption. - reply_markup (:obj:`InlineKeyboardMarkup `, optional): + reply_markup (:obj:`InlineKeyboardMarkup`, optional): Inline keyboard attached to the message. - input_message_content (:obj:`InputMessageContent `, optional): + input_message_content (:obj:`InputMessageContent`, optional): Content of the message to be sent instead of the voice message. """ diff --git a/pyrogram/client/types/inline_mode/todo/inline_query_result_document.py b/pyrogram/client/types/inline_mode/todo/inline_query_result_document.py index 148ec01d..a95dd2e9 100644 --- a/pyrogram/client/types/inline_mode/todo/inline_query_result_document.py +++ b/pyrogram/client/types/inline_mode/todo/inline_query_result_document.py @@ -50,10 +50,10 @@ class InlineQueryResultDocument(PyrogramType): description (``str``, optional): Short description of the result. - reply_markup (:obj:`InlineKeyboardMarkup `, optional): + reply_markup (:obj:`InlineKeyboardMarkup`, optional): Inline keyboard attached to the message. - input_message_content (:obj:`InputMessageContent `, optional): + input_message_content (:obj:`InputMessageContent`, optional): Content of the message to be sent instead of the file. thumb_url (``str``, optional): diff --git a/pyrogram/client/types/inline_mode/todo/inline_query_result_game.py b/pyrogram/client/types/inline_mode/todo/inline_query_result_game.py index faebacea..98654463 100644 --- a/pyrogram/client/types/inline_mode/todo/inline_query_result_game.py +++ b/pyrogram/client/types/inline_mode/todo/inline_query_result_game.py @@ -35,7 +35,7 @@ class InlineQueryResultGame(PyrogramType): game_short_name (``str``): Short name of the game. - reply_markup (:obj:`InlineKeyboardMarkup `, optional): + reply_markup (:obj:`InlineKeyboardMarkup`, optional): Inline keyboard attached to the message. """ diff --git a/pyrogram/client/types/inline_mode/todo/inline_query_result_photo.py b/pyrogram/client/types/inline_mode/todo/inline_query_result_photo.py index 3412b3f4..db6b9090 100644 --- a/pyrogram/client/types/inline_mode/todo/inline_query_result_photo.py +++ b/pyrogram/client/types/inline_mode/todo/inline_query_result_photo.py @@ -54,10 +54,10 @@ class InlineQueryResultPhoto(PyrogramType): Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or inline URLs in the media caption. - reply_markup (:obj:`InlineKeyboardMarkup `, *optional*): + reply_markup (:obj:`InlineKeyboardMarkup`, *optional*): Inline keyboard attached to the message. - input_message_content (:obj:`InputMessageContent `, *optional*): + input_message_content (:obj:`InputMessageContent`, *optional*): Content of the message to be sent instead of the photo. """ diff --git a/pyrogram/client/types/inline_mode/todo/inline_query_result_venue.py b/pyrogram/client/types/inline_mode/todo/inline_query_result_venue.py index 1dee9509..51ee8ae7 100644 --- a/pyrogram/client/types/inline_mode/todo/inline_query_result_venue.py +++ b/pyrogram/client/types/inline_mode/todo/inline_query_result_venue.py @@ -50,10 +50,10 @@ class InlineQueryResultVenue(PyrogramType): foursquare_type (``str``, optional): Foursquare type of the venue, if known. (For example, "arts_entertainment/default", "arts_entertainment/aquarium" or "food/icecream".). - reply_markup (:obj:`InlineKeyboardMarkup `, optional): + reply_markup (:obj:`InlineKeyboardMarkup`, optional): Inline keyboard attached to the message. - input_message_content (:obj:`InputMessageContent `, optional): + input_message_content (:obj:`InputMessageContent`, optional): Content of the message to be sent instead of the venue. thumb_url (``str``, optional): diff --git a/pyrogram/client/types/inline_mode/todo/inline_query_result_video.py b/pyrogram/client/types/inline_mode/todo/inline_query_result_video.py index 22d810e1..c8e27f79 100644 --- a/pyrogram/client/types/inline_mode/todo/inline_query_result_video.py +++ b/pyrogram/client/types/inline_mode/todo/inline_query_result_video.py @@ -62,10 +62,10 @@ class InlineQueryResultVideo(PyrogramType): description (``str``, optional): Short description of the result. - reply_markup (:obj:`InlineKeyboardMarkup `, optional): + reply_markup (:obj:`InlineKeyboardMarkup`, optional): Inline keyboard attached to the message. - input_message_content (:obj:`InputMessageContent `, optional): + input_message_content (:obj:`InputMessageContent`, optional): Content of the message to be sent instead of the video. This field is required if InlineQueryResultVideo is used to send an HTML-page as a result (e.g., a YouTube video). """ diff --git a/pyrogram/client/types/inline_mode/todo/inline_query_result_voice.py b/pyrogram/client/types/inline_mode/todo/inline_query_result_voice.py index 73d7fb1d..23cc741f 100644 --- a/pyrogram/client/types/inline_mode/todo/inline_query_result_voice.py +++ b/pyrogram/client/types/inline_mode/todo/inline_query_result_voice.py @@ -47,10 +47,10 @@ class InlineQueryResultVoice(PyrogramType): voice_duration (``int`` ``32-bit``, optional): Recording duration in seconds. - reply_markup (:obj:`InlineKeyboardMarkup `, optional): + reply_markup (:obj:`InlineKeyboardMarkup`, optional): Inline keyboard attached to the message. - input_message_content (:obj:`InputMessageContent `, optional): + input_message_content (:obj:`InputMessageContent`, optional): Content of the message to be sent instead of the voice recording. """ diff --git a/pyrogram/client/types/input_media/input_phone_contact.py b/pyrogram/client/types/input_media/input_phone_contact.py index 0b6353b7..c1627516 100644 --- a/pyrogram/client/types/input_media/input_phone_contact.py +++ b/pyrogram/client/types/input_media/input_phone_contact.py @@ -23,7 +23,7 @@ from ..pyrogram_type import PyrogramType class InputPhoneContact(PyrogramType): """A Phone Contact to be added in your Telegram address book. - It is intended to be used with :meth:`add_contacts() ` + It is intended to be used with :meth:`~Client.add_contacts() ` Parameters: phone (``str``): diff --git a/pyrogram/client/types/messages_and_media/message.py b/pyrogram/client/types/messages_and_media/message.py index f8d161c2..c3a12f3e 100644 --- a/pyrogram/client/types/messages_and_media/message.py +++ b/pyrogram/client/types/messages_and_media/message.py @@ -834,7 +834,7 @@ class Message(PyrogramType, Update): Returns: On success, the sent :obj:`Message` is returned. - In case the upload is deliberately stopped with :meth:`stop_transmission`, None is returned instead. + In case the upload is deliberately stopped with :meth:`~Client.stop_transmission`, None is returned instead. Raises: RPCError: In case of a Telegram RPC error. @@ -968,7 +968,7 @@ class Message(PyrogramType, Update): Returns: On success, the sent :obj:`Message` is returned. - In case the upload is deliberately stopped with :meth:`stop_transmission`, None is returned instead. + In case the upload is deliberately stopped with :meth:`~Client.stop_transmission`, None is returned instead. Raises: RPCError: In case of a Telegram RPC error. @@ -1294,7 +1294,7 @@ class Message(PyrogramType, Update): Returns: On success, the sent :obj:`Message` is returned. - In case the upload is deliberately stopped with :meth:`stop_transmission`, None is returned instead. + In case the upload is deliberately stopped with :meth:`~Client.stop_transmission`, None is returned instead. Raises: RPCError: In case of a Telegram RPC error. @@ -1686,7 +1686,7 @@ class Message(PyrogramType, Update): Returns: On success, the sent :obj:`Message` is returned. - In case the upload is deliberately stopped with :meth:`stop_transmission`, None is returned instead. + In case the upload is deliberately stopped with :meth:`~Client.stop_transmission`, None is returned instead. Raises: RPCError: In case of a Telegram RPC error. @@ -1864,7 +1864,7 @@ class Message(PyrogramType, Update): Returns: On success, the sent :obj:`Message` is returned. - In case the upload is deliberately stopped with :meth:`stop_transmission`, None is returned instead. + In case the upload is deliberately stopped with :meth:`~Client.stop_transmission`, None is returned instead. Raises: RPCError: In case of a Telegram RPC error. @@ -2094,7 +2094,7 @@ class Message(PyrogramType, Update): Returns: On success, the sent :obj:`Message` is returned. - In case the upload is deliberately stopped with :meth:`stop_transmission`, None is returned instead. + In case the upload is deliberately stopped with :meth:`~Client.stop_transmission`, None is returned instead. Raises: RPCError: In case of a Telegram RPC error. @@ -2216,7 +2216,7 @@ class Message(PyrogramType, Update): Returns: On success, the sent :obj:`Message` is returned. - In case the upload is deliberately stopped with :meth:`stop_transmission`, None is returned instead. + In case the upload is deliberately stopped with :meth:`~Client.stop_transmission`, None is returned instead. Raises: RPCError: In case of a Telegram RPC error. @@ -2332,7 +2332,7 @@ class Message(PyrogramType, Update): Returns: On success, the sent :obj:`Message` is returned. - In case the upload is deliberately stopped with :meth:`stop_transmission`, None is returned instead. + In case the upload is deliberately stopped with :meth:`~Client.stop_transmission`, None is returned instead. Raises: RPCError: In case of a Telegram RPC error. @@ -2778,9 +2778,8 @@ class Message(PyrogramType, Update): Timeout in seconds. Returns: - - The result of :meth:`request_callback_answer() ` in case of - inline callback button clicks. - - The result of :meth:`reply() ` in case of normal button clicks. + - The result of :meth:`~Client.request_callback_answer` in case of inline callback button clicks. + - The result of :meth:`~Message.reply()` in case of normal button clicks. - A string in case the inline button is a URL, a *switch_inline_query* or a *switch_inline_query_current_chat* button. diff --git a/pyrogram/client/types/messages_and_media/messages.py b/pyrogram/client/types/messages_and_media/messages.py index 379830be..f94f1951 100644 --- a/pyrogram/client/types/messages_and_media/messages.py +++ b/pyrogram/client/types/messages_and_media/messages.py @@ -146,7 +146,7 @@ class Messages(PyrogramType, Update): Defaults to False. Returns: - On success, a :class:`Messages` containing forwarded messages is returned. + On success, a :obj:`Messages` containing forwarded messages is returned. Raises: RPCError: In case of a Telegram RPC error. diff --git a/pyrogram/client/types/user_and_chats/chat.py b/pyrogram/client/types/user_and_chats/chat.py index 10cc10a7..e260d8cd 100644 --- a/pyrogram/client/types/user_and_chats/chat.py +++ b/pyrogram/client/types/user_and_chats/chat.py @@ -57,28 +57,28 @@ class Chat(PyrogramType): last_name (``str``, *optional*): Last name of the other party in a private chat, for private chats. - photo (:obj:`ChatPhoto `, *optional*): + photo (:obj:`ChatPhoto`, *optional*): Chat photo. Suitable for downloads only. description (``str``, *optional*): Bio, for private chats and bots or description for groups, supergroups and channels. - Returned only in :meth:`get_chat() `. + Returned only in :meth:`~Client.get_chat`. invite_link (``str``, *optional*): Chat invite link, for groups, supergroups and channels. - Returned only in :meth:`get_chat() `. + Returned only in :meth:`~Client.get_chat`. pinned_message (:obj:`Message`, *optional*): Pinned message, for groups, supergroups channels and own chat. - Returned only in :meth:`get_chat() `. + Returned only in :meth:`~Client.get_chat`. sticker_set_name (``str``, *optional*): For supergroups, name of group sticker set. - Returned only in :meth:`get_chat() `. + Returned only in :meth:`~Client.get_chat`. can_set_sticker_set (``bool``, *optional*): True, if the group sticker set can be changed by you. - Returned only in :meth:`get_chat() `. + Returned only in :meth:`~Client.get_chat`. members_count (``int``, *optional*): Chat members count, for groups, supergroups and channels only. @@ -87,7 +87,7 @@ class Chat(PyrogramType): The reason why this chat might be unavailable to some users. This field is available only in case *is_restricted* is True. - permissions (:obj:`ChatPermissions ` *optional*): + permissions (:obj:`ChatPermissions` *optional*): Information about the chat default permissions, for groups and supergroups. """ From 4ca87682af04206b53a6067ee152821234e85148 Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Fri, 31 May 2019 00:16:31 +0200 Subject: [PATCH 26/50] Fix Document.date attribute being a tuple Thanks Python... --- pyrogram/client/types/messages_and_media/document.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyrogram/client/types/messages_and_media/document.py b/pyrogram/client/types/messages_and_media/document.py index 654516e8..a8838531 100644 --- a/pyrogram/client/types/messages_and_media/document.py +++ b/pyrogram/client/types/messages_and_media/document.py @@ -68,7 +68,7 @@ class Document(PyrogramType): self.file_name = file_name self.mime_type = mime_type self.file_size = file_size - self.date = date, + self.date = date self.thumbnails = thumbnails @staticmethod From cb3addab1e60256fa6fa49093e5c9e78f9da629a Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Fri, 31 May 2019 00:18:43 +0200 Subject: [PATCH 27/50] Add iter_profile_photos method --- .../methods/users/iter_profile_photos.py | 79 +++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 pyrogram/client/methods/users/iter_profile_photos.py diff --git a/pyrogram/client/methods/users/iter_profile_photos.py b/pyrogram/client/methods/users/iter_profile_photos.py new file mode 100644 index 00000000..1773634e --- /dev/null +++ b/pyrogram/client/methods/users/iter_profile_photos.py @@ -0,0 +1,79 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-2019 Dan Tès +# +# This file is part of Pyrogram. +# +# Pyrogram is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pyrogram is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Pyrogram. If not, see . + +from typing import Union, Generator + +import pyrogram +from ...ext import BaseClient + + +class IterProfilePhotos(BaseClient): + def iter_profile_photos( + self, + chat_id: Union[int, str], + offset: int = 0, + limit: int = 0, + ) -> Generator["pyrogram.Photo", None, None]: + """Iterate through a chat or a user profile photos sequentially. + + This convenience method does the same as repeatedly calling :meth:`~Client.get_profile_photos` in a loop, thus + saving you from the hassle of setting up boilerplate code. It is useful for getting all the profile photos with + a single call. + + Parameters: + chat_id (``int`` | ``str``): + Unique identifier (int) or username (str) of the target chat. + For your personal cloud (Saved Messages) you can simply use "me" or "self". + For a contact that exists in your Telegram address book you can use his phone number (str). + + limit (``int``, *optional*): + Limits the number of profile photos to be retrieved. + By default, no limit is applied and all profile photos are returned. + + offset (``int``, *optional*): + Sequential number of the first profile photo to be returned. + + Returns: + ``Generator``: A generator yielding :obj:`Photo` objects. + + Raises: + RPCError: In case of a Telegram RPC error. + """ + current = 0 + total = limit or (1 << 31) + limit = min(100, total) + + while True: + photos = self.get_profile_photos( + chat_id=chat_id, + offset=offset, + limit=limit + ).photos + + if not photos: + return + + offset += len(photos) + + for photo in photos: + yield photo + + current += 1 + + if current >= total: + return From 06ad65e3a035f9bb0a721cc79086bdedd380cc90 Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Fri, 31 May 2019 00:19:18 +0200 Subject: [PATCH 28/50] Improve codegen scripts --- compiler/api/compiler.py | 4 ++-- compiler/docs/compiler.py | 20 ++++++++++++++------ 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/compiler/api/compiler.py b/compiler/api/compiler.py index 64e88c9d..6566bc8e 100644 --- a/compiler/api/compiler.py +++ b/compiler/api/compiler.py @@ -67,7 +67,7 @@ def get_docstring_arg_type(t: str, is_list: bool = False, is_pyrogram_type: bool n = len(t) - 1 t = (("e" if is_list else "E") + "ither " if n else "") + ", ".join( - ":obj:`{1} <{0}.{1}>`".format( + ":obj:`~{}.{}`".format( "pyrogram.types" if is_pyrogram_type else "pyrogram.api.types", i.replace("pyrogram.", "") ) @@ -88,7 +88,7 @@ def get_references(t: str): n = len(t) - 1 t = ", ".join( - ":obj:`{0} `".format(i) + ":obj:`~pyrogram.api.functions.{}`".format(i) for i in t ) diff --git a/compiler/docs/compiler.py b/compiler/docs/compiler.py index 2c67e66c..b167fa57 100644 --- a/compiler/docs/compiler.py +++ b/compiler/docs/compiler.py @@ -18,6 +18,7 @@ import ast import os +import re import shutil HOME = "compiler/docs" @@ -29,8 +30,10 @@ TYPES_PATH = "pyrogram/api/types" FUNCTIONS_BASE = "functions" TYPES_BASE = "types" -shutil.rmtree(TYPES_BASE, ignore_errors=True) -shutil.rmtree(FUNCTIONS_BASE, ignore_errors=True) + +def snek(s: str): + s = re.sub(r"(.)([A-Z][a-z]+)", r"\1_\2", s) + return re.sub(r"([a-z0-9])([A-Z])", r"\1_\2", s).lower() def generate(source_path, base): @@ -50,9 +53,11 @@ def generate(source_path, base): for node in ast.walk(p): if isinstance(node, ast.ClassDef): name = node.name + break + else: + continue - # name = "".join([str(j.title()) for j in os.path.splitext(i)[0].split("_")]) - full_path = os.path.basename(path) + "/" + name + ".rst" + full_path = os.path.basename(path) + "/" + snek(name).replace("_", "-") + ".rst" if level: full_path = base + "/" + full_path @@ -65,7 +70,7 @@ def generate(source_path, base): title=name, title_markup="=" * len(name), full_class_path="pyrogram.api.{}".format( - os.path.splitext(full_path)[0].replace("/", ".") + ".".join(full_path.split("/")[:-1]) + "." + name ) ) ) @@ -82,7 +87,7 @@ def generate(source_path, base): entities = [] for i in v: - entities.append(i) + entities.append(snek(i).replace("_", "-")) if k != base: inner_path = base + "/" + k + "/index" + ".rst" @@ -98,6 +103,7 @@ def generate(source_path, base): with open(DESTINATION + "/" + inner_path, "w", encoding="utf-8") as f: if k == base: f.write(":tocdepth: 1\n\n") + k = "Raw " + k f.write( toctree.format( @@ -115,6 +121,8 @@ def start(): global page_template global toctree + shutil.rmtree(DESTINATION, ignore_errors=True) + with open(HOME + "/template/page.txt", encoding="utf-8") as f: page_template = f.read() From a98455886036c61899665e6033d87b98c72882c4 Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Fri, 31 May 2019 00:20:09 +0200 Subject: [PATCH 29/50] Rename methods dealing with profile pictures --- docs/source/api/methods.rst | 18 +++--- pyrogram/client/ext/base_client.py | 3 + pyrogram/client/methods/users/__init__.py | 20 ++++--- ...ete_photos.py => delete_profile_photos.py} | 4 +- ...t_user_photos.py => get_profile_photos.py} | 57 ++++++++++++++----- ...s_count.py => get_profile_photos_count.py} | 21 ++----- .../{set_photo.py => set_profile_photo.py} | 4 +- 7 files changed, 74 insertions(+), 53 deletions(-) rename pyrogram/client/methods/users/{delete_photos.py => delete_profile_photos.py} (96%) rename pyrogram/client/methods/users/{get_user_photos.py => get_profile_photos.py} (55%) rename pyrogram/client/methods/users/{get_user_photos_count.py => get_profile_photos_count.py} (72%) rename pyrogram/client/methods/users/{set_photo.py => set_profile_photo.py} (96%) diff --git a/docs/source/api/methods.rst b/docs/source/api/methods.rst index 760c332b..2d3d8f23 100644 --- a/docs/source/api/methods.rst +++ b/docs/source/api/methods.rst @@ -111,10 +111,11 @@ Users - :meth:`~Client.get_me` - :meth:`~Client.get_users` - - :meth:`~Client.get_user_photos` - - :meth:`~Client.get_user_photos_count` - - :meth:`~Client.set_photo` - - :meth:`~Client.delete_photos` + - :meth:`~Client.get_profile_photos` + - :meth:`~Client.get_profile_photos_count` + - :meth:`~Client.iter_profile_photos` + - :meth:`~Client.set_profile_photo` + - :meth:`~Client.delete_profile_photos` - :meth:`~Client.update_username` - :meth:`~Client.get_user_dc` @@ -232,10 +233,11 @@ Details .. Users .. automethod:: Client.get_me() .. automethod:: Client.get_users() -.. automethod:: Client.get_user_photos() -.. automethod:: Client.get_user_photos_count() -.. automethod:: Client.set_photo() -.. automethod:: Client.delete_photos() +.. automethod:: Client.get_profile_photos() +.. automethod:: Client.get_profile_photos_count() +.. automethod:: Client.iter_profile_photos() +.. automethod:: Client.set_profile_photo() +.. automethod:: Client.delete_profile_photos() .. automethod:: Client.update_username() .. automethod:: Client.get_user_dc() diff --git a/pyrogram/client/ext/base_client.py b/pyrogram/client/ext/base_client.py index 3397c8d3..b193ceee 100644 --- a/pyrogram/client/ext/base_client.py +++ b/pyrogram/client/ext/base_client.py @@ -159,3 +159,6 @@ class BaseClient: def guess_extension(self, *args, **kwargs): pass + + def get_profile_photos(self, *args, **kwargs): + pass diff --git a/pyrogram/client/methods/users/__init__.py b/pyrogram/client/methods/users/__init__.py index bbc2df23..20b50ce9 100644 --- a/pyrogram/client/methods/users/__init__.py +++ b/pyrogram/client/methods/users/__init__.py @@ -16,24 +16,26 @@ # You should have received a copy of the GNU Lesser General Public License # along with Pyrogram. If not, see . -from .delete_photos import DeletePhotos +from .delete_profile_photos import DeleteProfilePhotos from .get_me import GetMe +from .get_profile_photos import GetProfilePhotos +from .get_profile_photos_count import GetProfilePhotosCount from .get_user_dc import GetUserDC -from .get_user_photos import GetUserPhotos -from .get_user_photos_count import GetUserPhotosCount from .get_users import GetUsers -from .set_photo import SetPhoto +from .iter_profile_photos import IterProfilePhotos +from .set_profile_photo import SetProfilePhoto from .update_username import UpdateUsername class Users( - GetUserPhotos, - SetPhoto, - DeletePhotos, + GetProfilePhotos, + SetProfilePhoto, + DeleteProfilePhotos, GetUsers, GetMe, UpdateUsername, - GetUserPhotosCount, - GetUserDC + GetProfilePhotosCount, + GetUserDC, + IterProfilePhotos ): pass diff --git a/pyrogram/client/methods/users/delete_photos.py b/pyrogram/client/methods/users/delete_profile_photos.py similarity index 96% rename from pyrogram/client/methods/users/delete_photos.py rename to pyrogram/client/methods/users/delete_profile_photos.py index 30b3b533..1b46382c 100644 --- a/pyrogram/client/methods/users/delete_photos.py +++ b/pyrogram/client/methods/users/delete_profile_photos.py @@ -24,8 +24,8 @@ from pyrogram.api import functions, types from ...ext import BaseClient -class DeletePhotos(BaseClient): - def delete_photos( +class DeleteProfilePhotos(BaseClient): + def delete_profile_photos( self, id: Union[str, List[str]] ) -> bool: diff --git a/pyrogram/client/methods/users/get_user_photos.py b/pyrogram/client/methods/users/get_profile_photos.py similarity index 55% rename from pyrogram/client/methods/users/get_user_photos.py rename to pyrogram/client/methods/users/get_profile_photos.py index e134a502..d45bd5b6 100644 --- a/pyrogram/client/methods/users/get_user_photos.py +++ b/pyrogram/client/methods/users/get_profile_photos.py @@ -19,21 +19,21 @@ from typing import Union import pyrogram -from pyrogram.api import functions +from pyrogram.api import functions, types from ...ext import BaseClient -class GetUserPhotos(BaseClient): - def get_user_photos( +class GetProfilePhotos(BaseClient): + def get_profile_photos( self, - user_id: Union[int, str], + chat_id: Union[int, str], offset: int = 0, limit: int = 100 ) -> "pyrogram.Photos": - """Get a list of profile pictures for a user. + """Get a list of profile pictures for a user or a chat. Parameters: - user_id (``int`` | ``str``): + chat_id (``int`` | ``str``): Unique identifier (int) or username (str) of the target chat. For your personal cloud (Saved Messages) you can simply use "me" or "self". For a contact that exists in your Telegram address book you can use his phone number (str). @@ -52,14 +52,41 @@ class GetUserPhotos(BaseClient): Raises: RPCError: In case of a Telegram RPC error. """ - return pyrogram.Photos._parse( - self, - self.send( - functions.photos.GetUserPhotos( - user_id=self.resolve_peer(user_id), - offset=offset, - max_id=0, - limit=limit + peer_id = self.resolve_peer(chat_id) + + if isinstance(peer_id, types.InputPeerUser): + return pyrogram.Photos._parse( + self, + self.send( + functions.photos.GetUserPhotos( + user_id=peer_id, + offset=offset, + max_id=0, + limit=limit + ) ) ) - ) + else: + new_chat_photos = pyrogram.Messages._parse( + self, + self.send( + functions.messages.Search( + peer=peer_id, + q="", + filter=types.InputMessagesFilterChatPhotos(), + min_date=0, + max_date=0, + offset_id=0, + add_offset=offset, + limit=limit, + max_id=0, + min_id=0, + hash=0 + ) + ) + ) + + return pyrogram.Photos( + total_count=new_chat_photos.total_count, + photos=[m.new_chat_photo for m in new_chat_photos.messages][:limit] + ) diff --git a/pyrogram/client/methods/users/get_user_photos_count.py b/pyrogram/client/methods/users/get_profile_photos_count.py similarity index 72% rename from pyrogram/client/methods/users/get_user_photos_count.py rename to pyrogram/client/methods/users/get_profile_photos_count.py index 3bbaf55b..a65e0ada 100644 --- a/pyrogram/client/methods/users/get_user_photos_count.py +++ b/pyrogram/client/methods/users/get_profile_photos_count.py @@ -18,16 +18,15 @@ from typing import Union -from pyrogram.api import functions, types from ...ext import BaseClient -class GetUserPhotosCount(BaseClient): - def get_user_photos_count(self, user_id: Union[int, str]) -> int: +class GetProfilePhotosCount(BaseClient): + def get_profile_photos_count(self, chat_id: Union[int, str]) -> int: """Get the total count of profile pictures for a user. Parameters: - user_id (``int`` | ``str``): + chat_id (``int`` | ``str``): Unique identifier (int) or username (str) of the target chat. For your personal cloud (Saved Messages) you can simply use "me" or "self". For a contact that exists in your Telegram address book you can use his phone number (str). @@ -39,16 +38,4 @@ class GetUserPhotosCount(BaseClient): RPCError: In case of a Telegram RPC error. """ - r = self.send( - functions.photos.GetUserPhotos( - user_id=self.resolve_peer(user_id), - offset=0, - max_id=0, - limit=1 - ) - ) - - if isinstance(r, types.photos.Photos): - return len(r.photos) - else: - return r.count + return self.get_profile_photos(chat_id, limit=1).total_count diff --git a/pyrogram/client/methods/users/set_photo.py b/pyrogram/client/methods/users/set_profile_photo.py similarity index 96% rename from pyrogram/client/methods/users/set_photo.py rename to pyrogram/client/methods/users/set_profile_photo.py index cd7f955d..a713fd34 100644 --- a/pyrogram/client/methods/users/set_photo.py +++ b/pyrogram/client/methods/users/set_profile_photo.py @@ -20,8 +20,8 @@ from pyrogram.api import functions from ...ext import BaseClient -class SetPhoto(BaseClient): - def set_photo( +class SetProfilePhoto(BaseClient): + def set_profile_photo( self, photo: str ) -> bool: From 364d3ec1450af42fc4148b53a90d50b1d39b482b Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Fri, 31 May 2019 01:09:03 +0200 Subject: [PATCH 30/50] Revert: Improve codegen scripts --- compiler/api/compiler.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/api/compiler.py b/compiler/api/compiler.py index 6566bc8e..64e88c9d 100644 --- a/compiler/api/compiler.py +++ b/compiler/api/compiler.py @@ -67,7 +67,7 @@ def get_docstring_arg_type(t: str, is_list: bool = False, is_pyrogram_type: bool n = len(t) - 1 t = (("e" if is_list else "E") + "ither " if n else "") + ", ".join( - ":obj:`~{}.{}`".format( + ":obj:`{1} <{0}.{1}>`".format( "pyrogram.types" if is_pyrogram_type else "pyrogram.api.types", i.replace("pyrogram.", "") ) @@ -88,7 +88,7 @@ def get_references(t: str): n = len(t) - 1 t = ", ".join( - ":obj:`~pyrogram.api.functions.{}`".format(i) + ":obj:`{0} `".format(i) for i in t ) From 2df9f53e5435a871219273866e4050f9639101de Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Fri, 31 May 2019 13:18:19 +0200 Subject: [PATCH 31/50] Add a FAQ about expiring sms codes --- docs/source/faq.rst | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/docs/source/faq.rst b/docs/source/faq.rst index 7d7e9032..33e7282f 100644 --- a/docs/source/faq.rst +++ b/docs/source/faq.rst @@ -155,6 +155,15 @@ things: chats). - The chat id argument you passed is in form of a string; you have to convert it into an integer with ``int(chat_id)``. +My verification code expires immediately! +----------------------------------------- + +That is because you likely shared it across any of your Telegram chats. Yes, that's right: the server keeps scanning the +messages you send and if an active verification code is found it will immediately expire, automatically. + +The reason behind this is to protect unaware users from giving their account access to any potential scammer, but if you +legitimately want to share your account(s) verification codes, consider scrambling them, e.g. ``12345`` → ``1-2-3-4-5``. + My account has been deactivated/limited! ---------------------------------------- From 48a5da8958f55763f7cd07bb5c7f38e112ac9f9d Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Fri, 31 May 2019 16:36:20 +0200 Subject: [PATCH 32/50] Let FutureSalt(s) attributes be plain integer instead of datetime values --- pyrogram/api/core/future_salt.py | 7 +++---- pyrogram/api/core/future_salts.py | 5 ++--- pyrogram/session/session.py | 3 ++- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/pyrogram/api/core/future_salt.py b/pyrogram/api/core/future_salt.py index 4ee8197b..c4ccea3d 100644 --- a/pyrogram/api/core/future_salt.py +++ b/pyrogram/api/core/future_salt.py @@ -16,7 +16,6 @@ # You should have received a copy of the GNU Lesser General Public License # along with Pyrogram. If not, see . -from datetime import datetime from io import BytesIO from .object import Object @@ -30,15 +29,15 @@ class FutureSalt(Object): QUALNAME = "FutureSalt" - def __init__(self, valid_since: int or datetime, valid_until: int or datetime, salt: int): + def __init__(self, valid_since: int, valid_until: int, salt: int): self.valid_since = valid_since self.valid_until = valid_until self.salt = salt @staticmethod def read(b: BytesIO, *args) -> "FutureSalt": - valid_since = datetime.fromtimestamp(Int.read(b)) - valid_until = datetime.fromtimestamp(Int.read(b)) + valid_since = Int.read(b) + valid_until = Int.read(b) salt = Long.read(b) return FutureSalt(valid_since, valid_until, salt) diff --git a/pyrogram/api/core/future_salts.py b/pyrogram/api/core/future_salts.py index cf6a9902..91ee7b51 100644 --- a/pyrogram/api/core/future_salts.py +++ b/pyrogram/api/core/future_salts.py @@ -16,7 +16,6 @@ # You should have received a copy of the GNU Lesser General Public License # along with Pyrogram. If not, see . -from datetime import datetime from io import BytesIO from . import FutureSalt @@ -31,7 +30,7 @@ class FutureSalts(Object): QUALNAME = "FutureSalts" - def __init__(self, req_msg_id: int, now: int or datetime, salts: list): + def __init__(self, req_msg_id: int, now: int, salts: list): self.req_msg_id = req_msg_id self.now = now self.salts = salts @@ -39,7 +38,7 @@ class FutureSalts(Object): @staticmethod def read(b: BytesIO, *args) -> "FutureSalts": req_msg_id = Long.read(b) - now = datetime.fromtimestamp(Int.read(b)) + now = Int.read(b) count = Int.read(b) salts = [FutureSalt.read(b) for _ in range(count)] diff --git a/pyrogram/session/session.py b/pyrogram/session/session.py index 66207037..e4260be4 100644 --- a/pyrogram/session/session.py +++ b/pyrogram/session/session.py @@ -350,7 +350,8 @@ class Session: # Seconds to wait until middle-overlap, which is # 15 minutes before/after the current/next salt end/start time - dt = (self.current_salt.valid_until - now).total_seconds() - 900 + valid_until = datetime.fromtimestamp(self.current_salt.valid_until) + dt = (valid_until - now).total_seconds() - 900 log.debug("Current salt: {} | Next salt in {:.0f}m {:.0f}s ({})".format( self.current_salt.salt, From 341c41e7efecc6f7bd6efc3b49ff7353a89ce927 Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Sat, 1 Jun 2019 13:10:06 +0200 Subject: [PATCH 33/50] Add MESSAGE_EDIT_TIME_EXPIRED 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 cbea977a..fa6ff67e 100644 --- a/compiler/error/source/400_BAD_REQUEST.tsv +++ b/compiler/error/source/400_BAD_REQUEST.tsv @@ -98,4 +98,5 @@ RESULTS_TOO_MUCH The result contains too many items RESULT_ID_DUPLICATE The result contains items with duplicated identifiers ACCESS_TOKEN_INVALID The bot access token is invalid INVITE_HASH_EXPIRED The chat invite link is no longer valid -USER_BANNED_IN_CHANNEL You are limited, check @SpamBot for details \ No newline at end of file +USER_BANNED_IN_CHANNEL You are limited, check @SpamBot for details +MESSAGE_EDIT_TIME_EXPIRED You can no longer edit this message \ No newline at end of file From e7f6e9ec66901151e9cda6182b71179eb067acea Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Sat, 1 Jun 2019 13:15:41 +0200 Subject: [PATCH 34/50] Cast is_bot value to bool --- pyrogram/client/ext/syncer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyrogram/client/ext/syncer.py b/pyrogram/client/ext/syncer.py index 71dc3f35..c3921205 100644 --- a/pyrogram/client/ext/syncer.py +++ b/pyrogram/client/ext/syncer.py @@ -94,7 +94,7 @@ class Syncer: auth_key=auth_key, user_id=client.user_id, date=int(time.time()), - is_bot=client.is_bot, + is_bot=bool(client.is_bot), peers_by_id={ k: getattr(v, "access_hash", None) for k, v in client.peers_by_id.copy().items() From f6361cd20fa714ebdaed2c894dc40c0811ffbbc8 Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Sat, 1 Jun 2019 13:17:04 +0200 Subject: [PATCH 35/50] Allow bare lists from the MTProto API to be printed nicely --- pyrogram/api/core/__init__.py | 1 + pyrogram/api/core/list.py | 26 ++++++++++++++ pyrogram/api/core/object.py | 47 +++++++++++++------------- pyrogram/api/core/primitives/vector.py | 5 +-- 4 files changed, 53 insertions(+), 26 deletions(-) create mode 100644 pyrogram/api/core/list.py diff --git a/pyrogram/api/core/__init__.py b/pyrogram/api/core/__init__.py index daba6b7c..bf596446 100644 --- a/pyrogram/api/core/__init__.py +++ b/pyrogram/api/core/__init__.py @@ -19,6 +19,7 @@ from .future_salt import FutureSalt from .future_salts import FutureSalts from .gzip_packed import GzipPacked +from .list import List from .message import Message from .msg_container import MsgContainer from .object import Object diff --git a/pyrogram/api/core/list.py b/pyrogram/api/core/list.py new file mode 100644 index 00000000..1f55dc45 --- /dev/null +++ b/pyrogram/api/core/list.py @@ -0,0 +1,26 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-2019 Dan Tès +# +# This file is part of Pyrogram. +# +# Pyrogram is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pyrogram is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Pyrogram. If not, see . + +from .object import Object + + +class List(list, Object): + __slots__ = [] + + def __repr__(self): + return "pyrogram.api.core.List([{}])".format(",".join(Object.__str__(i) for i in self)) diff --git a/pyrogram/api/core/object.py b/pyrogram/api/core/object.py index ace7a59a..9d1a4852 100644 --- a/pyrogram/api/core/object.py +++ b/pyrogram/api/core/object.py @@ -17,7 +17,6 @@ # along with Pyrogram. If not, see . from collections import OrderedDict -from datetime import datetime from io import BytesIO from json import dumps @@ -36,32 +35,22 @@ class Object: def write(self, *args) -> bytes: pass - def __eq__(self, other: "Object") -> bool: - for attr in self.__slots__: - try: - if getattr(self, attr) != getattr(other, attr): - return False - except AttributeError: - return False + @staticmethod + def default(obj: "Object"): + if isinstance(obj, bytes): + return repr(obj) - return True + return OrderedDict( + [("_", obj.QUALNAME)] + + [ + (attr, getattr(obj, attr)) + for attr in obj.__slots__ + if getattr(obj, attr) is not None + ] + ) def __str__(self) -> str: - def default(obj: Object): - try: - return OrderedDict( - [("_", obj.QUALNAME)] - + [(attr, getattr(obj, attr)) - for attr in obj.__slots__ - if getattr(obj, attr) is not None] - ) - except AttributeError: - if isinstance(obj, datetime): - return obj.strftime("%d-%b-%Y %H:%M:%S") - else: - return repr(obj) - - return dumps(self, indent=4, default=default, ensure_ascii=False) + return dumps(self, indent=4, default=Object.default, ensure_ascii=False) def __repr__(self) -> str: return "pyrogram.api.{}({})".format( @@ -73,6 +62,16 @@ class Object: ) ) + def __eq__(self, other: "Object") -> bool: + for attr in self.__slots__: + try: + if getattr(self, attr) != getattr(other, attr): + return False + except AttributeError: + return False + + return True + def __len__(self) -> int: return len(self.write()) diff --git a/pyrogram/api/core/primitives/vector.py b/pyrogram/api/core/primitives/vector.py index cd24ec35..720486f2 100644 --- a/pyrogram/api/core/primitives/vector.py +++ b/pyrogram/api/core/primitives/vector.py @@ -19,6 +19,7 @@ from io import BytesIO from . import Int +from ..list import List from ..object import Object @@ -37,11 +38,11 @@ class Vector(Object): @staticmethod def read(b: BytesIO, t: Object = None) -> list: - return [ + return List( t.read(b) if t else Vector._read(b) for _ in range(Int.read(b)) - ] + ) def __new__(cls, value: list, t: Object = None) -> bytes: return b"".join( From d243ebc2cdff4205334e5592d83abe80d4a1d277 Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Sat, 1 Jun 2019 13:18:48 +0200 Subject: [PATCH 36/50] Performance improvements --- pyrogram/client/client.py | 43 +++++++++++++----------------- pyrogram/client/ext/base_client.py | 1 - pyrogram/client/ext/dispatcher.py | 9 +++---- 3 files changed, 22 insertions(+), 31 deletions(-) diff --git a/pyrogram/client/client.py b/pyrogram/client/client.py index e93e3ff8..2ba6b8fa 100644 --- a/pyrogram/client/client.py +++ b/pyrogram/client/client.py @@ -765,7 +765,9 @@ class Client(Methods, BaseClient): types.Channel, types.ChannelForbidden ] ] - ): + ) -> bool: + is_min = False + for entity in entities: if isinstance(entity, types.User): user_id = entity.id @@ -773,6 +775,7 @@ class Client(Methods, BaseClient): access_hash = entity.access_hash if access_hash is None: + is_min = True continue username = entity.username @@ -808,6 +811,7 @@ class Client(Methods, BaseClient): access_hash = entity.access_hash if access_hash is None: + is_min = True continue username = getattr(entity, "username", None) @@ -822,6 +826,8 @@ class Client(Methods, BaseClient): if username is not None: self.peers_by_username[username.lower()] = input_peer + return is_min + def download_worker(self): name = threading.current_thread().name log.debug("{} started".format(name)) @@ -837,7 +843,6 @@ class Client(Methods, BaseClient): try: data, file_name, done, progress, progress_args, path = packet - data = data # type: BaseClient.FileData directory, file_name = os.path.split(file_name) directory = directory or "downloads" @@ -917,8 +922,10 @@ class Client(Methods, BaseClient): try: if isinstance(updates, (types.Update, types.UpdatesCombined)): - self.fetch_peers(updates.users) - self.fetch_peers(updates.chats) + is_min = self.fetch_peers(updates.users) or self.fetch_peers(updates.chats) + + users = {u.id: u for u in updates.users} + chats = {c.id: c for c in updates.chats} for update in updates.updates: channel_id = getattr( @@ -935,7 +942,7 @@ class Client(Methods, BaseClient): if isinstance(update, types.UpdateChannelTooLong): log.warning(update) - if isinstance(update, types.UpdateNewChannelMessage): + if isinstance(update, types.UpdateNewChannelMessage) and is_min: message = update.message if not isinstance(message, types.MessageEmpty): @@ -957,22 +964,10 @@ class Client(Methods, BaseClient): pass else: if not isinstance(diff, types.updates.ChannelDifferenceEmpty): - updates.users += diff.users - updates.chats += diff.chats + users.update({u.id: u for u in diff.users}) + chats.update({c.id: c for c in diff.chats}) - if channel_id and pts: - if channel_id not in self.channels_pts: - self.channels_pts[channel_id] = [] - - if pts in self.channels_pts[channel_id]: - continue - - self.channels_pts[channel_id].append(pts) - - if len(self.channels_pts[channel_id]) > 50: - self.channels_pts[channel_id] = self.channels_pts[channel_id][25:] - - self.dispatcher.updates_queue.put((update, updates.users, updates.chats)) + self.dispatcher.updates_queue.put((update, users, chats)) elif isinstance(updates, (types.UpdateShortMessage, types.UpdateShortChatMessage)): diff = self.send( functions.updates.GetDifference( @@ -989,13 +984,13 @@ class Client(Methods, BaseClient): pts=updates.pts, pts_count=updates.pts_count ), - diff.users, - diff.chats + {u.id: u for u in diff.users}, + {c.id: c for c in diff.chats} )) else: - self.dispatcher.updates_queue.put((diff.other_updates[0], [], [])) + self.dispatcher.updates_queue.put((diff.other_updates[0], {}, {})) elif isinstance(updates, types.UpdateShort): - self.dispatcher.updates_queue.put((updates.update, [], [])) + self.dispatcher.updates_queue.put((updates.update, {}, {})) elif isinstance(updates, types.UpdatesTooLong): log.warning(updates) except Exception as e: diff --git a/pyrogram/client/ext/base_client.py b/pyrogram/client/ext/base_client.py index b193ceee..9c0d661e 100644 --- a/pyrogram/client/ext/base_client.py +++ b/pyrogram/client/ext/base_client.py @@ -96,7 +96,6 @@ class BaseClient: self.date = None self.rnd_id = MsgId - self.channels_pts = {} self.peers_by_id = {} self.peers_by_username = {} diff --git a/pyrogram/client/ext/dispatcher.py b/pyrogram/client/ext/dispatcher.py index 1004095b..2f1ec2b9 100644 --- a/pyrogram/client/ext/dispatcher.py +++ b/pyrogram/client/ext/dispatcher.py @@ -125,16 +125,13 @@ class Dispatcher: log.debug("{} started".format(name)) while True: - update = self.updates_queue.get() + packet = self.updates_queue.get() - if update is None: + if packet is None: break try: - users = {i.id: i for i in update[1]} - chats = {i.id: i for i in update[2]} - update = update[0] - + update, users, chats = packet parser = self.update_parsers.get(type(update), None) parsed_update, handler_type = ( From dc94da3895de3d9497c16bdfc706d11b57c19657 Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Sat, 1 Jun 2019 14:04:39 +0200 Subject: [PATCH 37/50] Add application/x-tgsticker mime type with .tgs as extension --- pyrogram/client/ext/mime.types | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pyrogram/client/ext/mime.types b/pyrogram/client/ext/mime.types index 4db43cae..50ec065d 100644 --- a/pyrogram/client/ext/mime.types +++ b/pyrogram/client/ext/mime.types @@ -1852,4 +1852,7 @@ video/x-ms-wvx wvx video/x-msvideo avi video/x-sgi-movie movie video/x-smv smv -x-conference/x-cooltalk ice \ No newline at end of file +x-conference/x-cooltalk ice + +# Telegram animated stickers +application/x-tgsticker tgs \ No newline at end of file From 1f2be4f1cef6630831d99beb14c8eebcab9edb35 Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Sat, 1 Jun 2019 14:05:25 +0200 Subject: [PATCH 38/50] Add send_animated_sticker method --- pyrogram/client/methods/messages/__init__.py | 4 +- .../methods/messages/send_animated_sticker.py | 141 ++++++++++++++++++ 2 files changed, 144 insertions(+), 1 deletion(-) create mode 100644 pyrogram/client/methods/messages/send_animated_sticker.py diff --git a/pyrogram/client/methods/messages/__init__.py b/pyrogram/client/methods/messages/__init__.py index e843aa7c..9ed6e33b 100644 --- a/pyrogram/client/methods/messages/__init__.py +++ b/pyrogram/client/methods/messages/__init__.py @@ -28,6 +28,7 @@ from .get_history_count import GetHistoryCount from .get_messages import GetMessages from .iter_history import IterHistory from .retract_vote import RetractVote +from .send_animated_sticker import SendAnimatedSticker from .send_animation import SendAnimation from .send_audio import SendAudio from .send_cached_media import SendCachedMedia @@ -78,6 +79,7 @@ class Messages( DownloadMedia, IterHistory, SendCachedMedia, - GetHistoryCount + GetHistoryCount, + SendAnimatedSticker ): pass diff --git a/pyrogram/client/methods/messages/send_animated_sticker.py b/pyrogram/client/methods/messages/send_animated_sticker.py new file mode 100644 index 00000000..789ca06d --- /dev/null +++ b/pyrogram/client/methods/messages/send_animated_sticker.py @@ -0,0 +1,141 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-2019 Dan Tès +# +# This file is part of Pyrogram. +# +# Pyrogram is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pyrogram is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Pyrogram. If not, see . + +import os +from typing import Union + +import pyrogram +from pyrogram.api import functions, types +from pyrogram.client.ext import BaseClient, utils +from pyrogram.errors import FilePartMissing + + +class SendAnimatedSticker(BaseClient): + def send_animated_sticker( + self, + chat_id: Union[int, str], + animated_sticker: str, + disable_notification: bool = None, + reply_to_message_id: int = None, + reply_markup: Union[ + "pyrogram.InlineKeyboardMarkup", + "pyrogram.ReplyKeyboardMarkup", + "pyrogram.ReplyKeyboardRemove", + "pyrogram.ForceReply" + ] = None, + progress: callable = None, + progress_args: tuple = () + ) -> Union["pyrogram.Message", None]: + """Send .tgs animated stickers. + + Parameters: + chat_id (``int`` | ``str``): + Unique identifier (int) or username (str) of the target chat. + For your personal cloud (Saved Messages) you can simply use "me" or "self". + For a contact that exists in your Telegram address book you can use his phone number (str). + + animated_sticker (``str``): + Animated sticker to send. + Pass a file_id as string to send a animated sticker that exists on the Telegram servers, + pass an HTTP URL as a string for Telegram to get a .webp animated sticker file from the Internet, or + pass a file path as string to upload a new animated sticker that exists on your local machine. + + disable_notification (``bool``, *optional*): + Sends the message silently. + Users will receive a notification with no sound. + + reply_to_message_id (``int``, *optional*): + If the message is a reply, ID of the original message. + + reply_markup (:obj:`InlineKeyboardMarkup` | :obj:`ReplyKeyboardMarkup` | :obj:`ReplyKeyboardRemove` | :obj:`ForceReply`, *optional*): + Additional interface options. An object for an inline keyboard, custom reply keyboard, + instructions to remove reply keyboard or to force a reply from the user. + + progress (``callable``, *optional*): + Pass a callback function to view the upload progress. + The function must take *(client, current, total, \*args)* as positional arguments (look at the section + below for a detailed description). + + progress_args (``tuple``, *optional*): + Extra custom arguments for the progress callback function. Useful, for example, if you want to pass + a chat_id and a message_id in order to edit a message with the updated progress. + + Other Parameters: + client (:obj:`Client`): + The Client itself, useful when you want to call other API methods inside the callback function. + + current (``int``): + The amount of bytes uploaded so far. + + total (``int``): + The size of the file. + + *args (``tuple``, *optional*): + Extra custom arguments as defined in the *progress_args* parameter. + You can either keep *\*args* or add every single extra argument in your function signature. + + Returns: + :obj:`Message` | ``None``: On success, the sent animated sticker message is returned, otherwise, in case the + upload is deliberately stopped with :meth:`~Client.stop_transmission`, None is returned. + Raises: + RPCError: In case of a Telegram RPC error. + """ + file = None + + try: + if os.path.exists(animated_sticker): + file = self.save_file(animated_sticker, progress=progress, progress_args=progress_args) + media = types.InputMediaUploadedDocument( + mime_type=self.guess_mime_type(animated_sticker) or "application/x-tgsticker", + file=file, + attributes=[ + types.DocumentAttributeFilename(file_name=os.path.basename(animated_sticker)) + ] + ) + elif animated_sticker.startswith("http"): + media = types.InputMediaDocumentExternal( + url=animated_sticker + ) + else: + media = utils.get_input_media_from_file_id(animated_sticker, 8) + + while True: + try: + r = self.send( + functions.messages.SendMedia( + peer=self.resolve_peer(chat_id), + media=media, + silent=disable_notification or None, + reply_to_msg_id=reply_to_message_id, + random_id=self.rnd_id(), + reply_markup=reply_markup.write() if reply_markup else None, + message="" + ) + ) + except FilePartMissing as e: + self.save_file(animated_sticker, file_id=file.id, file_part=e.x) + else: + for i in r.updates: + if isinstance(i, (types.UpdateNewMessage, types.UpdateNewChannelMessage)): + return pyrogram.Message._parse( + self, i.message, + {i.id: i for i in r.users}, + {i.id: i for i in r.chats} + ) + except BaseClient.StopTransmission: + return None From acc0fab311d2b8af5d806d0bd9cc015b98daf065 Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Sat, 1 Jun 2019 14:07:45 +0200 Subject: [PATCH 39/50] Fix animated stickers media type. They are documents for now --- pyrogram/client/methods/messages/send_animated_sticker.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyrogram/client/methods/messages/send_animated_sticker.py b/pyrogram/client/methods/messages/send_animated_sticker.py index 789ca06d..6fd0c647 100644 --- a/pyrogram/client/methods/messages/send_animated_sticker.py +++ b/pyrogram/client/methods/messages/send_animated_sticker.py @@ -112,7 +112,7 @@ class SendAnimatedSticker(BaseClient): url=animated_sticker ) else: - media = utils.get_input_media_from_file_id(animated_sticker, 8) + media = utils.get_input_media_from_file_id(animated_sticker, 5) while True: try: From 56f1a8ca9d124a092d8da6cf2f4c9d4de9321a48 Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Sat, 1 Jun 2019 15:25:42 +0200 Subject: [PATCH 40/50] Add send_animated_sticker to docs --- docs/source/api/methods.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/source/api/methods.rst b/docs/source/api/methods.rst index 2d3d8f23..b9fa180c 100644 --- a/docs/source/api/methods.rst +++ b/docs/source/api/methods.rst @@ -48,6 +48,7 @@ Messages - :meth:`~Client.send_audio` - :meth:`~Client.send_document` - :meth:`~Client.send_sticker` + - :meth:`~Client.send_animated_sticker` - :meth:`~Client.send_video` - :meth:`~Client.send_animation` - :meth:`~Client.send_voice` @@ -180,6 +181,7 @@ Details .. automethod:: Client.send_audio() .. automethod:: Client.send_document() .. automethod:: Client.send_sticker() +.. automethod:: Client.send_animated_sticker() .. automethod:: Client.send_video() .. automethod:: Client.send_animation() .. automethod:: Client.send_voice() From e9a2087fe094c40edea2601399ff78cfdfad0ba6 Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Sat, 1 Jun 2019 15:36:53 +0200 Subject: [PATCH 41/50] Fix List not calling __repr__ --- pyrogram/api/core/list.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pyrogram/api/core/list.py b/pyrogram/api/core/list.py index 1f55dc45..922ec64d 100644 --- a/pyrogram/api/core/list.py +++ b/pyrogram/api/core/list.py @@ -23,4 +23,6 @@ class List(list, Object): __slots__ = [] def __repr__(self): - return "pyrogram.api.core.List([{}])".format(",".join(Object.__str__(i) for i in self)) + return "pyrogram.api.core.List([{}])".format( + ",".join(Object.__repr__(i) for i in self) + ) From 0a96355c5dcda94a7ce982421ca0eeba66adf80d Mon Sep 17 00:00:00 2001 From: ColinShark Date: Sat, 1 Jun 2019 23:31:17 +0200 Subject: [PATCH 42/50] Add Filter for Callback_Query.data --- pyrogram/client/filters/filters.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/pyrogram/client/filters/filters.py b/pyrogram/client/filters/filters.py index 9c80d870..a3e39117 100644 --- a/pyrogram/client/filters/filters.py +++ b/pyrogram/client/filters/filters.py @@ -339,4 +339,19 @@ class Filters: and message.from_user.is_self and not message.outgoing))) + @staticmethod + def data(data: str or bytes = None): + """Filter callback queries for their data. + + Parameters: + data (``str`` | ``bytes``): + Pass the data you want to filter for. + Defaults to None (no data). + """ + + def f(_, cb): + return bool(cb.data and cb.data == _.d) + + return create("Data", f, d=data) + dan = create("Dan", lambda _, m: bool(m.from_user and m.from_user.id == 23122162)) From 2eba6e58f9f0eb983aedc25ea9b0c250bd52980a Mon Sep 17 00:00:00 2001 From: ColinShark Date: Sat, 1 Jun 2019 23:34:20 +0200 Subject: [PATCH 43/50] Remove Optionality for args --- pyrogram/client/filters/filters.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyrogram/client/filters/filters.py b/pyrogram/client/filters/filters.py index a3e39117..83e862e6 100644 --- a/pyrogram/client/filters/filters.py +++ b/pyrogram/client/filters/filters.py @@ -340,7 +340,7 @@ class Filters: and not message.outgoing))) @staticmethod - def data(data: str or bytes = None): + def data(data: str or bytes): """Filter callback queries for their data. Parameters: From 04aada818e4a6482128ff7448a6a8843b7adf0cc Mon Sep 17 00:00:00 2001 From: ColinShark Date: Sat, 1 Jun 2019 23:36:45 +0200 Subject: [PATCH 44/50] Less arbitrary name for Filter, Adapt Docstring --- pyrogram/client/filters/filters.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pyrogram/client/filters/filters.py b/pyrogram/client/filters/filters.py index 83e862e6..c8b5b2f8 100644 --- a/pyrogram/client/filters/filters.py +++ b/pyrogram/client/filters/filters.py @@ -346,12 +346,11 @@ class Filters: Parameters: data (``str`` | ``bytes``): Pass the data you want to filter for. - Defaults to None (no data). """ def f(_, cb): return bool(cb.data and cb.data == _.d) - return create("Data", f, d=data) + return create("CallbackData", f, d=data) dan = create("Dan", lambda _, m: bool(m.from_user and m.from_user.id == 23122162)) From d3cb386a6f68eaa9ab94656c8826dd9b7c86d82b Mon Sep 17 00:00:00 2001 From: ColinShark Date: Sat, 1 Jun 2019 23:39:26 +0200 Subject: [PATCH 45/50] Appropiate naming --- pyrogram/client/filters/filters.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyrogram/client/filters/filters.py b/pyrogram/client/filters/filters.py index c8b5b2f8..1bcc858d 100644 --- a/pyrogram/client/filters/filters.py +++ b/pyrogram/client/filters/filters.py @@ -340,7 +340,7 @@ class Filters: and not message.outgoing))) @staticmethod - def data(data: str or bytes): + def callback_data(data: str or bytes): """Filter callback queries for their data. Parameters: From 12cc6fa4eb038af53621e14cf0b0565cc3b5db6f Mon Sep 17 00:00:00 2001 From: ColinShark Date: Sun, 2 Jun 2019 00:13:52 +0200 Subject: [PATCH 46/50] Removed Placeholder, break down comparison --- pyrogram/client/filters/filters.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pyrogram/client/filters/filters.py b/pyrogram/client/filters/filters.py index 1bcc858d..12d5a69e 100644 --- a/pyrogram/client/filters/filters.py +++ b/pyrogram/client/filters/filters.py @@ -348,9 +348,9 @@ class Filters: Pass the data you want to filter for. """ - def f(_, cb): - return bool(cb.data and cb.data == _.d) + def f(flt, cb): + return cb.data == flt.data - return create("CallbackData", f, d=data) + return create("CallbackData", f, data=data) dan = create("Dan", lambda _, m: bool(m.from_user and m.from_user.id == 23122162)) From 5cb709ee75bdf16065a9f213c78f34b87ed41107 Mon Sep 17 00:00:00 2001 From: ColinShark Date: Sun, 2 Jun 2019 00:25:59 +0200 Subject: [PATCH 47/50] Make it one-line --- pyrogram/client/filters/filters.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/pyrogram/client/filters/filters.py b/pyrogram/client/filters/filters.py index 12d5a69e..1d962e85 100644 --- a/pyrogram/client/filters/filters.py +++ b/pyrogram/client/filters/filters.py @@ -348,9 +348,6 @@ class Filters: Pass the data you want to filter for. """ - def f(flt, cb): - return cb.data == flt.data - - return create("CallbackData", f, data=data) + return create("CallbackData", lambda flt, cb: cb.data == flt.data, data=data) dan = create("Dan", lambda _, m: bool(m.from_user and m.from_user.id == 23122162)) From cfec26d3db138aa620f1ffa203f6e44576cb6bad Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Sun, 2 Jun 2019 16:16:16 +0200 Subject: [PATCH 48/50] Add PyrogramList type --- pyrogram/client/types/pyrogram_list.py | 32 ++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 pyrogram/client/types/pyrogram_list.py diff --git a/pyrogram/client/types/pyrogram_list.py b/pyrogram/client/types/pyrogram_list.py new file mode 100644 index 00000000..cb802e51 --- /dev/null +++ b/pyrogram/client/types/pyrogram_list.py @@ -0,0 +1,32 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-2019 Dan Tès +# +# This file is part of Pyrogram. +# +# Pyrogram is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pyrogram is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Pyrogram. If not, see . + +from .pyrogram_type import PyrogramType + + +class PyrogramList(list): + __slots__ = [] + + def __str__(self): + # noinspection PyCallByClass + return PyrogramType.__str__(self) + + def __repr__(self): + return "pyrogram.client.types.pyrogram_list.PyrogramList([{}])".format( + ",".join(PyrogramType.__repr__(i) for i in self) + ) From 6d9443c82e198a82a951e0b96462731632aac029 Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Sun, 2 Jun 2019 18:57:00 +0200 Subject: [PATCH 49/50] Reword some docs sections --- docs/source/license.rst | 2 +- docs/source/support-pyrogram.rst | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/docs/source/license.rst b/docs/source/license.rst index 1c8d99d1..43f59d73 100644 --- a/docs/source/license.rst +++ b/docs/source/license.rst @@ -8,7 +8,7 @@ Pyrogram is free software and is currently licensed under the terms of the `GNU Lesser General Public License v3 or later (LGPLv3+)`_. In short: you may use, redistribute and/or modify it provided that modifications are described and licensed for free under LGPLv3+. -In other words: you can use and integrate Pyrogram into your own code --- either open source, under the same or +In other words: you can use and integrate Pyrogram into your own code --- either open source, under the same or a different license, or even proprietary --- without being required to release the source code of your own applications. However, any modifications to the library itself are required to be published for free under the same LGPLv3+ license. diff --git a/docs/source/support-pyrogram.rst b/docs/source/support-pyrogram.rst index c867b706..81a0e533 100644 --- a/docs/source/support-pyrogram.rst +++ b/docs/source/support-pyrogram.rst @@ -1,8 +1,8 @@ Support Pyrogram ================ -Pyrogram is free and open source software, and thus supported by your love! If you like the project and have found it to -be useful, give Pyrogram a `Star on GitHub`_. Your appreciation means a lot and helps staying motivated. +Pyrogram is free and open source software, and thus powered by your love and support! If you like the project and have +found it to be useful, give Pyrogram a `Star on GitHub`_. Your appreciation means a lot and helps staying motivated. .. raw:: html @@ -12,8 +12,9 @@ be useful, give Pyrogram a `Star on GitHub`_. Your appreciation means a lot and Donate ------ -If you'd also like to donate in order to support Pyrogram -- or any of my `other works`_ -- you can use the PayPal -button below. Thank you. +As a developer, you probably understand that "open source" doesn't mean "free work". A lot of time and resources has +been put into the project and if you'd like to tip me for Pyrogram -- or any of my `other works`_ -- you can use the +PayPal button below. Thank you! .. image:: https://i.imgur.com/fasFTzK.png :target: https://paypal.me/delivrance From 6683b18b2b3ccde857d9b82c4bed17ddf0275f8a Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Sun, 2 Jun 2019 18:57:43 +0200 Subject: [PATCH 50/50] Add FAQ about easter eggs --- docs/source/faq.rst | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/source/faq.rst b/docs/source/faq.rst index 33e7282f..a0fe3331 100644 --- a/docs/source/faq.rst +++ b/docs/source/faq.rst @@ -183,6 +183,13 @@ However, you might be right, and your account was deactivated/limited without an mistakes by either the automatic systems or a moderator. In such cases you can kindly email Telegram at recover@telegram.org, contact `@smstelegram`_ on Twitter or use `this form`_. +Are there any secret easter eggs? +--------------------------------- + +Yes. If you found one, `let me know`_! + +.. _let me know: https://t.me/pyrogram + .. _@smstelegram: https://twitter.com/smstelegram .. _this form: https://telegram.org/support