From 0e62b3472ac2bab8fa19d136649a98deb81f9102 Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Fri, 28 Dec 2018 14:08:09 +0100 Subject: [PATCH 01/10] Add get_chat_preview method and ChatPreview object --- docs/source/pyrogram/Client.rst | 1 + docs/source/pyrogram/Types.rst | 4 + pyrogram/__init__.py | 2 +- pyrogram/client/methods/chats/__init__.py | 4 +- .../client/methods/chats/get_chat_preview.py | 63 +++++++++++++++ pyrogram/client/types/__init__.py | 2 +- .../client/types/user_and_chats/__init__.py | 1 + .../types/user_and_chats/chat_preview.py | 78 +++++++++++++++++++ 8 files changed, 152 insertions(+), 3 deletions(-) create mode 100644 pyrogram/client/methods/chats/get_chat_preview.py create mode 100644 pyrogram/client/types/user_and_chats/chat_preview.py diff --git a/docs/source/pyrogram/Client.rst b/docs/source/pyrogram/Client.rst index a0177a12..179910a3 100644 --- a/docs/source/pyrogram/Client.rst +++ b/docs/source/pyrogram/Client.rst @@ -74,6 +74,7 @@ Chats join_chat leave_chat + get_chat_preview kick_chat_member unban_chat_member restrict_chat_member diff --git a/docs/source/pyrogram/Types.rst b/docs/source/pyrogram/Types.rst index 47c755f9..bf1bf937 100644 --- a/docs/source/pyrogram/Types.rst +++ b/docs/source/pyrogram/Types.rst @@ -12,6 +12,7 @@ Users & Chats User UserStatus Chat + ChatPreview ChatPhoto ChatMember ChatMembers @@ -82,6 +83,9 @@ Input Media .. autoclass:: Chat :members: +.. autoclass:: ChatPreview + :members: + .. autoclass:: ChatPhoto :members: diff --git a/pyrogram/__init__.py b/pyrogram/__init__.py index e3628fe4..47af42c7 100644 --- a/pyrogram/__init__.py +++ b/pyrogram/__init__.py @@ -32,7 +32,7 @@ from .client.types import ( Location, Message, MessageEntity, Dialog, Dialogs, Photo, PhotoSize, Sticker, User, UserStatus, UserProfilePhotos, Venue, Animation, Video, VideoNote, Voice, CallbackQuery, Messages, ForceReply, InlineKeyboardButton, InlineKeyboardMarkup, KeyboardButton, ReplyKeyboardMarkup, ReplyKeyboardRemove, - Poll, PollOption + Poll, PollOption, ChatPreview ) from .client import ( Client, ChatAction, ParseMode, Emoji, diff --git a/pyrogram/client/methods/chats/__init__.py b/pyrogram/client/methods/chats/__init__.py index f9eb25f3..3d928e87 100644 --- a/pyrogram/client/methods/chats/__init__.py +++ b/pyrogram/client/methods/chats/__init__.py @@ -22,6 +22,7 @@ from .get_chat import GetChat from .get_chat_member import GetChatMember from .get_chat_members import GetChatMembers from .get_chat_members_count import GetChatMembersCount +from .get_chat_preview import GetChatPreview from .get_dialogs import GetDialogs from .join_chat import JoinChat from .kick_chat_member import KickChatMember @@ -54,6 +55,7 @@ class Chats( PinChatMessage, UnpinChatMessage, GetDialogs, - GetChatMembersCount + GetChatMembersCount, + GetChatPreview ): pass diff --git a/pyrogram/client/methods/chats/get_chat_preview.py b/pyrogram/client/methods/chats/get_chat_preview.py new file mode 100644 index 00000000..434c385b --- /dev/null +++ b/pyrogram/client/methods/chats/get_chat_preview.py @@ -0,0 +1,63 @@ +# 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 functions, types +from ...ext import BaseClient + + +class GetChatPreview(BaseClient): + def get_chat_preview(self, + invite_link: str): + """Use this method to get the preview of a chat using the invite link. + + This method only returns a chat preview, if you want to join a chat use :meth:`join_chat` + + Args: + invite_link (``str``): + Unique identifier for the target chat in form of *t.me/joinchat/* links. + + Returns: + Either :obj:`Chat` or :obj:`ChatPreview`, depending on whether you already joined the chat or not. + + Raises: + :class:`Error ` in case of a Telegram RPC error. + ``ValueError`` in case of an invalid invite_link. + """ + match = self.INVITE_LINK_RE.match(invite_link) + + if match: + r = self.send( + functions.messages.CheckChatInvite( + hash=match.group(1) + ) + ) + + if isinstance(r, types.ChatInvite): + return pyrogram.ChatPreview._parse(self, r) + + if isinstance(r, types.ChatInviteAlready): + chat = r.chat + + if isinstance(chat, types.Chat): + return pyrogram.Chat._parse_chat_chat(self, chat) + + if isinstance(chat, types.Channel): + return pyrogram.Chat._parse_channel_chat(self, chat) + else: + raise ValueError("The invite_link is invalid") diff --git a/pyrogram/client/types/__init__.py b/pyrogram/client/types/__init__.py index 24de120f..7b30670f 100644 --- a/pyrogram/client/types/__init__.py +++ b/pyrogram/client/types/__init__.py @@ -35,5 +35,5 @@ from .messages_and_media import ( ) from .user_and_chats import ( Chat, ChatMember, ChatMembers, ChatPhoto, - Dialog, Dialogs, User, UserStatus + Dialog, Dialogs, User, UserStatus, ChatPreview ) diff --git a/pyrogram/client/types/user_and_chats/__init__.py b/pyrogram/client/types/user_and_chats/__init__.py index 0f814b92..ec082dfe 100644 --- a/pyrogram/client/types/user_and_chats/__init__.py +++ b/pyrogram/client/types/user_and_chats/__init__.py @@ -20,6 +20,7 @@ from .chat import Chat from .chat_member import ChatMember from .chat_members import ChatMembers from .chat_photo import ChatPhoto +from .chat_preview import ChatPreview from .dialog import Dialog from .dialogs import Dialogs from .user import User diff --git a/pyrogram/client/types/user_and_chats/chat_preview.py b/pyrogram/client/types/user_and_chats/chat_preview.py new file mode 100644 index 00000000..45048637 --- /dev/null +++ b/pyrogram/client/types/user_and_chats/chat_preview.py @@ -0,0 +1,78 @@ +# 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 List + +import pyrogram +from pyrogram.api import types +from .chat_photo import ChatPhoto +from ..pyrogram_type import PyrogramType +from ..user_and_chats.user import User + + +class ChatPreview(PyrogramType): + """This object represents a chat preview. + + Args: + title (``str``): + Title of the chat. + + photo (:obj:`ChatPhoto`): + Chat photo. Suitable for downloads only. + + type (``str``): + Type of chat, can be either, "group", "supergroup" or "channel". + + members_count (``int``): + Chat members count. + + members (List of :obj:`User`, *optional*): + Preview of some of the chat members. + """ + + def __init__(self, + *, + client: "pyrogram.client.ext.BaseClient", + title: str, + photo: ChatPhoto, + type: str, + members_count: int, + members: List[User] = None): + super().__init__(client) + + self.title = title + self.photo = photo + self.type = type + self.members_count = members_count + self.members = members + + @staticmethod + def _parse(client, chat_invite: types.ChatInvite) -> "ChatPreview": + return ChatPreview( + title=chat_invite.title, + photo=ChatPhoto._parse(client, chat_invite.photo), + type=("group" if not chat_invite.channel else + "channel" if chat_invite.broadcast else + "supergroup"), + members_count=chat_invite.participants_count, + members=[User._parse(client, user) for user in chat_invite.participants] or None, + client=client + ) + + # TODO: Maybe just merge this object into Chat itself by adding the "members" field. + # get_chat can be used as well instead of get_chat_preview From c907e8146a77a7e04fa74d230def9c162fb83008 Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Fri, 28 Dec 2018 14:34:47 +0100 Subject: [PATCH 02/10] Allow get_chat to work with chat invite links --- pyrogram/client/methods/chats/get_chat.py | 23 ++++++++++++++++++++++ pyrogram/client/methods/chats/join_chat.py | 2 +- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/pyrogram/client/methods/chats/get_chat.py b/pyrogram/client/methods/chats/get_chat.py index f5bf19a9..03bf2a08 100644 --- a/pyrogram/client/methods/chats/get_chat.py +++ b/pyrogram/client/methods/chats/get_chat.py @@ -32,13 +32,36 @@ class GetChat(BaseClient): Args: chat_id (``int`` | ``str``): Unique identifier (int) or username (str) of the target chat. + Unique identifier for the target chat in form of a *t.me/joinchat/* link, identifier (int) or username + of the target channel/supergroup (in the format @username). Returns: On success, a :obj:`Chat ` object is returned. Raises: :class:`Error ` in case of a Telegram RPC error. + ``ValueError`` in case the chat invite link refers to a chat you haven't joined yet. """ + match = self.INVITE_LINK_RE.match(str(chat_id)) + + if match: + h = match.group(1) + + r = self.send( + functions.messages.CheckChatInvite( + hash=h + ) + ) + + if isinstance(r, types.ChatInvite): + raise ValueError("You haven't joined \"t.me/joinchat/{}\" yet".format(h)) + + if isinstance(r.chat, types.Chat): + chat_id = -r.chat.id + + if isinstance(r.chat, types.Channel): + chat_id = int("-100" + str(r.chat.id)) + peer = self.resolve_peer(chat_id) if isinstance(peer, types.InputPeerChannel): diff --git a/pyrogram/client/methods/chats/join_chat.py b/pyrogram/client/methods/chats/join_chat.py index 2f14c617..2c70a52f 100644 --- a/pyrogram/client/methods/chats/join_chat.py +++ b/pyrogram/client/methods/chats/join_chat.py @@ -27,7 +27,7 @@ class JoinChat(BaseClient): Args: chat_id (``str``): - Unique identifier for the target chat in form of *t.me/joinchat/* links or username of the target + Unique identifier for the target chat in form of a *t.me/joinchat/* link or username of the target channel/supergroup (in the format @username). Raises: From 64ec26850e4b6b86064fbe8eb186f992d00202e4 Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Fri, 28 Dec 2018 15:16:46 +0100 Subject: [PATCH 03/10] Document save_file --- docs/source/pyrogram/Client.rst | 2 +- pyrogram/client/client.py | 51 +++++++++++++++++++++++++++++++-- 2 files changed, 49 insertions(+), 4 deletions(-) diff --git a/docs/source/pyrogram/Client.rst b/docs/source/pyrogram/Client.rst index 179910a3..5f402c65 100644 --- a/docs/source/pyrogram/Client.rst +++ b/docs/source/pyrogram/Client.rst @@ -19,7 +19,7 @@ Utilities remove_handler send resolve_peer - download_media + save_file Decorators ---------- diff --git a/pyrogram/client/client.py b/pyrogram/client/client.py index 226f783c..673fc33c 100644 --- a/pyrogram/client/client.py +++ b/pyrogram/client/client.py @@ -1116,9 +1116,9 @@ class Client(Methods, BaseClient): peer_id: Union[int, str]): """Use this method to get the InputPeer of a known peer_id. - This is a utility method intended to be used only when working with Raw Functions (i.e: a Telegram API method - you wish to use which is not available yet in the Client class as an easy-to-use method), whenever an InputPeer - type is required. + This is a utility method intended to be used **only** when working with Raw Functions (i.e: a Telegram API + method you wish to use which is not available yet in the Client class as an easy-to-use method), whenever an + InputPeer type is required. Args: peer_id (``int`` | ``str``): @@ -1191,6 +1191,51 @@ class Client(Methods, BaseClient): file_part: int = 0, progress: callable = None, progress_args: tuple = ()): + """Use this method to upload a file onto Telegram servers, without actually sending the message to anyone. + + This is a utility method intended to be used **only** when working with Raw Functions (i.e: a Telegram API + method you wish to use which is not available yet in the Client class as an easy-to-use method), whenever an + InputFile type is required. + + Args: + path (``str``): + The path of the file you want to upload that exists on your local machine. + + file_id (``int``, *optional*): + In case a file part expired, pass the file_id and the file_part to retry uploading that specific chunk. + + file_part (``int``, *optional*): + In case a file part expired, pass the file_id and the file_part to retry uploading that specific chunk. + + 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: + On success, the uploaded file is returned in form of an InputFile object. + + Raises: + :class:`Error ` in case of a Telegram RPC error. + """ part_size = 512 * 1024 file_size = os.path.getsize(path) From 74c4e35a4fd47c4ed8f79a3b3c64a9a09e00961c Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Fri, 28 Dec 2018 15:17:05 +0100 Subject: [PATCH 04/10] Move download_media into messages and media namespace --- docs/source/pyrogram/Client.rst | 1 + pyrogram/client/methods/messages/__init__.py | 4 ++- .../{utilities => messages}/download_media.py | 2 +- pyrogram/client/methods/utilities/__init__.py | 25 ------------------- 4 files changed, 5 insertions(+), 27 deletions(-) rename pyrogram/client/methods/{utilities => messages}/download_media.py (99%) delete mode 100644 pyrogram/client/methods/utilities/__init__.py diff --git a/docs/source/pyrogram/Client.rst b/docs/source/pyrogram/Client.rst index 5f402c65..d8b04c40 100644 --- a/docs/source/pyrogram/Client.rst +++ b/docs/source/pyrogram/Client.rst @@ -65,6 +65,7 @@ Messages send_poll vote_poll retract_vote + download_media Chats ----- diff --git a/pyrogram/client/methods/messages/__init__.py b/pyrogram/client/methods/messages/__init__.py index 66340283..cfb36fd0 100644 --- a/pyrogram/client/methods/messages/__init__.py +++ b/pyrogram/client/methods/messages/__init__.py @@ -17,6 +17,7 @@ # along with Pyrogram. If not, see . from .delete_messages import DeleteMessages +from .download_media import DownloadMedia from .edit_message_caption import EditMessageCaption from .edit_message_media import EditMessageMedia from .edit_message_reply_markup import EditMessageReplyMarkup @@ -68,6 +69,7 @@ class Messages( SendVoice, SendPoll, VotePoll, - RetractVote + RetractVote, + DownloadMedia ): pass diff --git a/pyrogram/client/methods/utilities/download_media.py b/pyrogram/client/methods/messages/download_media.py similarity index 99% rename from pyrogram/client/methods/utilities/download_media.py rename to pyrogram/client/methods/messages/download_media.py index 33d72f82..1cddfe98 100644 --- a/pyrogram/client/methods/utilities/download_media.py +++ b/pyrogram/client/methods/messages/download_media.py @@ -20,7 +20,7 @@ from threading import Event from typing import Union import pyrogram -from ...ext import BaseClient +from pyrogram.client.ext import BaseClient class DownloadMedia(BaseClient): diff --git a/pyrogram/client/methods/utilities/__init__.py b/pyrogram/client/methods/utilities/__init__.py deleted file mode 100644 index f8db23e5..00000000 --- a/pyrogram/client/methods/utilities/__init__.py +++ /dev/null @@ -1,25 +0,0 @@ -# Pyrogram - Telegram MTProto API Client Library for Python -# Copyright (C) 2017-2018 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 .download_media import DownloadMedia - - -class Utilities( - DownloadMedia -): - pass From 5dcc19cfb3e0509c5a02ae83df82fc327c86213c Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Fri, 28 Dec 2018 15:17:05 +0100 Subject: [PATCH 05/10] Move download_media into messages and media namespace --- docs/source/pyrogram/Client.rst | 1 + pyrogram/client/methods/__init__.py | 2 -- pyrogram/client/methods/messages/__init__.py | 4 ++- .../{utilities => messages}/download_media.py | 2 +- pyrogram/client/methods/utilities/__init__.py | 25 ------------------- 5 files changed, 5 insertions(+), 29 deletions(-) rename pyrogram/client/methods/{utilities => messages}/download_media.py (99%) delete mode 100644 pyrogram/client/methods/utilities/__init__.py diff --git a/docs/source/pyrogram/Client.rst b/docs/source/pyrogram/Client.rst index 5f402c65..d8b04c40 100644 --- a/docs/source/pyrogram/Client.rst +++ b/docs/source/pyrogram/Client.rst @@ -65,6 +65,7 @@ Messages send_poll vote_poll retract_vote + download_media Chats ----- diff --git a/pyrogram/client/methods/__init__.py b/pyrogram/client/methods/__init__.py index eba768bb..ea249e3f 100644 --- a/pyrogram/client/methods/__init__.py +++ b/pyrogram/client/methods/__init__.py @@ -23,7 +23,6 @@ from .decorators import Decorators from .messages import Messages from .password import Password from .users import Users -from .utilities import Utilities class Methods( @@ -32,7 +31,6 @@ class Methods( Password, Chats, Users, - Utilities, Messages, Decorators ): diff --git a/pyrogram/client/methods/messages/__init__.py b/pyrogram/client/methods/messages/__init__.py index 66340283..cfb36fd0 100644 --- a/pyrogram/client/methods/messages/__init__.py +++ b/pyrogram/client/methods/messages/__init__.py @@ -17,6 +17,7 @@ # along with Pyrogram. If not, see . from .delete_messages import DeleteMessages +from .download_media import DownloadMedia from .edit_message_caption import EditMessageCaption from .edit_message_media import EditMessageMedia from .edit_message_reply_markup import EditMessageReplyMarkup @@ -68,6 +69,7 @@ class Messages( SendVoice, SendPoll, VotePoll, - RetractVote + RetractVote, + DownloadMedia ): pass diff --git a/pyrogram/client/methods/utilities/download_media.py b/pyrogram/client/methods/messages/download_media.py similarity index 99% rename from pyrogram/client/methods/utilities/download_media.py rename to pyrogram/client/methods/messages/download_media.py index 33d72f82..1cddfe98 100644 --- a/pyrogram/client/methods/utilities/download_media.py +++ b/pyrogram/client/methods/messages/download_media.py @@ -20,7 +20,7 @@ from threading import Event from typing import Union import pyrogram -from ...ext import BaseClient +from pyrogram.client.ext import BaseClient class DownloadMedia(BaseClient): diff --git a/pyrogram/client/methods/utilities/__init__.py b/pyrogram/client/methods/utilities/__init__.py deleted file mode 100644 index f8db23e5..00000000 --- a/pyrogram/client/methods/utilities/__init__.py +++ /dev/null @@ -1,25 +0,0 @@ -# Pyrogram - Telegram MTProto API Client Library for Python -# Copyright (C) 2017-2018 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 .download_media import DownloadMedia - - -class Utilities( - DownloadMedia -): - pass From 8f38ce3b9ea61b5d26be9965df209ee8a2f8ab5e Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Fri, 28 Dec 2018 16:19:30 +0100 Subject: [PATCH 06/10] Remove Raw Functions from Usage doc page --- docs/source/start/Usage.rst | 80 ++----------------------------------- 1 file changed, 4 insertions(+), 76 deletions(-) diff --git a/docs/source/start/Usage.rst b/docs/source/start/Usage.rst index 6c1697b9..8bb197ab 100644 --- a/docs/source/start/Usage.rst +++ b/docs/source/start/Usage.rst @@ -1,8 +1,7 @@ Usage ===== -Having your `project set up`_ and your account authorized_, it's time to play with the API. -In this section, you'll be shown two ways of communicating with Telegram using Pyrogram. Let's start! +Having your `project set up`_ and your account authorized_, it's time to play with the API. Let's start! High-level API -------------- @@ -43,79 +42,8 @@ exceptions in your code: More examples on `GitHub `_. -Raw Functions -------------- - -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 ` exposed by the -``pyrogram.api`` package and call any Telegram API method you wish using the :meth:`send() ` -method provided by the Client class. - -.. hint:: - - Every high-level method mentioned in the section above 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. - - If you think a raw function should be wrapped and added as a high-level method, feel free to ask in our Community_! - -Examples (more on `GitHub `_): - -- Update first name, last name and bio: - - .. code-block:: python - - from pyrogram import Client - from pyrogram.api import functions - - with Client("my_account") as app: - app.send( - functions.account.UpdateProfile( - first_name="Dan", last_name="Tès", - about="Bio written from Pyrogram" - ) - ) - -- Share your Last Seen time only with your contacts: - - .. code-block:: python - - from pyrogram import Client - from pyrogram.api import functions, types - - with Client("my_account") as app: - app.send( - functions.account.SetPrivacy( - key=types.InputPrivacyKeyStatusTimestamp(), - rules=[types.InputPrivacyValueAllowContacts()] - ) - ) - -- Invite users to your channel/supergroup: - - .. code-block:: python - - from pyrogram import Client - from pyrogram.api import functions, types - - with Client("my_account") as app: - app.send( - functions.channels.InviteToChannel( - channel=app.resolve_peer(123456789), # ID or Username - users=[ # The users you want to invite - app.resolve_peer(23456789), # By ID - app.resolve_peer("username"), # By username - app.resolve_peer("393281234567"), # By phone number - ] - ) - ) - -.. _methods: ../pyrogram/Client.html#messages -.. _plenty of them: ../pyrogram/Client.html#messages -.. _types: ../pyrogram/Types.html -.. _Raw Functions: Usage.html#using-raw-functions -.. _Community: https://t.me/PyrogramChat .. _project set up: Setup.html .. _authorized: Setup.html#user-authorization -.. _Telegram Bot API: https://core.telegram.org/bots/api \ No newline at end of file +.. _Telegram Bot API: https://core.telegram.org/bots/api +.. _methods: ../pyrogram/Client.html#messages +.. _types: ../pyrogram/Types.html \ No newline at end of file From 46aeb569d5e82eb51c567bbbcea1f8cb409db5f4 Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Fri, 28 Dec 2018 16:19:42 +0100 Subject: [PATCH 07/10] Add AdvancedUsage.rst --- docs/source/index.rst | 1 + docs/source/resources/AdvancedUsage.rst | 121 ++++++++++++++++++++++++ 2 files changed, 122 insertions(+) create mode 100644 docs/source/resources/AdvancedUsage.rst diff --git a/docs/source/index.rst b/docs/source/index.rst index 8234374c..085b38fb 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -93,6 +93,7 @@ To get started, press the Next button. resources/BotsInteraction resources/ErrorHandling resources/TestServers + resources/AdvancedUsage resources/Changelog .. toctree:: diff --git a/docs/source/resources/AdvancedUsage.rst b/docs/source/resources/AdvancedUsage.rst new file mode 100644 index 00000000..02395f26 --- /dev/null +++ b/docs/source/resources/AdvancedUsage.rst @@ -0,0 +1,121 @@ +Advanced Usage +============== + +In this section, you'll be shown the alternative way of communicating with Telegram using Pyrogram: the main Telegram +API with its raw functions and types. + +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 ` +exposed by the ``pyrogram.api`` package and call any Telegram API method you wish using the +:meth:`send() ` method provided by the Client class. + +.. hint:: + + Every available high-level method mentioned in the previous page 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. + + If you think a raw function should be wrapped and added as a high-level method, feel free to ask in our Community_! + +Caveats +------- + +As hinted before, raw functions and types can be confusing, mainly because people don't realize they must accept +*exactly* the right values, but also because most of them don't have enough Python experience to fully grasp how things +work. + +This section will therefore explain some pitfalls to take into consideration when working with the raw API. + +Chat IDs +^^^^^^^^ + +The way Telegram works makes it impossible to directly send a message to a user or a chat by using their IDs only. +Instead, a pair of ``id`` and ``access_hash`` wrapped in a so called ``InputPeer`` is always needed. + +There are three different InputPeer types, one for each kind of Telegram entity. +Whenever an InputPeer is needed you must pass one of these: + + - `InputPeerUser `_ - Users + - `InputPeerChat `_ - Basic Chats + - `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 +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 +all positive within their respective raw types. + +Things are different when working with Pyrogram's API because having them in the same space can theoretically lead to +collisions, and that's why Pyrogram (as well as the official Bot API) uses a slightly different representation for each +kind of ID. + +For example, given the ID *123456789*, here's how Pyrogram can tell entities apart: + + - ``+ID`` - User: *123456789* + - ``-ID`` - Chat: *-123456789* + - ``-100ID`` - Channel (and Supergroup): *-100123456789* + +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. + +Examples +-------- + +- Update first name, last name and bio: + + .. code-block:: python + + from pyrogram import Client + from pyrogram.api import functions + + with Client("my_account") as app: + app.send( + functions.account.UpdateProfile( + first_name="Dan", last_name="Tès", + about="Bio written from Pyrogram" + ) + ) + +- Share your Last Seen time only with your contacts: + + .. code-block:: python + + from pyrogram import Client + from pyrogram.api import functions, types + + with Client("my_account") as app: + app.send( + functions.account.SetPrivacy( + key=types.InputPrivacyKeyStatusTimestamp(), + rules=[types.InputPrivacyValueAllowContacts()] + ) + ) + +- Invite users to your channel/supergroup: + + .. code-block:: python + + from pyrogram import Client + from pyrogram.api import functions, types + + with Client("my_account") as app: + app.send( + functions.channels.InviteToChannel( + channel=app.resolve_peer(123456789), # ID or Username + users=[ # The users you want to invite + app.resolve_peer(23456789), # By ID + app.resolve_peer("username"), # By username + app.resolve_peer("393281234567"), # By phone number + ] + ) + ) + + +.. _plenty of them: ../pyrogram/Client.html#messages +.. _Raw Functions: Usage.html#using-raw-functions +.. _Community: https://t.me/PyrogramChat \ No newline at end of file From d00fde74de9908a295c1457bf4606b2bb8f864d5 Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Sat, 29 Dec 2018 13:37:13 +0100 Subject: [PATCH 08/10] Use clearer error pages' titles --- docs/source/errors/BadRequest.rst | 4 ++-- docs/source/errors/Flood.rst | 4 ++-- docs/source/errors/Forbidden.rst | 4 ++-- docs/source/errors/InternalServerError.rst | 4 ++-- docs/source/errors/NotAcceptable.rst | 4 ++-- docs/source/errors/SeeOther.rst | 4 ++-- docs/source/errors/Unauthorized.rst | 4 ++-- docs/source/errors/UnknownError.rst | 4 ++-- docs/source/resources/ErrorHandling.rst | 14 +++++++------- 9 files changed, 23 insertions(+), 23 deletions(-) diff --git a/docs/source/errors/BadRequest.rst b/docs/source/errors/BadRequest.rst index 7ea6cb4b..c51a7d54 100644 --- a/docs/source/errors/BadRequest.rst +++ b/docs/source/errors/BadRequest.rst @@ -1,5 +1,5 @@ -Bad Request -=========== +400 - Bad Request +================= .. module:: pyrogram.api.errors.BadRequest diff --git a/docs/source/errors/Flood.rst b/docs/source/errors/Flood.rst index a83a216c..72f819ea 100644 --- a/docs/source/errors/Flood.rst +++ b/docs/source/errors/Flood.rst @@ -1,5 +1,5 @@ -Flood -===== +420 - Flood +=========== .. module:: pyrogram.api.errors.Flood diff --git a/docs/source/errors/Forbidden.rst b/docs/source/errors/Forbidden.rst index fd2e08ce..aaaceaff 100644 --- a/docs/source/errors/Forbidden.rst +++ b/docs/source/errors/Forbidden.rst @@ -1,5 +1,5 @@ -Forbidden -========= +403 - Forbidden +=============== .. module:: pyrogram.api.errors.Forbidden diff --git a/docs/source/errors/InternalServerError.rst b/docs/source/errors/InternalServerError.rst index 310c5cfc..5e506fc9 100644 --- a/docs/source/errors/InternalServerError.rst +++ b/docs/source/errors/InternalServerError.rst @@ -1,5 +1,5 @@ -Internal Server Error -===================== +500 - Internal Server Error +=========================== .. module:: pyrogram.api.errors.InternalServerError diff --git a/docs/source/errors/NotAcceptable.rst b/docs/source/errors/NotAcceptable.rst index 66ebaf72..e9301396 100644 --- a/docs/source/errors/NotAcceptable.rst +++ b/docs/source/errors/NotAcceptable.rst @@ -1,5 +1,5 @@ -Not Acceptable -============== +406 - Not Acceptable +==================== .. module:: pyrogram.api.errors.NotAcceptable diff --git a/docs/source/errors/SeeOther.rst b/docs/source/errors/SeeOther.rst index 49411379..a916e779 100644 --- a/docs/source/errors/SeeOther.rst +++ b/docs/source/errors/SeeOther.rst @@ -1,5 +1,5 @@ -See Other -========= +303 - See Other +=============== .. module:: pyrogram.api.errors.SeeOther diff --git a/docs/source/errors/Unauthorized.rst b/docs/source/errors/Unauthorized.rst index b3926132..6de3ff67 100644 --- a/docs/source/errors/Unauthorized.rst +++ b/docs/source/errors/Unauthorized.rst @@ -1,5 +1,5 @@ -Unauthorized -============ +401 - Unauthorized +================== .. module:: pyrogram.api.errors.Unauthorized diff --git a/docs/source/errors/UnknownError.rst b/docs/source/errors/UnknownError.rst index 030f3e02..767f19c3 100644 --- a/docs/source/errors/UnknownError.rst +++ b/docs/source/errors/UnknownError.rst @@ -1,5 +1,5 @@ -Unknown Error -============= +520 - Unknown Error +=================== .. module:: pyrogram.api.errors.UnknownError diff --git a/docs/source/resources/ErrorHandling.rst b/docs/source/resources/ErrorHandling.rst index f2a77b7a..1f08c165 100644 --- a/docs/source/resources/ErrorHandling.rst +++ b/docs/source/resources/ErrorHandling.rst @@ -6,13 +6,13 @@ Errors are inevitable when working with the API, and they must be correctly hand There are many errors that Telegram could return, but they all fall in one of these categories (which are in turn children of the :obj:`pyrogram.Error` superclass) -- :obj:`303 See Other ` -- :obj:`400 Bad Request ` -- :obj:`401 Unauthorized ` -- :obj:`403 Forbidden ` -- :obj:`406 Not Acceptable ` -- :obj:`420 Flood ` -- :obj:`500 Internal Server Error ` +- :obj:`303 - See Other ` +- :obj:`400 - Bad Request ` +- :obj:`401 - Unauthorized ` +- :obj:`403 - Forbidden ` +- :obj:`406 - Not Acceptable ` +- :obj:`420 - Flood ` +- :obj:`500 - Internal Server Error ` As stated above, there are really many (too many) errors, and in case Pyrogram does not know anything yet about a specific one, it raises a special :obj:`520 Unknown Error ` exception and logs it From a02846e90066053bd7dec6e563c26dbf0a60a475 Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Sun, 30 Dec 2018 07:53:14 +0100 Subject: [PATCH 09/10] Move get_chat_preview in a better place --- docs/source/pyrogram/Client.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/pyrogram/Client.rst b/docs/source/pyrogram/Client.rst index d8b04c40..14796ef2 100644 --- a/docs/source/pyrogram/Client.rst +++ b/docs/source/pyrogram/Client.rst @@ -75,7 +75,6 @@ Chats join_chat leave_chat - get_chat_preview kick_chat_member unban_chat_member restrict_chat_member @@ -88,6 +87,7 @@ Chats pin_chat_message unpin_chat_message get_chat + get_chat_preview get_chat_member get_chat_members get_chat_members_count From 490b8bf5791ef889a8b5886e0de4a56e98e89312 Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Mon, 31 Dec 2018 12:02:15 +0100 Subject: [PATCH 10/10] Fix get_message getting infinite replies --- pyrogram/client/methods/messages/get_messages.py | 2 +- pyrogram/client/types/messages_and_media/messages.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pyrogram/client/methods/messages/get_messages.py b/pyrogram/client/methods/messages/get_messages.py index da2f6578..d0c064f9 100644 --- a/pyrogram/client/methods/messages/get_messages.py +++ b/pyrogram/client/methods/messages/get_messages.py @@ -78,6 +78,6 @@ class GetMessages(BaseClient): else: rpc = functions.messages.GetMessages(id=ids) - messages = pyrogram.Messages._parse(self, self.send(rpc)) + messages = pyrogram.Messages._parse(self, self.send(rpc), replies) return messages if is_iterable else messages.messages[0] diff --git a/pyrogram/client/types/messages_and_media/messages.py b/pyrogram/client/types/messages_and_media/messages.py index cd401c1b..51d3fbdf 100644 --- a/pyrogram/client/types/messages_and_media/messages.py +++ b/pyrogram/client/types/messages_and_media/messages.py @@ -47,13 +47,13 @@ class Messages(PyrogramType): self.messages = messages @staticmethod - def _parse(client, messages: types.messages.Messages) -> "Messages": + def _parse(client, messages: types.messages.Messages, replies: int = 1) -> "Messages": users = {i.id: i for i in messages.users} chats = {i.id: i for i in messages.chats} return Messages( total_count=getattr(messages, "count", len(messages.messages)), - messages=[Message._parse(client, message, users, chats) for message in messages.messages], + messages=[Message._parse(client, message, users, chats, replies) for message in messages.messages], client=client )