diff --git a/compiler/api/compiler.py b/compiler/api/compiler.py
index aa5714ec..3b6dbae7 100644
--- a/compiler/api/compiler.py
+++ b/compiler/api/compiler.py
@@ -506,6 +506,7 @@ def start():
f.write("\n 0xb0700027: \"pyrogram.client.types.Photo\",")
f.write("\n 0xb0700028: \"pyrogram.client.types.Dialog\",")
f.write("\n 0xb0700029: \"pyrogram.client.types.Dialogs\",")
+ f.write("\n 0xb0700030: \"pyrogram.client.types.ChatMembers\",")
f.write("\n}\n")
diff --git a/compiler/error/source/400_BAD_REQUEST.tsv b/compiler/error/source/400_BAD_REQUEST.tsv
index cd196077..e00c10c5 100644
--- a/compiler/error/source/400_BAD_REQUEST.tsv
+++ b/compiler/error/source/400_BAD_REQUEST.tsv
@@ -62,4 +62,7 @@ USER_IS_BOT A bot cannot send messages to other bots or to itself
WEBPAGE_CURL_FAILED Telegram could not fetch the provided URL
STICKERSET_INVALID The requested sticker set is invalid
PEER_FLOOD The method can't be used because your account is limited
-MEDIA_CAPTION_TOO_LONG The media caption is longer than 200 characters
\ No newline at end of file
+MEDIA_CAPTION_TOO_LONG The media caption is longer than 200 characters
+USER_NOT_MUTUAL_CONTACT The user is not a mutual contact
+USER_CHANNELS_TOO_MUCH The user is already in too many channels or supergroups
+API_ID_PUBLISHED_FLOOD You are using an API key that is limited on the server side
\ No newline at end of file
diff --git a/compiler/error/source/500_INTERNAL_SERVER_ERROR.tsv b/compiler/error/source/500_INTERNAL_SERVER_ERROR.tsv
index abb58495..60d1b51a 100644
--- a/compiler/error/source/500_INTERNAL_SERVER_ERROR.tsv
+++ b/compiler/error/source/500_INTERNAL_SERVER_ERROR.tsv
@@ -3,4 +3,5 @@ AUTH_RESTART User authorization has restarted
RPC_CALL_FAIL Telegram is having internal problems. Please try again later
RPC_MCGET_FAIL Telegram is having internal problems. Please try again later
PERSISTENT_TIMESTAMP_OUTDATED Telegram is having internal problems. Please try again later
-HISTORY_GET_FAILED Telegram is having internal problems. Please try again later
\ No newline at end of file
+HISTORY_GET_FAILED Telegram is having internal problems. Please try again later
+REG_ID_GENERATE_FAILED Telegram is having internal problems. Please try again later
\ No newline at end of file
diff --git a/docs/source/pyrogram/Client.rst b/docs/source/pyrogram/Client.rst
index 2fbd5879..bf9ac2ca 100644
--- a/docs/source/pyrogram/Client.rst
+++ b/docs/source/pyrogram/Client.rst
@@ -67,4 +67,10 @@ Client
get_users
get_chat
get_messages
- get_history
\ No newline at end of file
+ get_history
+ set_chat_photo
+ delete_chat_photo
+ set_chat_title
+ set_chat_description
+ pin_chat_message
+ unpin_chat_message
\ No newline at end of file
diff --git a/pyrogram/__init__.py b/pyrogram/__init__.py
index 764afb4e..3d220237 100644
--- a/pyrogram/__init__.py
+++ b/pyrogram/__init__.py
@@ -35,14 +35,12 @@ __version__ = "0.8.0dev1"
from .api.errors import Error
from .client.types import (
- Audio, Chat, ChatMember, ChatPhoto, Contact, Document, InputMediaPhoto,
+ Audio, Chat, ChatMember, ChatMembers, ChatPhoto, Contact, Document, InputMediaPhoto,
InputMediaVideo, InputPhoneContact, Location, Message, MessageEntity,
Dialog, Dialogs, Photo, PhotoSize, Sticker, Update, User, UserProfilePhotos,
- Venue, GIF, Video, VideoNote, Voice, CallbackQuery, Messages
-)
-from .client.types.reply_markup import (
- ForceReply, InlineKeyboardButton, InlineKeyboardMarkup,
- KeyboardButton, ReplyKeyboardMarkup, ReplyKeyboardRemove
+ Venue, GIF, Video, VideoNote, Voice, CallbackQuery, Messages, ForceReply,
+ InlineKeyboardButton, InlineKeyboardMarkup, KeyboardButton, ReplyKeyboardMarkup,
+ ReplyKeyboardRemove
)
from .client import (
Client, ChatAction, ParseMode, Emoji,
diff --git a/pyrogram/client/client.py b/pyrogram/client/client.py
index 833b9d2e..a53c1784 100644
--- a/pyrogram/client/client.py
+++ b/pyrogram/client/client.py
@@ -1259,8 +1259,6 @@ class Client(Methods, BaseClient):
break
f.write(chunk)
- f.flush()
- os.fsync(f.fileno())
offset += limit
@@ -1343,8 +1341,6 @@ class Client(Methods, BaseClient):
assert h.hash == sha256(cdn_chunk).digest(), "Invalid CDN hash part {}".format(i)
f.write(decrypted_chunk)
- f.flush()
- os.fsync(f.fileno())
offset += limit
diff --git a/pyrogram/client/ext/utils.py b/pyrogram/client/ext/utils.py
index f300136f..c4b84528 100644
--- a/pyrogram/client/ext/utils.py
+++ b/pyrogram/client/ext/utils.py
@@ -72,6 +72,7 @@ async def ainput(prompt: str = ""):
ENTITIES = {
types.MessageEntityMention.ID: "mention",
types.MessageEntityHashtag.ID: "hashtag",
+ types.MessageEntityCashtag.ID: "cashtag",
types.MessageEntityBotCommand.ID: "bot_command",
types.MessageEntityUrl.ID: "url",
types.MessageEntityEmail.ID: "email",
@@ -140,6 +141,10 @@ def parse_chat_photo(photo):
def parse_user(user: types.User) -> pyrogram_types.User or None:
return pyrogram_types.User(
id=user.id,
+ is_self=user.is_self,
+ is_contact=user.contact,
+ is_mutual_contact=user.mutual_contact,
+ is_deleted=user.deleted,
is_bot=user.bot,
first_name=user.first_name,
last_name=user.last_name,
@@ -371,6 +376,7 @@ async def parse_messages(
phone_number=media.phone_number,
first_name=media.first_name,
last_name=media.last_name or None,
+ vcard=media.vcard or None,
user_id=media.user_id or None
)
elif isinstance(media, types.MessageMediaVenue):
@@ -412,8 +418,7 @@ async def parse_messages(
duration=audio_attributes.duration,
mime_type=doc.mime_type,
file_size=doc.size,
- thumb=parse_thumb(doc.thumb),
- file_name=file_name,
+ waveform=audio_attributes.waveform,
date=doc.date
)
else:
@@ -476,7 +481,6 @@ async def parse_messages(
duration=video_attributes.duration,
thumb=parse_thumb(doc.thumb),
file_size=doc.size,
- file_name=file_name,
mime_type=doc.mime_type,
date=doc.date
)
@@ -938,3 +942,103 @@ def parse_dialog_chat(peer, users: dict, chats: dict):
return parse_chat_chat(chats[peer.chat_id])
else:
return parse_channel_chat(chats[peer.channel_id])
+
+
+def parse_chat_members(members: types.channels.ChannelParticipants or types.messages.ChatFull):
+ users = {i.id: i for i in members.users}
+ parsed_members = []
+
+ if isinstance(members, types.channels.ChannelParticipants):
+ members = members.participants
+
+ for member in members:
+ user = parse_user(users[member.user_id])
+
+ if isinstance(member, (types.ChannelParticipant, types.ChannelParticipantSelf)):
+ parsed_members.append(
+ pyrogram_types.ChatMember(
+ user=user,
+ status="member"
+ )
+ )
+ elif isinstance(member, types.ChannelParticipantCreator):
+ parsed_members.append(
+ pyrogram_types.ChatMember(
+ user=user,
+ status="creator"
+ )
+ )
+ elif isinstance(member, types.ChannelParticipantAdmin):
+ rights = member.admin_rights # type: types.ChannelAdminRights
+
+ parsed_members.append(
+ pyrogram_types.ChatMember(
+ user=user,
+ status="administrator",
+ can_be_edited=member.can_edit,
+ can_change_info=rights.change_info,
+ can_post_messages=rights.post_messages,
+ can_edit_messages=rights.edit_messages,
+ can_delete_messages=rights.delete_messages,
+ can_invite_users=rights.invite_users or rights.invite_link,
+ can_restrict_members=rights.ban_users,
+ can_pin_messages=rights.pin_messages,
+ can_promote_members=rights.add_admins
+ )
+ )
+ elif isinstance(member, types.ChannelParticipantBanned):
+ rights = member.banned_rights # type: types.ChannelBannedRights
+
+ chat_member = pyrogram_types.ChatMember(
+ user=user,
+ status="kicked" if rights.view_messages else "restricted",
+ until_date=0 if rights.until_date == (1 << 31) - 1 else rights.until_date
+ )
+
+ if chat_member.status == "restricted":
+ chat_member.can_send_messages = not rights.send_messages
+ chat_member.can_send_media_messages = not rights.send_media
+ chat_member.can_send_other_messages = (
+ not rights.send_stickers or not rights.send_gifs or
+ not rights.send_games or not rights.send_inline
+ )
+ chat_member.can_add_web_page_previews = not rights.embed_links
+
+ parsed_members.append(chat_member)
+
+ return pyrogram_types.ChatMembers(
+ total_count=members.count,
+ chat_members=parsed_members
+ )
+ else:
+ members = members.full_chat.participants.participants
+
+ for member in members:
+ user = parse_user(users[member.user_id])
+
+ if isinstance(member, types.ChatParticipant):
+ parsed_members.append(
+ pyrogram_types.ChatMember(
+ user=user,
+ status="member"
+ )
+ )
+ elif isinstance(member, types.ChatParticipantCreator):
+ parsed_members.append(
+ pyrogram_types.ChatMember(
+ user=user,
+ status="creator"
+ )
+ )
+ elif isinstance(member, types.ChatParticipantAdmin):
+ parsed_members.append(
+ pyrogram_types.ChatMember(
+ user=user,
+ status="administrator"
+ )
+ )
+
+ return pyrogram_types.ChatMembers(
+ total_count=len(members),
+ chat_members=parsed_members
+ )
diff --git a/pyrogram/client/methods/chats/__init__.py b/pyrogram/client/methods/chats/__init__.py
index 9c887ef5..038440f6 100644
--- a/pyrogram/client/methods/chats/__init__.py
+++ b/pyrogram/client/methods/chats/__init__.py
@@ -16,14 +16,21 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
+from .delete_chat_photo import DeleteChatPhoto
from .export_chat_invite_link import ExportChatInviteLink
from .get_chat import GetChat
+from .get_chat_members import GetChatMembers
from .join_chat import JoinChat
from .kick_chat_member import KickChatMember
from .leave_chat import LeaveChat
+from .pin_chat_message import PinChatMessage
from .promote_chat_member import PromoteChatMember
from .restrict_chat_member import RestrictChatMember
+from .set_chat_description import SetChatDescription
+from .set_chat_photo import SetChatPhoto
+from .set_chat_title import SetChatTitle
from .unban_chat_member import UnbanChatMember
+from .unpin_chat_message import UnpinChatMessage
class Chats(
@@ -34,6 +41,13 @@ class Chats(
KickChatMember,
UnbanChatMember,
RestrictChatMember,
- PromoteChatMember
+ PromoteChatMember,
+ GetChatMembers,
+ SetChatPhoto,
+ DeleteChatPhoto,
+ SetChatTitle,
+ SetChatDescription,
+ PinChatMessage,
+ UnpinChatMessage
):
pass
diff --git a/pyrogram/client/methods/chats/delete_chat_photo.py b/pyrogram/client/methods/chats/delete_chat_photo.py
new file mode 100644
index 00000000..57d90b11
--- /dev/null
+++ b/pyrogram/client/methods/chats/delete_chat_photo.py
@@ -0,0 +1,64 @@
+# 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 pyrogram.api import functions, types
+from ...ext import BaseClient
+
+
+class DeleteChatPhoto(BaseClient):
+ def delete_chat_photo(self, chat_id: int or str):
+ """Use this method to delete a chat photo.
+ Photos can't be changed for private chats.
+ You must be an administrator in the chat for this to work and must have the appropriate admin rights.
+
+ Note:
+ In regular groups (non-supergroups), this method will only work if the "All Members Are Admins"
+ setting is off.
+
+ Args:
+ chat_id (``int`` | ``str``):
+ Unique identifier (int) or username (str) of the target chat.
+ For a private channel/supergroup you can use its *t.me/joinchat/* link.
+
+ Returns:
+ True on success.
+
+ Raises:
+ :class:`Error `
+ ``ValueError``: If a chat_id belongs to user.
+ """
+ peer = self.resolve_peer(chat_id)
+
+ if isinstance(peer, types.InputPeerChat):
+ self.send(
+ functions.messages.EditChatPhoto(
+ chat_id=peer.chat_id,
+ photo=types.InputChatPhotoEmpty()
+ )
+ )
+ elif isinstance(peer, types.InputPeerChannel):
+ self.send(
+ functions.channels.EditPhoto(
+ channel=peer,
+ photo=types.InputChatPhotoEmpty()
+ )
+ )
+ else:
+ raise ValueError("The chat_id \"{}\" belongs to a user".format(chat_id))
+
+ return True
diff --git a/pyrogram/client/methods/chats/get_chat.py b/pyrogram/client/methods/chats/get_chat.py
index 9b5a5fe8..050b8118 100644
--- a/pyrogram/client/methods/chats/get_chat.py
+++ b/pyrogram/client/methods/chats/get_chat.py
@@ -25,6 +25,11 @@ class GetChat(BaseClient):
"""Use this method to get up to date information about the chat (current name of the user for
one-on-one conversations, current username of a user, group or channel, etc.)
+ Args:
+ chat_id (``int`` | ``str``):
+ Unique identifier (int) or username (str) of the target chat.
+ For a private channel/supergroup you can use its *t.me/joinchat/* link.
+
Returns:
On success, a :obj:`Chat ` object is returned.
diff --git a/pyrogram/client/methods/chats/get_chat_members.py b/pyrogram/client/methods/chats/get_chat_members.py
new file mode 100644
index 00000000..a851ef58
--- /dev/null
+++ b/pyrogram/client/methods/chats/get_chat_members.py
@@ -0,0 +1,79 @@
+# 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 pyrogram.api import functions, types
+from ...ext import BaseClient, utils
+
+
+class Filters:
+ ALL = "all"
+ KICKED = "kicked"
+ RESTRICTED = "restricted"
+ BOTS = "bots"
+ RECENT = "recent"
+ ADMINISTRATORS = "administrators"
+
+
+class GetChatMembers(BaseClient):
+ def get_chat_members(self,
+ chat_id: int or str,
+ offset: int = 0,
+ limit: int = 200,
+ query: str = "",
+ filter: str = Filters.ALL):
+ peer = self.resolve_peer(chat_id)
+
+ if isinstance(peer, types.InputPeerChat):
+ return utils.parse_chat_members(
+ self.send(
+ functions.messages.GetFullChat(
+ peer.chat_id
+ )
+ )
+ )
+ elif isinstance(peer, types.InputPeerChannel):
+ filter = filter.lower()
+
+ if filter == Filters.ALL:
+ filter = types.ChannelParticipantsSearch(q=query)
+ elif filter == Filters.KICKED:
+ filter = types.ChannelParticipantsKicked(q=query)
+ elif filter == Filters.RESTRICTED:
+ filter = types.ChannelParticipantsBanned(q=query)
+ elif filter == Filters.BOTS:
+ filter = types.ChannelParticipantsBots()
+ elif filter == Filters.RECENT:
+ filter = types.ChannelParticipantsRecent()
+ elif filter == Filters.ADMINISTRATORS:
+ filter = types.ChannelParticipantsAdmins()
+ else:
+ raise ValueError("Invalid filter \"{}\"".format(filter))
+
+ return utils.parse_chat_members(
+ self.send(
+ functions.channels.GetParticipants(
+ channel=peer,
+ filter=filter,
+ offset=offset,
+ limit=limit,
+ hash=0
+ )
+ )
+ )
+ else:
+ raise ValueError("The chat_id \"{}\" belongs to a user".format(chat_id))
diff --git a/pyrogram/client/methods/chats/pin_chat_message.py b/pyrogram/client/methods/chats/pin_chat_message.py
new file mode 100644
index 00000000..e9bc533e
--- /dev/null
+++ b/pyrogram/client/methods/chats/pin_chat_message.py
@@ -0,0 +1,63 @@
+# 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 pyrogram.api import functions, types
+from ...ext import BaseClient
+
+
+class PinChatMessage(BaseClient):
+ def pin_chat_message(self, chat_id: int or str, message_id: int, disable_notification: bool = None):
+ """Use this method to pin a message in a supergroup or a channel.
+ You must be an administrator in the chat for this to work and must have the "can_pin_messages" admin right in
+ the supergroup or "can_edit_messages" admin right in the channel.
+
+ Args:
+ chat_id (``int`` | ``str``):
+ Unique identifier (int) or username (str) of the target chat.
+ For a private channel/supergroup you can use its *t.me/joinchat/* link.
+
+ message_id (``int``):
+ Identifier of a message to pin.
+
+ disable_notification (``bool``):
+ Pass True, if it is not necessary to send a notification to all chat members about the new pinned
+ message. Notifications are always disabled in channels.
+
+ Returns:
+ True on success.
+
+ Raises:
+ :class:`Error `
+ ``ValueError``: If a chat_id doesn't belong to a supergroup or a channel.
+ """
+ peer = self.resolve_peer(chat_id)
+
+ if isinstance(peer, types.InputPeerChannel):
+ self.send(
+ functions.channels.UpdatePinnedMessage(
+ channel=peer,
+ id=message_id,
+ silent=disable_notification or None
+ )
+ )
+ elif isinstance(peer, types.InputPeerChat):
+ raise ValueError("The chat_id \"{}\" belongs to a basic group".format(chat_id))
+ else:
+ raise ValueError("The chat_id \"{}\" belongs to a user".format(chat_id))
+
+ return True
diff --git a/pyrogram/client/methods/chats/set_chat_description.py b/pyrogram/client/methods/chats/set_chat_description.py
new file mode 100644
index 00000000..c9597a62
--- /dev/null
+++ b/pyrogram/client/methods/chats/set_chat_description.py
@@ -0,0 +1,57 @@
+# 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 pyrogram.api import functions, types
+from ...ext import BaseClient
+
+
+class SetChatDescription(BaseClient):
+ def set_chat_description(self, chat_id: int or str, description: str):
+ """Use this method to change the description of a supergroup or a channel.
+ You must be an administrator in the chat for this to work and must have the appropriate admin rights.
+
+ Args:
+ chat_id (``int`` | ``str``):
+ Unique identifier (int) or username (str) of the target chat.
+ For a private channel/supergroup you can use its *t.me/joinchat/* link.
+
+ description (``str``):
+ New chat description, 0-255 characters.
+
+ Returns:
+ True on success.
+
+ Raises:
+ :class:`Error `
+ ``ValueError``: If a chat_id doesn't belong to a supergroup or a channel.
+ """
+ peer = self.resolve_peer(chat_id)
+
+ if isinstance(peer, types.InputPeerChannel):
+ self.send(
+ functions.channels.EditAbout(
+ channel=peer,
+ about=description
+ )
+ )
+ elif isinstance(peer, types.InputPeerChat):
+ raise ValueError("The chat_id \"{}\" belongs to a basic group".format(chat_id))
+ else:
+ raise ValueError("The chat_id \"{}\" belongs to a user".format(chat_id))
+
+ return True
diff --git a/pyrogram/client/methods/chats/set_chat_photo.py b/pyrogram/client/methods/chats/set_chat_photo.py
new file mode 100644
index 00000000..d98fefde
--- /dev/null
+++ b/pyrogram/client/methods/chats/set_chat_photo.py
@@ -0,0 +1,83 @@
+# 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 .
+
+import os
+from base64 import b64decode
+from struct import unpack
+
+from pyrogram.api import functions, types
+from ...ext import BaseClient
+
+
+class SetChatPhoto(BaseClient):
+ def set_chat_photo(self, chat_id: int or str, photo: str):
+ """Use this method to set a new profile photo for the chat.
+ Photos can't be changed for private chats.
+ You must be an administrator in the chat for this to work and must have the appropriate admin rights.
+
+ Note:
+ In regular groups (non-supergroups), this method will only work if the "All Members Are Admins"
+ setting is off.
+
+ Args:
+ chat_id (``int`` | ``str``):
+ Unique identifier (int) or username (str) of the target chat.
+ For a private channel/supergroup you can use its *t.me/joinchat/* link.
+
+ photo (``str``):
+ New chat photo. You can pass a :class:`Photo` id or a file path to upload a new photo.
+
+ Returns:
+ True on success.
+
+ Raises:
+ :class:`Error `
+ ``ValueError``: If a chat_id belongs to user.
+ """
+ peer = self.resolve_peer(chat_id)
+
+ if os.path.exists(photo):
+ photo = types.InputChatUploadedPhoto(file=self.save_file(photo))
+ else:
+ s = unpack("
+#
+# 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.api import functions, types
+from ...ext import BaseClient
+
+
+class SetChatTitle(BaseClient):
+ def set_chat_title(self, chat_id: int or str, title: str):
+ """Use this method to change the title of a chat.
+ Titles can't be changed for private chats.
+ You must be an administrator in the chat for this to work and must have the appropriate admin rights.
+
+ Note:
+ In regular groups (non-supergroups), this method will only work if the "All Members Are Admins"
+ setting is off.
+
+ Args:
+ chat_id (``int`` | ``str``):
+ Unique identifier (int) or username (str) of the target chat.
+ For a private channel/supergroup you can use its *t.me/joinchat/* link.
+
+ title (``str``):
+ New chat title, 1-255 characters.
+
+ Returns:
+ True on success.
+
+ Raises:
+ :class:`Error `
+ ``ValueError``: If a chat_id belongs to user.
+ """
+ peer = self.resolve_peer(chat_id)
+
+ if isinstance(peer, types.InputPeerChat):
+ self.send(
+ functions.messages.EditChatTitle(
+ chat_id=peer.chat_id,
+ title=title
+ )
+ )
+ elif isinstance(peer, types.InputPeerChannel):
+ self.send(
+ functions.channels.EditTitle(
+ channel=peer,
+ title=title
+ )
+ )
+ else:
+ raise ValueError("The chat_id \"{}\" belongs to a user".format(chat_id))
+
+ return True
diff --git a/pyrogram/client/methods/chats/unpin_chat_message.py b/pyrogram/client/methods/chats/unpin_chat_message.py
new file mode 100644
index 00000000..b1eeec79
--- /dev/null
+++ b/pyrogram/client/methods/chats/unpin_chat_message.py
@@ -0,0 +1,55 @@
+# 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 pyrogram.api import functions, types
+from ...ext import BaseClient
+
+
+class UnpinChatMessage(BaseClient):
+ def unpin_chat_message(self, chat_id: int or str):
+ """Use this method to unpin a message in a supergroup or a channel.
+ You must be an administrator in the chat for this to work and must have the "can_pin_messages" admin
+ right in the supergroup or "can_edit_messages" admin right in the channel.
+
+ Args:
+ chat_id (``int`` | ``str``):
+ Unique identifier (int) or username (str) of the target chat.
+ For a private channel/supergroup you can use its *t.me/joinchat/* link.
+
+ Returns:
+ True on success.
+
+ Raises:
+ :class:`Error `
+ ``ValueError``: If a chat_id doesn't belong to a supergroup or a channel.
+ """
+ peer = self.resolve_peer(chat_id)
+
+ if isinstance(peer, types.InputPeerChannel):
+ self.send(
+ functions.channels.UpdatePinnedMessage(
+ channel=peer,
+ id=0
+ )
+ )
+ elif isinstance(peer, types.InputPeerChat):
+ raise ValueError("The chat_id \"{}\" belongs to a basic group".format(chat_id))
+ else:
+ raise ValueError("The chat_id \"{}\" belongs to a user".format(chat_id))
+
+ return True
diff --git a/pyrogram/client/methods/download_media.py b/pyrogram/client/methods/download_media.py
index 485684b9..b379dbf7 100644
--- a/pyrogram/client/methods/download_media.py
+++ b/pyrogram/client/methods/download_media.py
@@ -74,7 +74,10 @@ class DownloadMedia(BaseClient):
Raises:
:class:`Error `
+ ``ValueError``: If the message doesn't contain any downloadable media
"""
+ error_message = "This message doesn't contain any downloadable media"
+
if isinstance(message, pyrogram_types.Message):
if message.photo:
media = pyrogram_types.Document(
@@ -98,7 +101,7 @@ class DownloadMedia(BaseClient):
elif message.gif:
media = message.gif
else:
- return
+ raise ValueError(error_message)
elif isinstance(message, (
pyrogram_types.Photo,
pyrogram_types.PhotoSize,
@@ -126,7 +129,7 @@ class DownloadMedia(BaseClient):
mime_type=""
)
else:
- return
+ raise ValueError(error_message)
done = asyncio.Event()
path = [None]
diff --git a/pyrogram/client/methods/messages/send_contact.py b/pyrogram/client/methods/messages/send_contact.py
index 7b7b3368..e15bc501 100644
--- a/pyrogram/client/methods/messages/send_contact.py
+++ b/pyrogram/client/methods/messages/send_contact.py
@@ -26,7 +26,7 @@ class SendContact(BaseClient):
phone_number: str,
first_name: str,
last_name: str = "",
- disable_notification: bool = None,
+ vcard: str = "", disable_notification: bool = None,
reply_to_message_id: int = None,
reply_markup=None):
"""Use this method to send phone contacts.
@@ -47,6 +47,9 @@ class SendContact(BaseClient):
last_name (``str``, *optional*):
Contact's last name.
+ vcard (``str``, *optional*):
+ Contact's vCard information.
+
disable_notification (``bool``, *optional*):
Sends the message silently.
Users will receive a notification with no sound.
@@ -68,9 +71,10 @@ class SendContact(BaseClient):
functions.messages.SendMedia(
peer=await self.resolve_peer(chat_id),
media=types.InputMediaContact(
- phone_number,
- first_name,
- last_name
+ phone_number=phone_number,
+ first_name=first_name,
+ last_name=last_name,
+ vcard=vcard
),
message="",
silent=disable_notification or None,
diff --git a/pyrogram/client/types/__init__.py b/pyrogram/client/types/__init__.py
index 3c569324..e6fcc8aa 100644
--- a/pyrogram/client/types/__init__.py
+++ b/pyrogram/client/types/__init__.py
@@ -16,34 +16,26 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
-from .audio import Audio
from .callback_query import CallbackQuery
from .chat import Chat
from .chat_member import ChatMember
+from .chat_members import ChatMembers
from .chat_photo import ChatPhoto
-from .contact import Contact
from .dialog import Dialog
from .dialogs import Dialogs
-from .document import Document
-from .gif import GIF
from .input_media_photo import InputMediaPhoto
from .input_media_video import InputMediaVideo
from .input_phone_contact import InputPhoneContact
-from .location import Location
+from .media import (
+ Audio, Contact, Document, GIF, Location, Photo, PhotoSize,
+ Sticker, Venue, Video, VideoNote, Voice, UserProfilePhotos
+)
from .message import Message
from .message_entity import MessageEntity
from .messages import Messages
-from .photo import Photo
-from .photo_size import PhotoSize
from .reply_markup import (
ForceReply, InlineKeyboardButton, InlineKeyboardMarkup,
KeyboardButton, ReplyKeyboardMarkup, ReplyKeyboardRemove
)
-from .sticker import Sticker
from .update import Update
from .user import User
-from .user_profile_photos import UserProfilePhotos
-from .venue import Venue
-from .video import Video
-from .video_note import VideoNote
-from .voice import Voice
diff --git a/pyrogram/client/types/chat.py b/pyrogram/client/types/chat.py
index 9cd7aec7..afed1ca4 100644
--- a/pyrogram/client/types/chat.py
+++ b/pyrogram/client/types/chat.py
@@ -24,15 +24,13 @@ class Chat(Object):
Args:
id (``int``):
- Unique identifier for this chat. This number may be greater than 32 bits and some programming
- languages may have difficulty/silent defects in interpreting it. But it is smaller than 52 bits,
- so a signed 64 bit integer or double-precision float type are safe for storing this identifier.
+ Unique identifier for this chat.
type (``str``):
Type of chat, can be either "private", "group", "supergroup" or "channel".
title (``str``, *optional*):
- Title, for supergroups, channels and group chats.
+ Title, for supergroups, channels and basic group chats.
username (``str``, *optional*):
Username, for private chats, supergroups and channels if available.
@@ -44,25 +42,33 @@ class Chat(Object):
Last name of the other party in a private chat.
all_members_are_administrators (``bool``, *optional*):
- True if a group has 'All Members Are Admins' enabled.
+ True if a basic group has "All Members Are Admins" enabled.
photo (:obj:`ChatPhoto `, *optional*):
- Chat photo. Returned only in getChat.
+ Chat photo. Suitable for downloads only.
description (``str``, *optional*):
- Description, for supergroups and channel chats. Returned only in getChat.
+ Description, for supergroups and channel chats.
+ Returned only in :meth:`get_chat() `.
invite_link (``str``, *optional*):
- Chat invite link, for supergroups and channel chats. Returned only in getChat.
+ Chat invite link, for supergroups and channel chats.
+ Returned only in :meth:`get_chat() `.
pinned_message (:obj:`Message `, *optional*):
- Pinned message, for supergroups and channel chats. Returned only in getChat.
+ Pinned message, for supergroups and channel chats.
+ Returned only in :meth:`get_chat() `.
sticker_set_name (``str``, *optional*):
- For supergroups, name of group sticker set. Returned only in getChat.
+ For supergroups, name of group sticker set.
+ Returned only in :meth:`get_chat() `.
can_set_sticker_set (``bool``, *optional*):
- True, if the bot can change the group sticker set. Returned only in getChat.
+ True, if the group sticker set can be changed by you.
+ Returned only in :meth:`get_chat() `.
+
+ members_count (``int``, *optional*):
+ Chat members count, for groups and channels only.
"""
ID = 0xb0700002
diff --git a/pyrogram/client/types/chat_members.py b/pyrogram/client/types/chat_members.py
new file mode 100644
index 00000000..658a3086
--- /dev/null
+++ b/pyrogram/client/types/chat_members.py
@@ -0,0 +1,29 @@
+# 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 pyrogram.api.core import Object
+
+
+class ChatMembers(Object):
+ # TODO: Docstrings
+
+ ID = 0xb0700030
+
+ def __init__(self, total_count: int, chat_members: list):
+ self.total_count = total_count
+ self.chat_members = chat_members
diff --git a/pyrogram/client/types/dialog.py b/pyrogram/client/types/dialog.py
index 5ad99477..60ffb76c 100644
--- a/pyrogram/client/types/dialog.py
+++ b/pyrogram/client/types/dialog.py
@@ -20,6 +20,24 @@ from pyrogram.api.core import Object
class Dialog(Object):
+ """This object represents a dialog
+
+ Args:
+ chat (:obj:`Chat `):
+ Conversation the dialog belongs to.
+
+ top_message (:obj:`Message `):
+ The last message sent in the dialog at this time.
+
+ unread_messages_count (``int``):
+ Amount of unread messages in this dialogs.
+
+ unread_mentions_count (``int``):
+ Amount of unread messages containing a mention in this dialog.
+
+ unread_mark (``bool``):
+ True, if the dialog has the unread mark set.
+ """
ID = 0xb0700028
def __init__(self,
@@ -28,7 +46,6 @@ class Dialog(Object):
unread_messages_count: int,
unread_mentions_count: int,
unread_mark: bool):
- # TODO docstrings
self.chat = chat
self.top_message = top_message
self.unread_messages_count = unread_messages_count
diff --git a/pyrogram/client/types/dialogs.py b/pyrogram/client/types/dialogs.py
index 1e1b0cb2..cdf1d951 100644
--- a/pyrogram/client/types/dialogs.py
+++ b/pyrogram/client/types/dialogs.py
@@ -20,9 +20,17 @@ from pyrogram.api.core import Object
class Dialogs(Object):
+ """This object represents a user's dialogs chunk
+
+ Args:
+ total_count (``int``):
+ Total number of dialogs the user has.
+
+ dialogs (List of :obj:`Dialog `):
+ Requested dialogs.
+ """
ID = 0xb0700029
def __init__(self, total_count: int, dialogs: list):
- # TODO docstrings
self.total_count = total_count
self.dialogs = dialogs
diff --git a/pyrogram/client/types/media/__init__.py b/pyrogram/client/types/media/__init__.py
new file mode 100644
index 00000000..5b09d832
--- /dev/null
+++ b/pyrogram/client/types/media/__init__.py
@@ -0,0 +1,31 @@
+# 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 .audio import Audio
+from .contact import Contact
+from .document import Document
+from .gif import GIF
+from .location import Location
+from .photo import Photo
+from .photo_size import PhotoSize
+from .sticker import Sticker
+from .user_profile_photos import UserProfilePhotos
+from .venue import Venue
+from .video import Video
+from .video_note import VideoNote
+from .voice import Voice
diff --git a/pyrogram/client/types/audio.py b/pyrogram/client/types/media/audio.py
similarity index 83%
rename from pyrogram/client/types/audio.py
rename to pyrogram/client/types/media/audio.py
index 51cec257..57731266 100644
--- a/pyrogram/client/types/audio.py
+++ b/pyrogram/client/types/media/audio.py
@@ -65,12 +65,12 @@ class Audio(Object):
performer: str = None,
title: str = None
):
- self.file_id = file_id # string
- self.thumb = thumb # flags.0?PhotoSize
- self.file_name = file_name # flags.1?string
- self.mime_type = mime_type # flags.2?string
- self.file_size = file_size # flags.3?int
- self.date = date # flags.4?int
- self.duration = duration # int
- self.performer = performer # flags.5?string
- self.title = title # flags.6?string
+ 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.duration = duration
+ self.performer = performer
+ self.title = title
diff --git a/pyrogram/client/types/contact.py b/pyrogram/client/types/media/contact.py
similarity index 74%
rename from pyrogram/client/types/contact.py
rename to pyrogram/client/types/media/contact.py
index f625120c..a59e2047 100644
--- a/pyrogram/client/types/contact.py
+++ b/pyrogram/client/types/media/contact.py
@@ -32,14 +32,25 @@ class Contact(Object):
last_name (``str``, *optional*):
Contact's last name.
+ vcard (``str``, *optional*):
+ Contact's vCard.
+
user_id (``int``, *optional*):
Contact's user identifier in Telegram.
"""
ID = 0xb0700011
- def __init__(self, phone_number: str, first_name: str, last_name: str = None, user_id=None):
- self.phone_number = phone_number # string
- self.first_name = first_name # string
- self.last_name = last_name # flags.0?string
- self.user_id = user_id # flags.1?int
+ def __init__(
+ self,
+ phone_number: str,
+ first_name: str,
+ last_name: str = None,
+ vcard: str = None,
+ user_id: int = None
+ ):
+ self.phone_number = phone_number
+ self.first_name = first_name
+ self.last_name = last_name
+ self.vcard = vcard
+ self.user_id = user_id
diff --git a/pyrogram/client/types/document.py b/pyrogram/client/types/media/document.py
similarity index 84%
rename from pyrogram/client/types/document.py
rename to pyrogram/client/types/media/document.py
index 076c1934..d87fa666 100644
--- a/pyrogram/client/types/document.py
+++ b/pyrogram/client/types/media/document.py
@@ -20,7 +20,7 @@ from pyrogram.api.core import Object
class Document(Object):
- """This object represents a general file (as opposed to photos, voice messages and audio files).
+ """This object represents a general file (as opposed to photos, voice messages, audio files, ...).
Args:
file_id (``str``):
@@ -53,9 +53,9 @@ class Document(Object):
file_size: int = None,
date: int = None
):
- self.file_id = file_id # string
- self.thumb = thumb # flags.0?PhotoSize
- self.file_name = file_name # flags.1?string
- self.mime_type = mime_type # flags.2?string
- self.file_size = file_size # flags.3?int
- self.date = date # flags.3?int
+ 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
diff --git a/pyrogram/client/types/gif.py b/pyrogram/client/types/media/gif.py
similarity index 83%
rename from pyrogram/client/types/gif.py
rename to pyrogram/client/types/media/gif.py
index 71e975f5..5172aae2 100644
--- a/pyrogram/client/types/gif.py
+++ b/pyrogram/client/types/media/gif.py
@@ -65,12 +65,12 @@ class GIF(Object):
file_size: int = None,
date: int = None
):
- self.file_id = file_id # string
- self.thumb = thumb # flags.0?PhotoSize
- self.file_name = file_name # flags.1?string
- self.mime_type = mime_type # flags.2?string
- self.file_size = file_size # flags.3?int
- self.date = date # flags.4?int
- self.width = width # int
- self.height = height # int
- self.duration = duration # int
+ 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.width = width
+ self.height = height
+ self.duration = duration
diff --git a/pyrogram/client/types/location.py b/pyrogram/client/types/media/location.py
similarity index 93%
rename from pyrogram/client/types/location.py
rename to pyrogram/client/types/media/location.py
index 1f5feb00..be8c839f 100644
--- a/pyrogram/client/types/location.py
+++ b/pyrogram/client/types/media/location.py
@@ -33,5 +33,5 @@ class Location(Object):
ID = 0xb0700012
def __init__(self, longitude: float, latitude: float):
- self.longitude = longitude # double
- self.latitude = latitude # double
+ self.longitude = longitude
+ self.latitude = latitude
diff --git a/pyrogram/client/types/photo.py b/pyrogram/client/types/media/photo.py
similarity index 92%
rename from pyrogram/client/types/photo.py
rename to pyrogram/client/types/media/photo.py
index f5494f13..d9deed76 100644
--- a/pyrogram/client/types/photo.py
+++ b/pyrogram/client/types/media/photo.py
@@ -27,10 +27,10 @@ class Photo(Object):
Unique identifier for this photo.
date (``int``):
- Date the photo was sent in Unix time
+ Date the photo was sent in Unix time.
sizes (List of :obj:`PhotoSize `):
- Available sizes of this photo
+ Available sizes of this photo.
"""
ID = 0xb0700027
diff --git a/pyrogram/client/types/photo_size.py b/pyrogram/client/types/media/photo_size.py
similarity index 94%
rename from pyrogram/client/types/photo_size.py
rename to pyrogram/client/types/media/photo_size.py
index 65691de0..764b046b 100644
--- a/pyrogram/client/types/photo_size.py
+++ b/pyrogram/client/types/media/photo_size.py
@@ -20,7 +20,7 @@ from pyrogram.api.core import Object
class PhotoSize(Object):
- """This object represents one size of a photo or a file / sticker thumbnail.
+ """This object represents one size of a photo or a file/sticker thumbnail.
Args:
file_id (``str``):
diff --git a/pyrogram/client/types/sticker.py b/pyrogram/client/types/media/sticker.py
similarity index 81%
rename from pyrogram/client/types/sticker.py
rename to pyrogram/client/types/media/sticker.py
index a5ed9085..2e7ac901 100644
--- a/pyrogram/client/types/sticker.py
+++ b/pyrogram/client/types/media/sticker.py
@@ -73,14 +73,14 @@ class Sticker(Object):
set_name: str = None,
mask_position=None
):
- self.file_id = file_id # string
- self.thumb = thumb # flags.0?PhotoSize
- self.file_name = file_name # flags.1?string
- self.mime_type = mime_type # flags.2?string
- self.file_size = file_size # flags.3?int
- self.date = date # flags.4?int
- self.width = width # int
- self.height = height # int
- self.emoji = emoji # flags.5?string
- self.set_name = set_name # flags.6?string
- self.mask_position = mask_position # flags.7?MaskPosition
+ 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.width = width
+ self.height = height
+ self.emoji = emoji
+ self.set_name = set_name
+ self.mask_position = mask_position
diff --git a/pyrogram/client/types/user_profile_photos.py b/pyrogram/client/types/media/user_profile_photos.py
similarity index 100%
rename from pyrogram/client/types/user_profile_photos.py
rename to pyrogram/client/types/media/user_profile_photos.py
diff --git a/pyrogram/client/types/venue.py b/pyrogram/client/types/media/venue.py
similarity index 87%
rename from pyrogram/client/types/venue.py
rename to pyrogram/client/types/media/venue.py
index 653f0dd3..5d9e387f 100644
--- a/pyrogram/client/types/venue.py
+++ b/pyrogram/client/types/media/venue.py
@@ -40,7 +40,7 @@ class Venue(Object):
ID = 0xb0700013
def __init__(self, location, title: str, address: str, foursquare_id: str = None):
- self.location = location # Location
- self.title = title # string
- self.address = address # string
- self.foursquare_id = foursquare_id # flags.0?string
+ self.location = location
+ self.title = title
+ self.address = address
+ self.foursquare_id = foursquare_id
diff --git a/pyrogram/client/types/video.py b/pyrogram/client/types/media/video.py
similarity index 83%
rename from pyrogram/client/types/video.py
rename to pyrogram/client/types/media/video.py
index b4ffff2b..8b272a2d 100644
--- a/pyrogram/client/types/video.py
+++ b/pyrogram/client/types/media/video.py
@@ -65,12 +65,12 @@ class Video(Object):
file_size: int = None,
date: int = None
):
- self.file_id = file_id # string
- self.thumb = thumb # flags.0?PhotoSize
- self.file_name = file_name # flags.1?string
- self.mime_type = mime_type # flags.2?string
- self.file_size = file_size # flags.3?int
- self.date = date # flags.4?int
- self.width = width # int
- self.height = height # int
- self.duration = duration # int
+ 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.width = width
+ self.height = height
+ self.duration = duration
diff --git a/pyrogram/client/types/video_note.py b/pyrogram/client/types/media/video_note.py
similarity index 79%
rename from pyrogram/client/types/video_note.py
rename to pyrogram/client/types/media/video_note.py
index 7f0b6736..642eb5aa 100644
--- a/pyrogram/client/types/video_note.py
+++ b/pyrogram/client/types/media/video_note.py
@@ -35,9 +35,6 @@ class VideoNote(Object):
thumb (:obj:`PhotoSize `, *optional*):
Video thumbnail.
- file_name (``str``, *optional*):
- Video note file name.
-
mime_type (``str``, *optional*):
MIME type of the file as defined by sender.
@@ -56,16 +53,14 @@ class VideoNote(Object):
length: int,
duration: int,
thumb=None,
- file_name: str = None,
mime_type: str = None,
file_size: int = None,
date: int = None
):
- self.file_id = file_id # string
- self.thumb = thumb # flags.0?PhotoSize
- self.file_name = file_name # flags.1?string
- self.mime_type = mime_type # flags.2?string
- self.file_size = file_size # flags.3?int
- self.date = date # flags.4?int
- self.length = length # int
- self.duration = duration # int
+ 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
diff --git a/pyrogram/client/types/voice.py b/pyrogram/client/types/media/voice.py
similarity index 73%
rename from pyrogram/client/types/voice.py
rename to pyrogram/client/types/media/voice.py
index 414d2267..d838cf59 100644
--- a/pyrogram/client/types/voice.py
+++ b/pyrogram/client/types/media/voice.py
@@ -29,11 +29,8 @@ class Voice(Object):
duration (``int``):
Duration of the audio in seconds as defined by sender.
- thumb (:obj:`PhotoSize `, *optional*):
- Voice thumbnail.
-
- file_name (``str``, *optional*):
- Voice file name.
+ waveform (``bytes``, *optional*):
+ Voice waveform.
mime_type (``str``, *optional*):
MIME type of the file as defined by sender.
@@ -51,15 +48,13 @@ class Voice(Object):
self,
file_id: str,
duration: int,
- thumb=None,
- file_name: str = None,
+ waveform: bytes = None,
mime_type: str = None,
file_size: int = None,
date: int = None):
- self.file_id = file_id # string
- self.thumb = thumb # flags.0?PhotoSize
- self.file_name = file_name # flags.1?string
- self.mime_type = mime_type # flags.2?string
- self.file_size = file_size # flags.3?int
- self.date = date # flags.4?int
- self.duration = duration # int
+ self.file_id = file_id
+ self.duration = duration
+ self.waveform = waveform
+ self.mime_type = mime_type
+ self.file_size = file_size
+ self.date = date
diff --git a/pyrogram/client/types/message.py b/pyrogram/client/types/message.py
index 86c40f75..c9137328 100644
--- a/pyrogram/client/types/message.py
+++ b/pyrogram/client/types/message.py
@@ -26,9 +26,6 @@ class Message(Object):
Args:
message_id (``int``):
Unique message identifier inside this chat.
-
- client (:obj:`Client `, *optional*):
- The client instance this message is bound to.
date (``int``, *optional*):
Date the message was sent in Unix time.
@@ -574,3 +571,39 @@ class Message(Object):
raise ValueError("This button is not supported yet")
else:
raise ValueError("The message doesn't contain any keyboard")
+
+ def download(self, file_name: str = "", block: bool = True):
+ """Use this method as a shortcut for:
+
+ .. code-block:: python
+
+ client.download_media(message)
+
+ Example:
+ .. code-block:: python
+
+ message.download()
+
+ Args:
+ file_name (``str``, *optional*):
+ A custom *file_name* to be used instead of the one provided by Telegram.
+ By default, all files are downloaded in the *downloads* folder in your working directory.
+ You can also specify a path for downloading files in a custom location: paths that end with "/"
+ are considered directories. All non-existent folders will be created automatically.
+
+ block (``bool``, *optional*):
+ Blocks the code execution until the file has been downloaded.
+ Defaults to True.
+
+ Returns:
+ On success, the absolute path of the downloaded file as string is returned, None otherwise.
+
+ Raises:
+ :class:`Error `
+ ``ValueError``: If the message doesn't contain any downloadable media
+ """
+ return self._client.download_media(
+ message=self,
+ file_name=file_name,
+ block=block
+ )
diff --git a/pyrogram/client/types/message_entity.py b/pyrogram/client/types/message_entity.py
index 460da6e7..db2eee3e 100644
--- a/pyrogram/client/types/message_entity.py
+++ b/pyrogram/client/types/message_entity.py
@@ -26,9 +26,9 @@ class MessageEntity(Object):
Args:
type (``str``):
Type of the entity.
- Can be mention (@username), hashtag, bot_command, url, email, bold (bold text), italic (italic text),
- code (monowidth string), pre (monowidth block), text_link (for clickable text URLs),
- text_mention (for users without usernames).
+ Can be "mention" (@username), "hashtag", "cashtag", "bot_command", "url", "email", "bold" (bold text),
+ italic (italic text), "code" (monowidth string), "pre" (monowidth block), "text_link" (for clickable text
+ URLs), "text_mention" (for users without usernames).
offset (``int``):
Offset in UTF-16 code units to the start of the entity.
@@ -45,9 +45,16 @@ class MessageEntity(Object):
ID = 0xb0700004
- def __init__(self, type: str, offset: int, length: int, url: str = None, user=None):
- self.type = type # string
- self.offset = offset # int
- self.length = length # int
- self.url = url # flags.0?string
- self.user = user # flags.1?User
+ def __init__(
+ self,
+ type: str,
+ offset: int,
+ length: int,
+ url: str = None,
+ user=None
+ ):
+ self.type = type
+ self.offset = offset
+ self.length = length
+ self.url = url
+ self.user = user
diff --git a/pyrogram/client/types/messages.py b/pyrogram/client/types/messages.py
index 0d5d0a36..7a2546a9 100644
--- a/pyrogram/client/types/messages.py
+++ b/pyrogram/client/types/messages.py
@@ -33,5 +33,5 @@ class Messages(Object):
ID = 0xb0700026
def __init__(self, total_count: int, messages: list):
- self.total_count = total_count # int
- self.messages = messages # Vector>
+ self.total_count = total_count
+ self.messages = messages
diff --git a/pyrogram/client/types/user.py b/pyrogram/client/types/user.py
index 62e79e19..9ae5dab2 100644
--- a/pyrogram/client/types/user.py
+++ b/pyrogram/client/types/user.py
@@ -26,6 +26,18 @@ class User(Object):
id (``int``):
Unique identifier for this user or bot.
+ is_self(``bool``):
+ True, if this user is you yourself.
+
+ is_contact(``bool``):
+ True, if this user is in your contacts.
+
+ is_mutual_contact(``bool``):
+ True, if you both have each other's contact.
+
+ is_deleted(``bool``):
+ True, if this user is deleted.
+
is_bot (``bool``):
True, if this user is a bot.
@@ -42,10 +54,10 @@ class User(Object):
IETF language tag of the user's language.
phone_number (``str``, *optional*):
- User's or bot's phone number.
+ User's phone number.
photo (:obj:`ChatPhoto `, *optional*):
- User's or bot's current profile photo.
+ User's or bot's current profile photo. Suitable for downloads only.
"""
ID = 0xb0700001
@@ -53,6 +65,10 @@ class User(Object):
def __init__(
self,
id: int,
+ is_self: bool,
+ is_contact: bool,
+ is_mutual_contact: bool,
+ is_deleted: bool,
is_bot: bool,
first_name: str,
last_name: str = None,
@@ -62,6 +78,10 @@ class User(Object):
photo=None
):
self.id = id
+ self.is_self = is_self
+ self.is_contact = is_contact
+ self.is_mutual_contact = is_mutual_contact
+ self.is_deleted = is_deleted
self.is_bot = is_bot
self.first_name = first_name
self.last_name = last_name