diff --git a/compiler/api/compiler.py b/compiler/api/compiler.py
index cacd9342..d31353c6 100644
--- a/compiler/api/compiler.py
+++ b/compiler/api/compiler.py
@@ -475,39 +475,6 @@ def start():
f.write("\n 0x3072cfa1: \"pyrogram.api.core.GzipPacked\",")
f.write("\n 0x5bb8e511: \"pyrogram.api.core.Message\",")
- f.write("\n 0xb0700000: \"pyrogram.client.types.Update\",")
- f.write("\n 0xb0700001: \"pyrogram.client.types.User\",")
- f.write("\n 0xb0700002: \"pyrogram.client.types.Chat\",")
- f.write("\n 0xb0700003: \"pyrogram.client.types.Message\",")
- f.write("\n 0xb0700004: \"pyrogram.client.types.MessageEntity\",")
- f.write("\n 0xb0700005: \"pyrogram.client.types.PhotoSize\",")
- f.write("\n 0xb0700006: \"pyrogram.client.types.Audio\",")
- f.write("\n 0xb0700007: \"pyrogram.client.types.Document\",")
- f.write("\n 0xb0700008: \"pyrogram.client.types.Video\",")
- f.write("\n 0xb0700009: \"pyrogram.client.types.Voice\",")
- f.write("\n 0xb0700010: \"pyrogram.client.types.VideoNote\",")
- f.write("\n 0xb0700011: \"pyrogram.client.types.Contact\",")
- f.write("\n 0xb0700012: \"pyrogram.client.types.Location\",")
- f.write("\n 0xb0700013: \"pyrogram.client.types.Venue\",")
- f.write("\n 0xb0700014: \"pyrogram.client.types.UserProfilePhotos\",")
- f.write("\n 0xb0700015: \"pyrogram.client.types.ChatPhoto\",")
- f.write("\n 0xb0700016: \"pyrogram.client.types.ChatMember\",")
- f.write("\n 0xb0700017: \"pyrogram.client.types.Sticker\",")
- f.write("\n 0xb0700018: \"pyrogram.client.types.bots.ForceReply\",")
- f.write("\n 0xb0700019: \"pyrogram.client.types.bots.InlineKeyboardButton\",")
- f.write("\n 0xb0700020: \"pyrogram.client.types.bots.InlineKeyboardMarkup\",")
- f.write("\n 0xb0700021: \"pyrogram.client.types.bots.KeyboardButton\",")
- f.write("\n 0xb0700022: \"pyrogram.client.types.bots.ReplyKeyboardMarkup\",")
- f.write("\n 0xb0700023: \"pyrogram.client.types.bots.ReplyKeyboardRemove\",")
- f.write("\n 0xb0700024: \"pyrogram.client.types.CallbackQuery\",")
- f.write("\n 0xb0700025: \"pyrogram.client.types.Animation\",")
- f.write("\n 0xb0700026: \"pyrogram.client.types.Messages\",")
- 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 0xb0700031: \"pyrogram.client.types.UserStatus\"")
-
f.write("\n}\n")
for k, v in namespaces.items():
diff --git a/pyrogram/__init__.py b/pyrogram/__init__.py
index 57ac6f08..bc6d8424 100644
--- a/pyrogram/__init__.py
+++ b/pyrogram/__init__.py
@@ -37,7 +37,7 @@ from .api.errors import Error
from .client.types import (
Audio, Chat, ChatMember, ChatMembers, ChatPhoto, Contact, Document, InputMediaPhoto,
InputMediaVideo, InputMediaDocument, InputMediaAudio, InputMediaAnimation, InputPhoneContact,
- Location, Message, MessageEntity, Dialog, Dialogs, Photo, PhotoSize, Sticker, Update, User, UserStatus,
+ Location, Message, MessageEntity, Dialog, Dialogs, Photo, PhotoSize, Sticker, User, UserStatus,
UserProfilePhotos, Venue, Animation, Video, VideoNote, Voice, CallbackQuery, Messages, ForceReply,
InlineKeyboardButton, InlineKeyboardMarkup, KeyboardButton, ReplyKeyboardMarkup, ReplyKeyboardRemove
)
diff --git a/pyrogram/client/client.py b/pyrogram/client/client.py
index 3c0081a7..1401ac6c 100644
--- a/pyrogram/client/client.py
+++ b/pyrogram/client/client.py
@@ -36,6 +36,7 @@ from hashlib import sha256, md5
from importlib import import_module
from pathlib import Path
from signal import signal, SIGINT, SIGTERM, SIGABRT
+from typing import Union, List
from pyrogram.api import functions, types
from pyrogram.api.core import Object
@@ -44,8 +45,7 @@ from pyrogram.api.errors import (
PhoneNumberUnoccupied, PhoneCodeInvalid, PhoneCodeHashEmpty,
PhoneCodeExpired, PhoneCodeEmpty, SessionPasswordNeeded,
PasswordHashInvalid, FloodWait, PeerIdInvalid, FirstnameInvalid, PhoneNumberBanned,
- VolumeLocNotFound, UserMigrate, FileIdInvalid, ChannelPrivate)
-from pyrogram.client.handlers import DisconnectHandler
+ VolumeLocNotFound, UserMigrate, FileIdInvalid, ChannelPrivate, PhoneNumberOccupied)
from pyrogram.client.handlers.handler import Handler
from pyrogram.crypto import AES
from pyrogram.session import Auth, Session
@@ -153,7 +153,7 @@ class Client(Methods, BaseClient):
def __init__(self,
session_name: str,
- api_id: int or str = None,
+ api_id: Union[int, str] = None,
api_hash: str = None,
app_version: str = None,
device_model: str = None,
@@ -163,7 +163,7 @@ class Client(Methods, BaseClient):
proxy: dict = None,
test_mode: bool = False,
phone_number: str = None,
- phone_code: str or callable = None,
+ phone_code: Union[str, callable] = None,
password: str = None,
force_sms: bool = False,
first_name: str = None,
@@ -372,7 +372,7 @@ class Client(Methods, BaseClient):
return coroutine
- def add_handler(self, handler, group: int = 0):
+ def add_handler(self, handler: Handler, group: int = 0):
"""Use this method to register an update handler.
You can register multiple handlers, but at most one handler within a group
@@ -396,7 +396,7 @@ class Client(Methods, BaseClient):
return handler, group
- def remove_handler(self, handler, group: int = 0):
+ def remove_handler(self, handler: Handler, group: int = 0):
"""Removes a previously-added update handler.
Make sure to provide the right group that the handler was added in. You can use
@@ -534,16 +534,8 @@ class Client(Methods, BaseClient):
try:
if phone_registered:
- r = await self.send(
- functions.auth.SignIn(
- self.phone_number,
- phone_code_hash,
- self.phone_code
- )
- )
- else:
try:
- await self.send(
+ r = await self.send(
functions.auth.SignIn(
self.phone_number,
phone_code_hash,
@@ -551,20 +543,27 @@ class Client(Methods, BaseClient):
)
)
except PhoneNumberUnoccupied:
- pass
+ log.warning("Phone number unregistered")
+ phone_registered = False
+ continue
+ else:
+ self.first_name = self.first_name if self.first_name is not None else input("First name: ")
+ self.last_name = self.last_name if self.last_name is not None else input("Last name: ")
- self.first_name = self.first_name if self.first_name is not None else await ainput("First name: ")
- self.last_name = self.last_name if self.last_name is not None else await ainput("Last name: ")
-
- r = await self.send(
- functions.auth.SignUp(
- self.phone_number,
- phone_code_hash,
- self.phone_code,
- self.first_name,
- self.last_name
+ try:
+ r = await self.send(
+ functions.auth.SignUp(
+ self.phone_number,
+ phone_code_hash,
+ self.phone_code,
+ self.first_name,
+ self.last_name
+ )
)
- )
+ except PhoneNumberOccupied:
+ log.warning("Phone number already registered")
+ phone_registered = True
+ continue
except (PhoneCodeInvalid, PhoneCodeEmpty, PhoneCodeExpired, PhoneCodeHashEmpty) as e:
if phone_code_invalid_raises:
raise
@@ -630,7 +629,9 @@ class Client(Methods, BaseClient):
print("Logged in successfully as {}".format(r.user.first_name))
- def fetch_peers(self, entities: list):
+ def fetch_peers(self, entities: List[Union[types.User,
+ types.Chat, types.ChatForbidden,
+ types.Channel, types.ChannelForbidden]]):
for entity in entities:
if isinstance(entity, types.User):
user_id = entity.id
@@ -886,7 +887,10 @@ class Client(Methods, BaseClient):
log.info("UpdatesWorkerTask stopped")
- async def send(self, data: Object, retries: int = Session.MAX_RETRIES, timeout: float = Session.WAIT_TIMEOUT):
+ async def send(self,
+ data: Object,
+ retries: int = Session.MAX_RETRIES,
+ timeout: float = Session.WAIT_TIMEOUT):
"""Use this method to send Raw Function queries.
This method makes possible to manually call every single Telegram API method in a low-level manner.
@@ -1045,7 +1049,8 @@ class Client(Methods, BaseClient):
indent=4
)
- async def get_initial_dialogs_chunk(self, offset_date: int = 0):
+ async def get_initial_dialogs_chunk(self,
+ offset_date: int = 0):
while True:
try:
r = await self.send(
@@ -1077,7 +1082,8 @@ class Client(Methods, BaseClient):
await self.get_initial_dialogs_chunk()
- async def resolve_peer(self, peer_id: int or str):
+ async def resolve_peer(self,
+ 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
@@ -1146,13 +1152,13 @@ class Client(Methods, BaseClient):
part_size = 512 * 1024
file_size = os.path.getsize(path)
-
+
if file_size == 0:
raise ValueError("File size equals to 0 B")
-
+
if file_size > 1500 * 1024 * 1024:
raise ValueError("Telegram doesn't support uploading files bigger than 1500 MiB")
-
+
file_total_parts = int(math.ceil(file_size / part_size))
is_big = file_size > 10 * 1024 * 1024
is_missing_part = file_id is not None
diff --git a/pyrogram/client/dispatcher/dispatcher.py b/pyrogram/client/dispatcher/dispatcher.py
index 0883571e..e6dcd4b6 100644
--- a/pyrogram/client/dispatcher/dispatcher.py
+++ b/pyrogram/client/dispatcher/dispatcher.py
@@ -20,9 +20,9 @@ import asyncio
import logging
from collections import OrderedDict
+import pyrogram
from pyrogram.api import types
-from ..ext import utils
-from ..handlers import CallbackQueryHandler, MessageHandler, DeletedMessagesHandler, UserStatusHandler, RawUpdateHandler
+from ..handlers import CallbackQueryHandler, MessageHandler, RawUpdateHandler, UserStatusHandler, DeletedMessagesHandler
log = logging.getLogger(__name__)
@@ -38,7 +38,7 @@ class Dispatcher:
types.UpdateEditChannelMessage
)
- DELETE_MESSAGE_UPDATES = (
+ DELETE_MESSAGES_UPDATES = (
types.UpdateDeleteMessages,
types.UpdateDeleteChannelMessages
)
@@ -59,16 +59,16 @@ class Dispatcher:
self.groups = OrderedDict()
async def message_parser(update, users, chats):
- return await utils.parse_messages(self.client, update.message, users, chats), MessageHandler
+ return await pyrogram.Message._parse(self.client, update.message, users, chats), MessageHandler
async def deleted_messages_parser(update, users, chats):
- return utils.parse_deleted_messages(update), DeletedMessagesHandler
+ return pyrogram.Messages._parse_deleted(self.client, update), DeletedMessagesHandler
async def callback_query_parser(update, users, chats):
- return await utils.parse_callback_query(self.client, update, users), CallbackQueryHandler
+ return await pyrogram.CallbackQuery._parse(self.client, update, users), CallbackQueryHandler
async def user_status_parser(update, users, chats):
- return utils.parse_user_status(update.status, update.user_id), UserStatusHandler
+ return pyrogram.UserStatus._parse(self.client, update.status, update.user_id), UserStatusHandler
self.update_parsers = {
Dispatcher.MESSAGE_UPDATES: message_parser,
diff --git a/pyrogram/client/ext/utils.py b/pyrogram/client/ext/utils.py
index a8b5b07b..3e67e3cd 100644
--- a/pyrogram/client/ext/utils.py
+++ b/pyrogram/client/ext/utils.py
@@ -16,245 +16,9 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
-import asyncio
-import logging
-import sys
from base64 import b64decode, b64encode
-from concurrent.futures.thread import ThreadPoolExecutor
-from struct import pack
-from pyrogram.client import types as pyrogram_types
-from ...api import types, functions
-from ...api.errors import StickersetInvalid, MessageIdsEmpty
-
-log = logging.getLogger(__name__)
-
-
-# TODO: Organize the code better?
-
-class Str(str):
- __slots__ = "_client", "_entities"
-
- def __init__(self, *args):
- super().__init__()
- self._client = None
- self._entities = None
-
- def init(self, client, entities):
- self._client = client
- self._entities = entities
-
- @property
- def text(self):
- return self
-
- @property
- def markdown(self):
- return self._client.markdown.unparse(self, self._entities)
-
- @property
- def html(self):
- return self._client.html.unparse(self, self._entities)
-
-
-async def ainput(prompt: str = ""):
- print(prompt, end="", flush=True)
-
- with ThreadPoolExecutor(1) as executor:
- return (await asyncio.get_event_loop().run_in_executor(
- executor, sys.stdin.readline
- )).rstrip()
-
-
-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",
- types.MessageEntityBold.ID: "bold",
- types.MessageEntityItalic.ID: "italic",
- types.MessageEntityCode.ID: "code",
- types.MessageEntityPre.ID: "pre",
- types.MessageEntityTextUrl.ID: "text_link",
- types.MessageEntityMentionName.ID: "text_mention",
- types.MessageEntityPhone.ID: "phone_number"
-}
-
-
-def parse_entities(entities: list, users: dict) -> list:
- output_entities = []
-
- for entity in entities:
- entity_type = ENTITIES.get(entity.ID, None)
-
- if entity_type:
- output_entities.append(
- pyrogram_types.MessageEntity(
- type=entity_type,
- offset=entity.offset,
- length=entity.length,
- url=getattr(entity, "url", None),
- user=parse_user(
- users.get(
- getattr(entity, "user_id", None),
- None
- )
- )
- )
- )
-
- return output_entities
-
-
-def parse_chat_photo(photo):
- if not isinstance(photo, (types.UserProfilePhoto, types.ChatPhoto)):
- return None
-
- if not isinstance(photo.photo_small, types.FileLocation):
- return None
-
- if not isinstance(photo.photo_big, types.FileLocation):
- return None
-
- photo_id = getattr(photo, "photo_id", 0)
- loc_small = photo.photo_small
- loc_big = photo.photo_big
-
- return pyrogram_types.ChatPhoto(
- small_file_id=encode(
- pack(
- " pyrogram_types.UserStatus or None:
- if is_bot:
- return None
-
- status = pyrogram_types.UserStatus(user_id)
-
- if isinstance(user_status, types.UserStatusOnline):
- status.online = True
- status.date = user_status.expires
- elif isinstance(user_status, types.UserStatusOffline):
- status.offline = True
- status.date = user_status.was_online
- elif isinstance(user_status, types.UserStatusRecently):
- status.recently = True
- elif isinstance(user_status, types.UserStatusLastWeek):
- status.within_week = True
- elif isinstance(user_status, types.UserStatusLastMonth):
- status.within_month = True
- else:
- status.long_time_ago = True
-
- return status
-
-
-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,
- username=user.username,
- language_code=user.lang_code,
- phone_number=user.phone,
- photo=parse_chat_photo(user.photo),
- status=parse_user_status(user.status, is_bot=user.bot),
- restriction_reason=user.restriction_reason
- ) if user else None
-
-
-def parse_chat(message: types.Message, users: dict, chats: dict) -> pyrogram_types.Chat:
- if isinstance(message.to_id, types.PeerUser):
- return parse_user_chat(users[message.to_id.user_id if message.out else message.from_id])
- elif isinstance(message.to_id, types.PeerChat):
- return parse_chat_chat(chats[message.to_id.chat_id])
- else:
- return parse_channel_chat(chats[message.to_id.channel_id])
-
-
-def parse_user_chat(user: types.User) -> pyrogram_types.Chat:
- return pyrogram_types.Chat(
- id=user.id,
- type="private",
- username=user.username,
- first_name=user.first_name,
- last_name=user.last_name,
- photo=parse_chat_photo(user.photo),
- restriction_reason=user.restriction_reason
- )
-
-
-def parse_chat_chat(chat: types.Chat) -> pyrogram_types.Chat:
- admins_enabled = getattr(chat, "admins_enabled", None)
-
- if admins_enabled is not None:
- admins_enabled = not admins_enabled
-
- return pyrogram_types.Chat(
- id=-chat.id,
- type="group",
- title=chat.title,
- all_members_are_administrators=admins_enabled,
- photo=parse_chat_photo(getattr(chat, "photo", None))
- )
-
-
-def parse_channel_chat(channel: types.Channel) -> pyrogram_types.Chat:
- return pyrogram_types.Chat(
- id=int("-100" + str(channel.id)),
- type="supergroup" if channel.megagroup else "channel",
- title=channel.title,
- username=getattr(channel, "username", None),
- photo=parse_chat_photo(getattr(channel, "photo", None)),
- restriction_reason=getattr(channel, "restriction_reason", None)
- )
-
-
-def parse_thumb(thumb: types.PhotoSize or types.PhotoCachedSize) -> pyrogram_types.PhotoSize or None:
- if isinstance(thumb, (types.PhotoSize, types.PhotoCachedSize)):
- loc = thumb.location
-
- if isinstance(thumb, types.PhotoSize):
- file_size = thumb.size
- else:
- file_size = len(thumb.bytes)
-
- if isinstance(loc, types.FileLocation):
- return pyrogram_types.PhotoSize(
- file_id=encode(
- pack(
- " bytes:
@@ -293,507 +57,6 @@ def encode(s: bytes) -> str:
return b64encode(r, b"-_").decode().rstrip("=")
-# TODO: Reorganize code, maybe split parts as well
-async def parse_messages(
- client,
- messages: list or types.Message or types.MessageService or types.MessageEmpty,
- users: dict,
- chats: dict,
- replies: int = 1
-) -> pyrogram_types.Message or list:
- is_list = isinstance(messages, list)
- messages = messages if is_list else [messages]
- parsed_messages = []
-
- for message in messages:
- if isinstance(message, types.Message):
- entities = parse_entities(message.entities, users)
-
- forward_from = None
- forward_from_chat = None
- forward_from_message_id = None
- forward_signature = None
- forward_date = None
-
- forward_header = message.fwd_from # type: types.MessageFwdHeader
-
- if forward_header:
- forward_date = forward_header.date
-
- if forward_header.from_id:
- forward_from = parse_user(users[forward_header.from_id])
- else:
- forward_from_chat = parse_channel_chat(chats[forward_header.channel_id])
- forward_from_message_id = forward_header.channel_post
- forward_signature = forward_header.post_author
-
- photo = None
- location = None
- contact = None
- venue = None
- audio = None
- voice = None
- animation = None
- video = None
- video_note = None
- sticker = None
- document = None
- web_page = None
-
- media = message.media
-
- if media:
- if isinstance(media, types.MessageMediaPhoto):
- photo = media.photo
-
- if isinstance(photo, types.Photo):
- sizes = photo.sizes
- photo_sizes = []
-
- for size in sizes:
- if isinstance(size, (types.PhotoSize, types.PhotoCachedSize)):
- loc = size.location
-
- if isinstance(size, types.PhotoSize):
- file_size = size.size
- else:
- file_size = len(size.bytes)
-
- if isinstance(loc, types.FileLocation):
- photo_size = pyrogram_types.PhotoSize(
- file_id=encode(
- pack(
- " pyrogram_types.Messages:
- messages = update.messages
- channel_id = getattr(update, "channel_id", None)
-
- parsed_messages = []
-
- for message in messages:
- parsed_messages.append(
- pyrogram_types.Message(
- message_id=message,
- chat=(pyrogram_types.Chat(id=int("-100" + str(channel_id)), type="channel")
- if channel_id is not None
- else None)
- )
- )
-
- return pyrogram_types.Messages(len(parsed_messages), parsed_messages)
-
-
def get_peer_id(input_peer) -> int:
return (
input_peer.user_id if isinstance(input_peer, types.InputPeerUser)
@@ -819,255 +82,3 @@ def get_offset_date(dialogs):
return m.date
else:
return 0
-
-
-def parse_profile_photos(photos):
- if isinstance(photos, types.photos.Photos):
- total_count = len(photos.photos)
- else:
- total_count = photos.count
-
- user_profile_photos = []
-
- for photo in photos.photos:
- if isinstance(photo, types.Photo):
- sizes = photo.sizes
- photo_sizes = []
-
- for size in sizes:
- if isinstance(size, (types.PhotoSize, types.PhotoCachedSize)):
- loc = size.location
-
- if isinstance(size, types.PhotoSize):
- file_size = size.size
- else:
- file_size = len(size.bytes)
-
- if isinstance(loc, types.FileLocation):
- photo_size = pyrogram_types.PhotoSize(
- file_id=encode(
- pack(
- " pyrogram_types.Chat:
- if isinstance(chat_full, types.UserFull):
- parsed_chat = parse_user_chat(chat_full.user)
- parsed_chat.description = chat_full.about
- else:
- full_chat = chat_full.full_chat
- chat = None
-
- for i in chat_full.chats:
- if full_chat.id == i.id:
- chat = i
-
- if isinstance(full_chat, types.ChatFull):
- parsed_chat = parse_chat_chat(chat)
-
- if isinstance(full_chat.participants, types.ChatParticipants):
- parsed_chat.members_count = len(full_chat.participants.participants)
- else:
- parsed_chat = parse_channel_chat(chat)
- parsed_chat.members_count = full_chat.participants_count
- parsed_chat.description = full_chat.about or None
- # TODO: Add StickerSet type
- parsed_chat.can_set_sticker_set = full_chat.can_set_stickers
- parsed_chat.sticker_set_name = full_chat.stickerset
-
- if full_chat.pinned_msg_id:
- parsed_chat.pinned_message = await client.get_messages(
- parsed_chat.id,
- message_ids=full_chat.pinned_msg_id
- )
-
- if isinstance(full_chat.exported_invite, types.ChatInviteExported):
- parsed_chat.invite_link = full_chat.exported_invite.link
-
- return parsed_chat
-
-
-def parse_dialog_chat(peer, users: dict, chats: dict):
- if isinstance(peer, types.PeerUser):
- return parse_user_chat(users[peer.user_id])
- elif isinstance(peer, types.PeerChat):
- 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):
- count = members.count
- 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=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/bots/get_inline_bot_results.py b/pyrogram/client/methods/bots/get_inline_bot_results.py
index 5aa1ddda..0953b6c1 100644
--- a/pyrogram/client/methods/bots/get_inline_bot_results.py
+++ b/pyrogram/client/methods/bots/get_inline_bot_results.py
@@ -16,6 +16,8 @@
# 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 pyrogram.api.errors import UnknownError
from pyrogram.client.ext import BaseClient
@@ -23,7 +25,7 @@ from pyrogram.client.ext import BaseClient
class GetInlineBotResults(BaseClient):
async def get_inline_bot_results(self,
- bot: int or str,
+ bot: Union[int, str],
query: str,
offset: str = "",
latitude: float = None,
diff --git a/pyrogram/client/methods/bots/request_callback_answer.py b/pyrogram/client/methods/bots/request_callback_answer.py
index da0f09e5..5bd7adef 100644
--- a/pyrogram/client/methods/bots/request_callback_answer.py
+++ b/pyrogram/client/methods/bots/request_callback_answer.py
@@ -16,13 +16,15 @@
# 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
from pyrogram.client.ext import BaseClient
class RequestCallbackAnswer(BaseClient):
async def request_callback_answer(self,
- chat_id: int or str,
+ chat_id: Union[int, str],
message_id: int,
callback_data: bytes):
"""Use this method to request a callback answer from bots. This is the equivalent of clicking an
diff --git a/pyrogram/client/methods/bots/send_inline_bot_result.py b/pyrogram/client/methods/bots/send_inline_bot_result.py
index 3b3d36aa..0fade63b 100644
--- a/pyrogram/client/methods/bots/send_inline_bot_result.py
+++ b/pyrogram/client/methods/bots/send_inline_bot_result.py
@@ -16,13 +16,15 @@
# 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
from pyrogram.client.ext import BaseClient
class SendInlineBotResult(BaseClient):
async def send_inline_bot_result(self,
- chat_id: int or str,
+ chat_id: Union[int, str],
query_id: int,
result_id: str,
disable_notification: bool = None,
diff --git a/pyrogram/client/methods/chats/delete_chat_photo.py b/pyrogram/client/methods/chats/delete_chat_photo.py
index b107aa3e..d076a600 100644
--- a/pyrogram/client/methods/chats/delete_chat_photo.py
+++ b/pyrogram/client/methods/chats/delete_chat_photo.py
@@ -16,12 +16,15 @@
# 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 DeleteChatPhoto(BaseClient):
- async def delete_chat_photo(self, chat_id: int or str):
+ async def delete_chat_photo(self,
+ chat_id: Union[int, str]) -> bool:
"""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.
diff --git a/pyrogram/client/methods/chats/export_chat_invite_link.py b/pyrogram/client/methods/chats/export_chat_invite_link.py
index 710679d5..c02f49de 100644
--- a/pyrogram/client/methods/chats/export_chat_invite_link.py
+++ b/pyrogram/client/methods/chats/export_chat_invite_link.py
@@ -16,12 +16,15 @@
# 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 ExportChatInviteLink(BaseClient):
- async def export_chat_invite_link(self, chat_id: int or str):
+ async def export_chat_invite_link(self,
+ chat_id: Union[int, str]) -> str:
"""Use this method to generate a new invite link for a chat; any previously generated link is revoked.
You must be an administrator in the chat for this to work and have the appropriate admin rights.
diff --git a/pyrogram/client/methods/chats/get_chat.py b/pyrogram/client/methods/chats/get_chat.py
index 2b22fd67..8446b29d 100644
--- a/pyrogram/client/methods/chats/get_chat.py
+++ b/pyrogram/client/methods/chats/get_chat.py
@@ -16,12 +16,16 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
+from typing import Union
+
+import pyrogram
from pyrogram.api import functions, types
-from ...ext import BaseClient, utils
+from ...ext import BaseClient
class GetChat(BaseClient):
- async def get_chat(self, chat_id: int or str):
+ async def get_chat(self,
+ chat_id: Union[int, str]) -> "pyrogram.Chat":
"""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.)
@@ -44,4 +48,4 @@ class GetChat(BaseClient):
else:
r = await self.send(functions.messages.GetFullChat(peer.chat_id))
- return await utils.parse_chat_full(self, r)
+ return pyrogram.Chat._parse_full(self, r)
diff --git a/pyrogram/client/methods/chats/get_chat_member.py b/pyrogram/client/methods/chats/get_chat_member.py
index 2943c8de..81c7f137 100644
--- a/pyrogram/client/methods/chats/get_chat_member.py
+++ b/pyrogram/client/methods/chats/get_chat_member.py
@@ -16,14 +16,17 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
+from typing import Union
+
+import pyrogram
from pyrogram.api import functions, types, errors
-from ...ext import BaseClient, utils
+from ...ext import BaseClient
class GetChatMember(BaseClient):
async def get_chat_member(self,
- chat_id: int or str,
- user_id: int or str):
+ chat_id: Union[int, str],
+ user_id: Union[int, str]) -> "pyrogram.ChatMember":
"""Use this method to get information about one member of a chat.
Args:
@@ -51,7 +54,7 @@ class GetChatMember(BaseClient):
)
)
- for member in utils.parse_chat_members(full_chat).chat_members:
+ for member in pyrogram.ChatMembers._parse(self, full_chat).chat_members:
if member.user.id == user_id.user_id:
return member
else:
@@ -64,12 +67,6 @@ class GetChatMember(BaseClient):
)
)
- return utils.parse_chat_members(
- types.channels.ChannelParticipants(
- count=1,
- participants=[r.participant],
- users=r.users
- )
- ).chat_members[0]
+ return pyrogram.ChatMember._parse(self, r.participant, r.users[0])
else:
raise ValueError("The chat_id \"{}\" belongs to a user".format(chat_id))
diff --git a/pyrogram/client/methods/chats/get_chat_members.py b/pyrogram/client/methods/chats/get_chat_members.py
index 70f2c310..dfe2844e 100644
--- a/pyrogram/client/methods/chats/get_chat_members.py
+++ b/pyrogram/client/methods/chats/get_chat_members.py
@@ -16,8 +16,11 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
+from typing import Union
+
+import pyrogram
from pyrogram.api import functions, types
-from ...ext import BaseClient, utils
+from ...ext import BaseClient
class Filters:
@@ -31,11 +34,11 @@ class Filters:
class GetChatMembers(BaseClient):
async def get_chat_members(self,
- chat_id: int or str,
+ chat_id: Union[int, str],
offset: int = 0,
limit: int = 200,
query: str = "",
- filter: str = Filters.ALL):
+ filter: str = Filters.ALL) -> "pyrogram.ChatMembers":
"""Use this method to get the members list of a chat.
A chat can be either a basic group, a supergroup or a channel.
@@ -83,7 +86,8 @@ class GetChatMembers(BaseClient):
peer = await self.resolve_peer(chat_id)
if isinstance(peer, types.InputPeerChat):
- return utils.parse_chat_members(
+ return pyrogram.ChatMembers._parse(
+ self,
await self.send(
functions.messages.GetFullChat(
peer.chat_id
@@ -108,7 +112,8 @@ class GetChatMembers(BaseClient):
else:
raise ValueError("Invalid filter \"{}\"".format(filter))
- return utils.parse_chat_members(
+ return pyrogram.ChatMembers._parse(
+ self,
await self.send(
functions.channels.GetParticipants(
channel=peer,
diff --git a/pyrogram/client/methods/chats/get_chat_members_count.py b/pyrogram/client/methods/chats/get_chat_members_count.py
index f3344b96..8f5ee51c 100644
--- a/pyrogram/client/methods/chats/get_chat_members_count.py
+++ b/pyrogram/client/methods/chats/get_chat_members_count.py
@@ -16,12 +16,15 @@
# 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 GetChatMembersCount(BaseClient):
- async def get_chat_members_count(self, chat_id: int or str):
+ async def get_chat_members_count(self,
+ chat_id: Union[int, str]) -> int:
"""Use this method to get the number of members in a chat.
Args:
diff --git a/pyrogram/client/methods/chats/get_dialogs.py b/pyrogram/client/methods/chats/get_dialogs.py
index 5018dc1e..583615fd 100644
--- a/pyrogram/client/methods/chats/get_dialogs.py
+++ b/pyrogram/client/methods/chats/get_dialogs.py
@@ -18,31 +18,31 @@
import pyrogram
from pyrogram.api import functions, types
-from ...ext import BaseClient, utils
+from ...ext import BaseClient
class GetDialogs(BaseClient):
async def get_dialogs(self,
- offset_dialogs=None,
+ offset_dialog: "pyrogram.Dialog" = None,
limit: int = 100,
- pinned_only: bool = False):
+ pinned_only: bool = False) -> "pyrogram.Dialogs":
"""Use this method to get the user's dialogs
You can get up to 100 dialogs at once.
Args:
+ offset_dialog (:obj:`Dialog`):
+ Sequential Dialog of the first dialog to be returned.
+ Defaults to None (start from the beginning).
+
limit (``str``, *optional*):
Limits the number of dialogs to be retrieved.
- Defaults to 100
+ Defaults to 100.
pinned_only (``bool``, *optional*):
Pass True if you want to get only pinned dialogs.
Defaults to False.
- offset_dialogs (:obj:`Dialogs`):
- Pass the previous dialogs object to retrieve the next dialogs chunk starting from the last dialog.
- Defaults to None (start from the beginning).
-
Returns:
On success, a :obj:`Dialogs` object is returned.
@@ -53,22 +53,9 @@ class GetDialogs(BaseClient):
if pinned_only:
r = await self.send(functions.messages.GetPinnedDialogs())
else:
- offset_date = 0
-
- if offset_dialogs:
- for dialog in reversed(offset_dialogs.dialogs):
- top_message = dialog.top_message
-
- if top_message:
- message_date = top_message.date
-
- if message_date:
- offset_date = message_date
- break
-
r = await self.send(
functions.messages.GetDialogs(
- offset_date=offset_date,
+ offset_date=offset_dialog.top_message.date if offset_dialog else 0,
offset_id=0,
offset_peer=types.InputPeerEmpty(),
limit=limit,
@@ -77,49 +64,4 @@ class GetDialogs(BaseClient):
)
)
- users = {i.id: i for i in r.users}
- chats = {i.id: i for i in r.chats}
- messages = {}
-
- for message in r.messages:
- to_id = message.to_id
-
- if isinstance(to_id, types.PeerUser):
- if message.out:
- chat_id = to_id.user_id
- else:
- chat_id = message.from_id
- elif isinstance(to_id, types.PeerChat):
- chat_id = -to_id.chat_id
- else:
- chat_id = int("-100" + str(to_id.channel_id))
-
- messages[chat_id] = await utils.parse_messages(self, message, users, chats)
-
- dialogs = []
-
- for dialog in r.dialogs:
- chat_id = dialog.peer
-
- if isinstance(chat_id, types.PeerUser):
- chat_id = chat_id.user_id
- elif isinstance(chat_id, types.PeerChat):
- chat_id = -chat_id.chat_id
- else:
- chat_id = int("-100" + str(chat_id.channel_id))
-
- dialogs.append(
- pyrogram.Dialog(
- chat=utils.parse_dialog_chat(dialog.peer, users, chats),
- top_message=messages.get(chat_id),
- unread_messages_count=dialog.unread_count,
- unread_mentions_count=dialog.unread_mentions_count,
- unread_mark=dialog.unread_mark,
- is_pinned=dialog.pinned
- )
- )
-
- return pyrogram.Dialogs(
- total_count=getattr(r, "count", len(r.dialogs)),
- dialogs=dialogs
- )
+ return pyrogram.Dialogs._parse(self, r)
diff --git a/pyrogram/client/methods/chats/join_chat.py b/pyrogram/client/methods/chats/join_chat.py
index 6eb1a543..f37368ba 100644
--- a/pyrogram/client/methods/chats/join_chat.py
+++ b/pyrogram/client/methods/chats/join_chat.py
@@ -21,7 +21,8 @@ from ...ext import BaseClient
class JoinChat(BaseClient):
- async def join_chat(self, chat_id: str):
+ async def join_chat(self,
+ chat_id: str):
"""Use this method to join a group chat or channel.
Args:
diff --git a/pyrogram/client/methods/chats/kick_chat_member.py b/pyrogram/client/methods/chats/kick_chat_member.py
index 74a073bb..efa6ff52 100644
--- a/pyrogram/client/methods/chats/kick_chat_member.py
+++ b/pyrogram/client/methods/chats/kick_chat_member.py
@@ -16,16 +16,18 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
+from typing import Union
+
+import pyrogram
from pyrogram.api import functions, types
-from pyrogram.client.ext import utils
from ...ext import BaseClient
class KickChatMember(BaseClient):
async def kick_chat_member(self,
- chat_id: int or str,
- user_id: int or str,
- until_date: int = 0):
+ chat_id: Union[int, str],
+ user_id: Union[int, str],
+ until_date: int = 0) -> "pyrogram.Message":
"""Use this method to kick a user from a group, a supergroup or a channel.
In the case of supergroups and channels, the user will not be able to return to the group on their own using
invite links, etc., unless unbanned first. You must be an administrator in the chat for this to work and must
@@ -86,7 +88,7 @@ class KickChatMember(BaseClient):
for i in r.updates:
if isinstance(i, (types.UpdateNewMessage, types.UpdateNewChannelMessage)):
- return utils.parse_messages(
+ return await pyrogram.Message._parse(
self, i.message,
{i.id: i for i in r.users},
{i.id: i for i in r.chats}
diff --git a/pyrogram/client/methods/chats/leave_chat.py b/pyrogram/client/methods/chats/leave_chat.py
index 62af1781..0f947aa8 100644
--- a/pyrogram/client/methods/chats/leave_chat.py
+++ b/pyrogram/client/methods/chats/leave_chat.py
@@ -16,12 +16,16 @@
# 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 LeaveChat(BaseClient):
- async def leave_chat(self, chat_id: int or str, delete: bool = False):
+ async def leave_chat(self,
+ chat_id: Union[int, str],
+ delete: bool = False):
"""Use this method to leave a group chat or channel.
Args:
diff --git a/pyrogram/client/methods/chats/pin_chat_message.py b/pyrogram/client/methods/chats/pin_chat_message.py
index 8df5dfde..c0902234 100644
--- a/pyrogram/client/methods/chats/pin_chat_message.py
+++ b/pyrogram/client/methods/chats/pin_chat_message.py
@@ -16,12 +16,17 @@
# 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 PinChatMessage(BaseClient):
- async def pin_chat_message(self, chat_id: int or str, message_id: int, disable_notification: bool = None):
+ async def pin_chat_message(self,
+ chat_id: Union[int, str],
+ message_id: int,
+ disable_notification: bool = None) -> bool:
"""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.
diff --git a/pyrogram/client/methods/chats/promote_chat_member.py b/pyrogram/client/methods/chats/promote_chat_member.py
index 6703cf63..0602816d 100644
--- a/pyrogram/client/methods/chats/promote_chat_member.py
+++ b/pyrogram/client/methods/chats/promote_chat_member.py
@@ -16,14 +16,16 @@
# 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 PromoteChatMember(BaseClient):
async def promote_chat_member(self,
- chat_id: int or str,
- user_id: int or str,
+ chat_id: Union[int, str],
+ user_id: Union[int, str],
can_change_info: bool = True,
can_post_messages: bool = False,
can_edit_messages: bool = False,
@@ -31,7 +33,7 @@ class PromoteChatMember(BaseClient):
can_invite_users: bool = True,
can_restrict_members: bool = True,
can_pin_messages: bool = False,
- can_promote_members: bool = False):
+ can_promote_members: bool = False) -> bool:
"""Use this method to promote or demote a user in a supergroup or a channel.
You must be an administrator in the chat for this to work and must have the appropriate admin rights.
Pass False for all boolean parameters to demote a user.
diff --git a/pyrogram/client/methods/chats/restrict_chat_member.py b/pyrogram/client/methods/chats/restrict_chat_member.py
index 1828040a..1618a588 100644
--- a/pyrogram/client/methods/chats/restrict_chat_member.py
+++ b/pyrogram/client/methods/chats/restrict_chat_member.py
@@ -16,19 +16,21 @@
# 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 RestrictChatMember(BaseClient):
async def restrict_chat_member(self,
- chat_id: int or str,
- user_id: int or str,
+ chat_id: Union[int, str],
+ user_id: Union[int, str],
until_date: int = 0,
can_send_messages: bool = False,
can_send_media_messages: bool = False,
can_send_other_messages: bool = False,
- can_add_web_page_previews: bool = False):
+ can_add_web_page_previews: bool = False) -> bool:
"""Use this method to restrict a user in a supergroup. The bot must be an administrator in the supergroup for
this to work and must have the appropriate admin rights. Pass True for all boolean parameters to lift
restrictions from a user.
diff --git a/pyrogram/client/methods/chats/set_chat_description.py b/pyrogram/client/methods/chats/set_chat_description.py
index 33ed3d13..e1541647 100644
--- a/pyrogram/client/methods/chats/set_chat_description.py
+++ b/pyrogram/client/methods/chats/set_chat_description.py
@@ -16,12 +16,16 @@
# 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 SetChatDescription(BaseClient):
- async def set_chat_description(self, chat_id: int or str, description: str):
+ async def set_chat_description(self,
+ chat_id: Union[int, str],
+ description: str) -> bool:
"""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.
diff --git a/pyrogram/client/methods/chats/set_chat_photo.py b/pyrogram/client/methods/chats/set_chat_photo.py
index dce78919..5091b3bc 100644
--- a/pyrogram/client/methods/chats/set_chat_photo.py
+++ b/pyrogram/client/methods/chats/set_chat_photo.py
@@ -19,13 +19,16 @@
import os
from base64 import b64decode
from struct import unpack
+from typing import Union
from pyrogram.api import functions, types
from ...ext import BaseClient
class SetChatPhoto(BaseClient):
- async def set_chat_photo(self, chat_id: int or str, photo: str):
+ async def set_chat_photo(self,
+ chat_id: Union[int, str],
+ photo: str) -> bool:
"""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.
diff --git a/pyrogram/client/methods/chats/set_chat_title.py b/pyrogram/client/methods/chats/set_chat_title.py
index c3f507af..4c138965 100644
--- a/pyrogram/client/methods/chats/set_chat_title.py
+++ b/pyrogram/client/methods/chats/set_chat_title.py
@@ -16,12 +16,16 @@
# 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 SetChatTitle(BaseClient):
- async def set_chat_title(self, chat_id: int or str, title: str):
+ async def set_chat_title(self,
+ chat_id: Union[int, str],
+ title: str) -> bool:
"""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.
diff --git a/pyrogram/client/methods/chats/unban_chat_member.py b/pyrogram/client/methods/chats/unban_chat_member.py
index 27a10ce2..3320eec2 100644
--- a/pyrogram/client/methods/chats/unban_chat_member.py
+++ b/pyrogram/client/methods/chats/unban_chat_member.py
@@ -16,14 +16,16 @@
# 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 UnbanChatMember(BaseClient):
async def unban_chat_member(self,
- chat_id: int or str,
- user_id: int or str):
+ chat_id: Union[int, str],
+ user_id: Union[int, str]) -> bool:
"""Use this method to unban a previously kicked user in a supergroup or channel.
The user will **not** return to the group or channel automatically, but will be able to join via link, etc.
You must be an administrator for this to work.
diff --git a/pyrogram/client/methods/chats/unpin_chat_message.py b/pyrogram/client/methods/chats/unpin_chat_message.py
index baed8cd5..fafb8a05 100644
--- a/pyrogram/client/methods/chats/unpin_chat_message.py
+++ b/pyrogram/client/methods/chats/unpin_chat_message.py
@@ -16,12 +16,15 @@
# 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 UnpinChatMessage(BaseClient):
- async def unpin_chat_message(self, chat_id: int or str):
+ async def unpin_chat_message(self,
+ chat_id: Union[int, str]) -> bool:
"""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.
diff --git a/pyrogram/client/methods/contacts/add_contacts.py b/pyrogram/client/methods/contacts/add_contacts.py
index e34dc160..622f4b8b 100644
--- a/pyrogram/client/methods/contacts/add_contacts.py
+++ b/pyrogram/client/methods/contacts/add_contacts.py
@@ -16,17 +16,21 @@
# 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 functions
from ...ext import BaseClient
class AddContacts(BaseClient):
- async def add_contacts(self, contacts: list):
+ async def add_contacts(self,
+ contacts: List["pyrogram.InputPhoneContact"]):
"""Use this method to add contacts to your Telegram address book.
Args:
- contacts (``list``):
- A list of :obj:`InputPhoneContact `
+ contacts (List of :obj:`InputPhoneContact `):
+ The contact list to be added
Returns:
On success, the added contacts are returned.
diff --git a/pyrogram/client/methods/contacts/delete_contacts.py b/pyrogram/client/methods/contacts/delete_contacts.py
index 262af19c..af1c58fb 100644
--- a/pyrogram/client/methods/contacts/delete_contacts.py
+++ b/pyrogram/client/methods/contacts/delete_contacts.py
@@ -16,17 +16,20 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
+from typing import List
+
from pyrogram.api import functions, types
from pyrogram.api.errors import PeerIdInvalid
from ...ext import BaseClient
class DeleteContacts(BaseClient):
- async def delete_contacts(self, ids: list):
+ async def delete_contacts(self,
+ ids: List[int]):
"""Use this method to delete contacts from your Telegram address book
Args:
- ids (``list``):
+ ids (List of ``int``):
A list of unique identifiers for the target users.
Can be an ID (int), a username (string) or phone number (string).
diff --git a/pyrogram/client/methods/decorators/on_callback_query.py b/pyrogram/client/methods/decorators/on_callback_query.py
index 51a6df2e..8c152706 100644
--- a/pyrogram/client/methods/decorators/on_callback_query.py
+++ b/pyrogram/client/methods/decorators/on_callback_query.py
@@ -16,13 +16,18 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
+from typing import Tuple
+
import pyrogram
from pyrogram.client.filters.filter import Filter
+from pyrogram.client.handlers.handler import Handler
from ...ext import BaseClient
class OnCallbackQuery(BaseClient):
- def on_callback_query(self=None, filters=None, group: int = 0):
+ def on_callback_query(self=None,
+ filters=None,
+ group: int = 0) -> callable:
"""Use this decorator to automatically register a function for handling
callback queries. This does the same thing as :meth:`add_handler` using the
:class:`CallbackQueryHandler`.
@@ -43,7 +48,7 @@ class OnCallbackQuery(BaseClient):
The group identifier, defaults to 0.
"""
- def decorator(func):
+ def decorator(func: callable) -> Tuple[Handler, int]:
if isinstance(func, tuple):
func = func[0].callback
diff --git a/pyrogram/client/methods/decorators/on_deleted_messages.py b/pyrogram/client/methods/decorators/on_deleted_messages.py
index c23b7594..84abc92e 100644
--- a/pyrogram/client/methods/decorators/on_deleted_messages.py
+++ b/pyrogram/client/methods/decorators/on_deleted_messages.py
@@ -16,13 +16,18 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
+from typing import Tuple
+
import pyrogram
from pyrogram.client.filters.filter import Filter
+from pyrogram.client.handlers.handler import Handler
from ...ext import BaseClient
class OnDeletedMessages(BaseClient):
- def on_deleted_messages(self=None, filters=None, group: int = 0):
+ def on_deleted_messages(self=None,
+ filters=None,
+ group: int = 0) -> callable:
"""Use this decorator to automatically register a function for handling
deleted messages. This does the same thing as :meth:`add_handler` using the
:class:`DeletedMessagesHandler`.
@@ -43,7 +48,7 @@ class OnDeletedMessages(BaseClient):
The group identifier, defaults to 0.
"""
- def decorator(func):
+ def decorator(func: callable) -> Tuple[Handler, int]:
if isinstance(func, tuple):
func = func[0].callback
diff --git a/pyrogram/client/methods/decorators/on_disconnect.py b/pyrogram/client/methods/decorators/on_disconnect.py
index e2288619..56796bf5 100644
--- a/pyrogram/client/methods/decorators/on_disconnect.py
+++ b/pyrogram/client/methods/decorators/on_disconnect.py
@@ -17,17 +17,18 @@
# along with Pyrogram. If not, see .
import pyrogram
+from pyrogram.client.handlers.handler import Handler
from ...ext import BaseClient
class OnDisconnect(BaseClient):
- def on_disconnect(self=None):
+ def on_disconnect(self=None) -> callable:
"""Use this decorator to automatically register a function for handling
disconnections. This does the same thing as :meth:`add_handler` using the
:class:`DisconnectHandler`.
"""
- def decorator(func):
+ def decorator(func: callable) -> Handler:
handler = pyrogram.DisconnectHandler(func)
if self is not None:
diff --git a/pyrogram/client/methods/decorators/on_message.py b/pyrogram/client/methods/decorators/on_message.py
index a098cfa2..68ed1fab 100644
--- a/pyrogram/client/methods/decorators/on_message.py
+++ b/pyrogram/client/methods/decorators/on_message.py
@@ -22,7 +22,9 @@ from ...ext import BaseClient
class OnMessage(BaseClient):
- def on_message(self=None, filters=None, group: int = 0):
+ def on_message(self=None,
+ filters=None,
+ group: int = 0) -> callable:
"""Use this decorator to automatically register a function for handling
messages. This does the same thing as :meth:`add_handler` using the
:class:`MessageHandler`.
diff --git a/pyrogram/client/methods/decorators/on_raw_update.py b/pyrogram/client/methods/decorators/on_raw_update.py
index 52728e1c..ce2584d5 100644
--- a/pyrogram/client/methods/decorators/on_raw_update.py
+++ b/pyrogram/client/methods/decorators/on_raw_update.py
@@ -16,12 +16,16 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
+from typing import Tuple
+
import pyrogram
+from pyrogram.client.handlers.handler import Handler
from ...ext import BaseClient
class OnRawUpdate(BaseClient):
- def on_raw_update(self=None, group: int = 0):
+ def on_raw_update(self=None,
+ group: int = 0) -> callable:
"""Use this decorator to automatically register a function for handling
raw updates. This does the same thing as :meth:`add_handler` using the
:class:`RawUpdateHandler`.
@@ -38,7 +42,7 @@ class OnRawUpdate(BaseClient):
The group identifier, defaults to 0.
"""
- def decorator(func):
+ def decorator(func: callable) -> Tuple[Handler, int]:
if isinstance(func, tuple):
func = func[0].callback
diff --git a/pyrogram/client/methods/decorators/on_user_status.py b/pyrogram/client/methods/decorators/on_user_status.py
index 2ca41e56..c552e706 100644
--- a/pyrogram/client/methods/decorators/on_user_status.py
+++ b/pyrogram/client/methods/decorators/on_user_status.py
@@ -16,13 +16,18 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
+from typing import Tuple
+
import pyrogram
from pyrogram.client.filters.filter import Filter
+from pyrogram.client.handlers.handler import Handler
from ...ext import BaseClient
class OnUserStatus(BaseClient):
- def on_user_status(self=None, filters=None, group: int = 0):
+ def on_user_status(self=None,
+ filters=None,
+ group: int = 0) -> callable:
"""Use this decorator to automatically register a function for handling
user status updates. This does the same thing as :meth:`add_handler` using the
:class:`UserStatusHandler`.
@@ -42,7 +47,7 @@ class OnUserStatus(BaseClient):
The group identifier, defaults to 0.
"""
- def decorator(func):
+ def decorator(func: callable) -> Tuple[Handler, int]:
if isinstance(func, tuple):
func = func[0].callback
diff --git a/pyrogram/client/methods/messages/delete_messages.py b/pyrogram/client/methods/messages/delete_messages.py
index 4ef19d35..96e52ba1 100644
--- a/pyrogram/client/methods/messages/delete_messages.py
+++ b/pyrogram/client/methods/messages/delete_messages.py
@@ -16,15 +16,17 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
+from typing import Union, Iterable
+
from pyrogram.api import functions, types
from pyrogram.client.ext import BaseClient
class DeleteMessages(BaseClient):
async def delete_messages(self,
- chat_id: int or str,
- message_ids,
- revoke: bool = True):
+ chat_id: Union[int, str],
+ message_ids: Iterable[int],
+ revoke: bool = True) -> bool:
"""Use this method to delete messages, including service messages, with the following limitations:
- A message can only be deleted if it was sent less than 48 hours ago.
diff --git a/pyrogram/client/methods/messages/edit_message_caption.py b/pyrogram/client/methods/messages/edit_message_caption.py
index 5cc075b9..cc950bf6 100644
--- a/pyrogram/client/methods/messages/edit_message_caption.py
+++ b/pyrogram/client/methods/messages/edit_message_caption.py
@@ -16,17 +16,20 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
+from typing import Union
+
+import pyrogram
from pyrogram.api import functions, types
-from pyrogram.client.ext import BaseClient, utils
+from pyrogram.client.ext import BaseClient
class EditMessageCaption(BaseClient):
async def edit_message_caption(self,
- chat_id: int or str,
+ chat_id: Union[int, str],
message_id: int,
caption: str,
parse_mode: str = "",
- reply_markup=None):
+ reply_markup: "pyrogram.InlineKeyboardMarkup" = None) -> "pyrogram.Message":
"""Use this method to edit captions of messages.
Args:
@@ -68,7 +71,7 @@ class EditMessageCaption(BaseClient):
for i in r.updates:
if isinstance(i, (types.UpdateEditMessage, types.UpdateEditChannelMessage)):
- return await utils.parse_messages(
+ return await pyrogram.Message._parse(
self, i.message,
{i.id: i for i in r.users},
{i.id: i for i in r.chats}
diff --git a/pyrogram/client/methods/messages/edit_message_media.py b/pyrogram/client/methods/messages/edit_message_media.py
index 6c512312..6c87ead8 100644
--- a/pyrogram/client/methods/messages/edit_message_media.py
+++ b/pyrogram/client/methods/messages/edit_message_media.py
@@ -20,7 +20,9 @@ import binascii
import mimetypes
import os
import struct
+from typing import Union
+import pyrogram
from pyrogram.api import functions, types
from pyrogram.api.errors import FileIdInvalid
from pyrogram.client.ext import BaseClient, utils
@@ -28,14 +30,15 @@ from pyrogram.client.types import (
InputMediaPhoto, InputMediaVideo, InputMediaAudio,
InputMediaAnimation, InputMediaDocument
)
+from pyrogram.client.types.input_media import InputMedia
class EditMessageMedia(BaseClient):
async def edit_message_media(self,
- chat_id: int or str,
+ chat_id: Union[int, str],
message_id: int,
- media,
- reply_markup=None):
+ media: InputMedia,
+ reply_markup: "pyrogram.InlineKeyboardMarkup" = None) -> "pyrogram.Message":
"""Use this method to edit audio, document, photo, or video messages.
If a message is a part of a message album, then it can be edited only to a photo or a video. Otherwise,
@@ -333,7 +336,7 @@ class EditMessageMedia(BaseClient):
for i in r.updates:
if isinstance(i, (types.UpdateEditMessage, types.UpdateEditChannelMessage)):
- return await utils.parse_messages(
+ return await pyrogram.Message._parse(
self, i.message,
{i.id: i for i in r.users},
{i.id: i for i in r.chats}
diff --git a/pyrogram/client/methods/messages/edit_message_reply_markup.py b/pyrogram/client/methods/messages/edit_message_reply_markup.py
index 9a83d88a..f57ee31d 100644
--- a/pyrogram/client/methods/messages/edit_message_reply_markup.py
+++ b/pyrogram/client/methods/messages/edit_message_reply_markup.py
@@ -16,15 +16,18 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
+from typing import Union
+
+import pyrogram
from pyrogram.api import functions, types
-from pyrogram.client.ext import BaseClient, utils
+from pyrogram.client.ext import BaseClient
class EditMessageReplyMarkup(BaseClient):
async def edit_message_reply_markup(self,
- chat_id: int or str,
+ chat_id: Union[int, str],
message_id: int,
- reply_markup=None):
+ reply_markup: "pyrogram.InlineKeyboardMarkup" = None) -> "pyrogram.Message":
"""Use this method to edit only the reply markup of messages sent by the bot or via the bot (for inline bots).
Args:
@@ -57,7 +60,7 @@ class EditMessageReplyMarkup(BaseClient):
for i in r.updates:
if isinstance(i, (types.UpdateEditMessage, types.UpdateEditChannelMessage)):
- return await utils.parse_messages(
+ return await pyrogram.Message._parse(
self, i.message,
{i.id: i for i in r.users},
{i.id: i for i in r.chats}
diff --git a/pyrogram/client/methods/messages/edit_message_text.py b/pyrogram/client/methods/messages/edit_message_text.py
index fbae8d08..522ada9c 100644
--- a/pyrogram/client/methods/messages/edit_message_text.py
+++ b/pyrogram/client/methods/messages/edit_message_text.py
@@ -16,18 +16,21 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
+from typing import Union
+
+import pyrogram
from pyrogram.api import functions, types
-from pyrogram.client.ext import BaseClient, utils
+from pyrogram.client.ext import BaseClient
class EditMessageText(BaseClient):
async def edit_message_text(self,
- chat_id: int or str,
+ chat_id: Union[int, str],
message_id: int,
text: str,
parse_mode: str = "",
disable_web_page_preview: bool = None,
- reply_markup=None):
+ reply_markup: "pyrogram.InlineKeyboardMarkup" = None) -> "pyrogram.Message":
"""Use this method to edit text messages.
Args:
@@ -73,7 +76,7 @@ class EditMessageText(BaseClient):
for i in r.updates:
if isinstance(i, (types.UpdateEditMessage, types.UpdateEditChannelMessage)):
- return await utils.parse_messages(
+ return await pyrogram.Message._parse(
self, i.message,
{i.id: i for i in r.users},
{i.id: i for i in r.chats}
diff --git a/pyrogram/client/methods/messages/forward_messages.py b/pyrogram/client/methods/messages/forward_messages.py
index f0626fbb..b79b1bcc 100644
--- a/pyrogram/client/methods/messages/forward_messages.py
+++ b/pyrogram/client/methods/messages/forward_messages.py
@@ -16,16 +16,19 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
+from typing import Union, Iterable
+
+import pyrogram
from pyrogram.api import functions, types
-from ...ext import BaseClient, utils
+from ...ext import BaseClient
class ForwardMessages(BaseClient):
async def forward_messages(self,
- chat_id: int or str,
- from_chat_id: int or str,
- message_ids,
- disable_notification: bool = None):
+ chat_id: Union[int, str],
+ from_chat_id: Union[int, str],
+ message_ids: Iterable[int],
+ disable_notification: bool = None) -> "pyrogram.Messages":
"""Use this method to forward messages of any kind.
Args:
@@ -48,7 +51,7 @@ class ForwardMessages(BaseClient):
Users will receive a notification with no sound.
Returns:
- On success and in case *message_ids* was a list, the returned value will be a list of the forwarded
+ On success and in case *message_ids* was an iterable, the returned value will be a list of the forwarded
:obj:`Messages ` even if a list contains just one element, otherwise if
*message_ids* was an integer, the single forwarded :obj:`Message `
is returned.
@@ -77,10 +80,14 @@ class ForwardMessages(BaseClient):
for i in r.updates:
if isinstance(i, (types.UpdateNewMessage, types.UpdateNewChannelMessage)):
messages.append(
- await utils.parse_messages(
+ await pyrogram.Message._parse(
self, i.message,
users, chats
)
)
- return messages if is_iterable else messages[0]
+ return pyrogram.Messages(
+ client=self,
+ total_count=len(messages),
+ messages=messages
+ ) if is_iterable else messages[0]
diff --git a/pyrogram/client/methods/messages/get_history.py b/pyrogram/client/methods/messages/get_history.py
index bf012323..46b70d28 100644
--- a/pyrogram/client/methods/messages/get_history.py
+++ b/pyrogram/client/methods/messages/get_history.py
@@ -16,14 +16,16 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
+from typing import Union
+
import pyrogram
from pyrogram.api import functions
-from ...ext import BaseClient, utils
+from ...ext import BaseClient
class GetHistory(BaseClient):
async def get_history(self,
- chat_id: int or str,
+ chat_id: Union[int, str],
offset: int = 0,
limit: int = 100,
offset_id: int = 0,
@@ -59,52 +61,18 @@ class GetHistory(BaseClient):
:class:`Error ` in case of a Telegram RPC error.
"""
- r = await self.send(
- functions.messages.GetHistory(
- peer=await self.resolve_peer(chat_id),
- offset_id=offset_id,
- offset_date=offset_date,
- add_offset=offset,
- limit=limit,
- max_id=0,
- min_id=0,
- hash=0
+ return await pyrogram.Messages._parse(
+ self,
+ await self.send(
+ functions.messages.GetHistory(
+ peer=await self.resolve_peer(chat_id),
+ offset_id=offset_id,
+ offset_date=offset_date,
+ add_offset=offset,
+ limit=limit,
+ max_id=0,
+ min_id=0,
+ hash=0
+ )
)
)
-
- users = {i.id: i for i in r.users}
- chats = {i.id: i for i in r.chats}
-
- reply_to_messages = {
- i.reply_to_msg_id: None
- for i in r.messages
- if i.reply_to_msg_id
- }
-
- if reply_to_messages:
- temp = await self.get_messages(
- chat_id, reply_to_messages,
- replies=0
- )
-
- assert len(temp) == len(reply_to_messages)
-
- for i in range(len(temp)):
- reply_to_messages[temp[i].message_id] = temp[i]
-
- messages = await utils.parse_messages(
- self, r.messages,
- users, chats,
- replies=0
- )
-
- assert len(messages) == len(r.messages)
-
- for i in range(len(messages)):
- if r.messages[i].reply_to_msg_id:
- messages[i].reply_to_message = reply_to_messages[r.messages[i].reply_to_msg_id]
-
- return pyrogram.Messages(
- total_count=getattr(r, "count", len(r.messages)),
- messages=messages
- )
diff --git a/pyrogram/client/methods/messages/get_messages.py b/pyrogram/client/methods/messages/get_messages.py
index dae1df09..edcad039 100644
--- a/pyrogram/client/methods/messages/get_messages.py
+++ b/pyrogram/client/methods/messages/get_messages.py
@@ -16,16 +16,19 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
+from typing import Union, Iterable
+
+import pyrogram
from pyrogram.api import functions, types
-from ...ext import BaseClient, utils
+from ...ext import BaseClient
class GetMessages(BaseClient):
async def get_messages(self,
- chat_id: int or str,
- message_ids: int or list = None,
- reply_to_message_ids: int or list = None,
- replies: int = 1):
+ chat_id: Union[int, str],
+ message_ids: Union[int, Iterable[int]] = None,
+ reply_to_message_ids: Union[int, Iterable[int]] = None,
+ replies: int = 1) -> "pyrogram.Messages":
"""Use this method to get one or more messages that belong to a specific chat.
You can retrieve up to 200 messages at once.
@@ -48,10 +51,9 @@ class GetMessages(BaseClient):
The number of subsequent replies to get for each message. Defaults to 1.
Returns:
- On success and in case *message_ids* or *reply_to_message_ids* was a list, the returned value will be a
- list of the requested :obj:`Messages ` even if a list contains just one element,
- otherwise if *message_ids* or *reply_to_message_ids* was an integer, the single requested
- :obj:`Message ` is returned.
+ On success and in case *message_ids* or *reply_to_message_ids* was an iterable, the returned value will be a
+ :obj:`Messages ` even if a list contains just one element. Otherwise, if *message_ids* or
+ *reply_to_message_ids* was an integer, the single requested :obj:`Message ` is returned.
Raises:
:class:`Error ` in case of a Telegram RPC error.
@@ -76,13 +78,6 @@ class GetMessages(BaseClient):
else:
rpc = functions.messages.GetMessages(id=ids)
- r = await self.send(rpc)
+ messages = await pyrogram.Messages._parse(self, self.send(rpc))
- messages = await utils.parse_messages(
- self, r.messages,
- {i.id: i for i in r.users},
- {i.id: i for i in r.chats},
- replies=replies
- )
-
- return messages if is_iterable else messages[0]
+ return messages if is_iterable else messages.messages[0]
diff --git a/pyrogram/client/methods/messages/send_animation.py b/pyrogram/client/methods/messages/send_animation.py
index 5c696803..923a1fbf 100644
--- a/pyrogram/client/methods/messages/send_animation.py
+++ b/pyrogram/client/methods/messages/send_animation.py
@@ -20,7 +20,9 @@ import binascii
import mimetypes
import os
import struct
+from typing import Union
+import pyrogram
from pyrogram.api import functions, types
from pyrogram.api.errors import FileIdInvalid, FilePartMissing
from pyrogram.client.ext import BaseClient, utils
@@ -28,7 +30,7 @@ from pyrogram.client.ext import BaseClient, utils
class SendAnimation(BaseClient):
async def send_animation(self,
- chat_id: int or str,
+ chat_id: Union[int, str],
animation: str,
caption: str = "",
parse_mode: str = "",
@@ -38,9 +40,12 @@ class SendAnimation(BaseClient):
thumb: str = None,
disable_notification: bool = None,
reply_to_message_id: int = None,
- reply_markup=None,
+ reply_markup: Union["pyrogram.InlineKeyboardMarkup",
+ "pyrogram.ReplyKeyboardMarkup",
+ "pyrogram.ReplyKeyboardRemove",
+ "pyrogram.ForceReply"] = None,
progress: callable = None,
- progress_args: tuple = ()):
+ progress_args: tuple = ()) -> "pyrogram.Message":
"""Use this method to send animation files (animation or H.264/MPEG-4 AVC video without sound).
Args:
@@ -184,7 +189,7 @@ class SendAnimation(BaseClient):
else:
for i in r.updates:
if isinstance(i, (types.UpdateNewMessage, types.UpdateNewChannelMessage)):
- return await utils.parse_messages(
+ return await pyrogram.Message._parse(
self, i.message,
{i.id: i for i in r.users},
{i.id: i for i in r.chats}
diff --git a/pyrogram/client/methods/messages/send_audio.py b/pyrogram/client/methods/messages/send_audio.py
index b7df78fa..5c949e59 100644
--- a/pyrogram/client/methods/messages/send_audio.py
+++ b/pyrogram/client/methods/messages/send_audio.py
@@ -20,7 +20,9 @@ import binascii
import mimetypes
import os
import struct
+from typing import Union
+import pyrogram
from pyrogram.api import functions, types
from pyrogram.api.errors import FileIdInvalid, FilePartMissing
from pyrogram.client.ext import BaseClient, utils
@@ -28,18 +30,21 @@ from pyrogram.client.ext import BaseClient, utils
class SendAudio(BaseClient):
async def send_audio(self,
- chat_id: int or str,
+ chat_id: Union[int, str],
audio: str,
caption: str = "",
parse_mode: str = "",
duration: int = 0,
performer: str = None,
title: str = None,
- thumb: str = None,disable_notification: bool = None,
+ thumb: str = None, disable_notification: bool = None,
reply_to_message_id: int = None,
- reply_markup=None,
+ reply_markup: Union["pyrogram.InlineKeyboardMarkup",
+ "pyrogram.ReplyKeyboardMarkup",
+ "pyrogram.ReplyKeyboardRemove",
+ "pyrogram.ForceReply"] = None,
progress: callable = None,
- progress_args: tuple = ()):
+ progress_args: tuple = ()) -> "pyrogram.Message":
"""Use this method to send audio files.
For sending voice messages, use the :obj:`send_voice()` method instead.
@@ -183,7 +188,7 @@ class SendAudio(BaseClient):
else:
for i in r.updates:
if isinstance(i, (types.UpdateNewMessage, types.UpdateNewChannelMessage)):
- return await utils.parse_messages(
+ return await pyrogram.Message._parse(
self, i.message,
{i.id: i for i in r.users},
{i.id: i for i in r.chats}
diff --git a/pyrogram/client/methods/messages/send_chat_action.py b/pyrogram/client/methods/messages/send_chat_action.py
index ed12ce67..21ff3032 100644
--- a/pyrogram/client/methods/messages/send_chat_action.py
+++ b/pyrogram/client/methods/messages/send_chat_action.py
@@ -16,14 +16,16 @@
# 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
from pyrogram.client.ext import BaseClient, ChatAction
class SendChatAction(BaseClient):
async def send_chat_action(self,
- chat_id: int or str,
- action: ChatAction or str,
+ chat_id: Union[int, str],
+ action: Union[ChatAction, str],
progress: int = 0):
"""Use this method when you need to tell the other party that something is happening on your side.
diff --git a/pyrogram/client/methods/messages/send_contact.py b/pyrogram/client/methods/messages/send_contact.py
index 67330dfd..2105e550 100644
--- a/pyrogram/client/methods/messages/send_contact.py
+++ b/pyrogram/client/methods/messages/send_contact.py
@@ -16,19 +16,25 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
+from typing import Union
+
+import pyrogram
from pyrogram.api import functions, types
-from pyrogram.client.ext import BaseClient, utils
+from pyrogram.client.ext import BaseClient
class SendContact(BaseClient):
async def send_contact(self,
- chat_id: int or str,
+ chat_id: Union[int, str],
phone_number: str,
first_name: str,
last_name: str = "",
vcard: str = "", disable_notification: bool = None,
reply_to_message_id: int = None,
- reply_markup=None):
+ reply_markup: Union["pyrogram.InlineKeyboardMarkup",
+ "pyrogram.ReplyKeyboardMarkup",
+ "pyrogram.ReplyKeyboardRemove",
+ "pyrogram.ForceReply"] = None) -> "pyrogram.Message":
"""Use this method to send phone contacts.
Args:
@@ -85,7 +91,7 @@ class SendContact(BaseClient):
for i in r.updates:
if isinstance(i, (types.UpdateNewMessage, types.UpdateNewChannelMessage)):
- return await utils.parse_messages(
+ return await pyrogram.Message._parse(
self, i.message,
{i.id: i for i in r.users},
{i.id: i for i in r.chats}
diff --git a/pyrogram/client/methods/messages/send_document.py b/pyrogram/client/methods/messages/send_document.py
index 53e825f2..2dfc0c8b 100644
--- a/pyrogram/client/methods/messages/send_document.py
+++ b/pyrogram/client/methods/messages/send_document.py
@@ -20,7 +20,9 @@ import binascii
import mimetypes
import os
import struct
+from typing import Union
+import pyrogram
from pyrogram.api import functions, types
from pyrogram.api.errors import FileIdInvalid, FilePartMissing
from pyrogram.client.ext import BaseClient, utils
@@ -28,15 +30,18 @@ from pyrogram.client.ext import BaseClient, utils
class SendDocument(BaseClient):
async def send_document(self,
- chat_id: int or str,
+ chat_id: Union[int, str],
document: str,
- thumb: str = None,caption: str = "",
+ thumb: str = None, caption: str = "",
parse_mode: str = "",
disable_notification: bool = None,
reply_to_message_id: int = None,
- reply_markup=None,
+ reply_markup: Union["pyrogram.InlineKeyboardMarkup",
+ "pyrogram.ReplyKeyboardMarkup",
+ "pyrogram.ReplyKeyboardRemove",
+ "pyrogram.ForceReply"] = None,
progress: callable = None,
- progress_args: tuple = ()):
+ progress_args: tuple = ()) -> "pyrogram.Message":
"""Use this method to send general files.
Args:
@@ -164,7 +169,7 @@ class SendDocument(BaseClient):
else:
for i in r.updates:
if isinstance(i, (types.UpdateNewMessage, types.UpdateNewChannelMessage)):
- return await utils.parse_messages(
+ return await pyrogram.Message._parse(
self, i.message,
{i.id: i for i in r.users},
{i.id: i for i in r.chats}
diff --git a/pyrogram/client/methods/messages/send_location.py b/pyrogram/client/methods/messages/send_location.py
index 565a7773..88aeb7d9 100644
--- a/pyrogram/client/methods/messages/send_location.py
+++ b/pyrogram/client/methods/messages/send_location.py
@@ -16,18 +16,24 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
+from typing import Union
+
+import pyrogram
from pyrogram.api import functions, types
-from pyrogram.client.ext import BaseClient, utils
+from pyrogram.client.ext import BaseClient
class SendLocation(BaseClient):
async def send_location(self,
- chat_id: int or str,
+ chat_id: Union[int, str],
latitude: float,
longitude: float,
disable_notification: bool = None,
reply_to_message_id: int = None,
- reply_markup=None):
+ reply_markup: Union["pyrogram.InlineKeyboardMarkup",
+ "pyrogram.ReplyKeyboardMarkup",
+ "pyrogram.ReplyKeyboardRemove",
+ "pyrogram.ForceReply"] = None) -> "pyrogram.Message":
"""Use this method to send points on the map.
Args:
@@ -78,7 +84,7 @@ class SendLocation(BaseClient):
for i in r.updates:
if isinstance(i, (types.UpdateNewMessage, types.UpdateNewChannelMessage)):
- return await utils.parse_messages(
+ return await pyrogram.Message._parse(
self, i.message,
{i.id: i for i in r.users},
{i.id: i for i in r.chats}
diff --git a/pyrogram/client/methods/messages/send_media_group.py b/pyrogram/client/methods/messages/send_media_group.py
index 0f045277..68783cfe 100644
--- a/pyrogram/client/methods/messages/send_media_group.py
+++ b/pyrogram/client/methods/messages/send_media_group.py
@@ -20,10 +20,11 @@ import binascii
import mimetypes
import os
import struct
+from typing import Union, List
+import pyrogram
from pyrogram.api import functions, types
from pyrogram.api.errors import FileIdInvalid
-from pyrogram.client import types as pyrogram_types
from pyrogram.client.ext import BaseClient, utils
@@ -32,8 +33,8 @@ class SendMediaGroup(BaseClient):
# TODO: Return new Message object
# TODO: Figure out how to send albums using URLs
async def send_media_group(self,
- chat_id: int or str,
- media: list,
+ chat_id: Union[int, str],
+ media: List[Union["pyrogram.InputMediaPhoto", "pyrogram.InputMediaVideo"]],
disable_notification: bool = None,
reply_to_message_id: int = None):
"""Use this method to send a group of photos or videos as an album.
@@ -62,7 +63,7 @@ class SendMediaGroup(BaseClient):
for i in media:
style = self.html if i.parse_mode.lower() == "html" else self.markdown
- if isinstance(i, pyrogram_types.InputMediaPhoto):
+ if isinstance(i, pyrogram.InputMediaPhoto):
if os.path.exists(i.media):
media = await self.send(
functions.messages.UploadMedia(
@@ -101,7 +102,7 @@ class SendMediaGroup(BaseClient):
access_hash=unpacked[3]
)
)
- elif isinstance(i, pyrogram_types.InputMediaVideo):
+ elif isinstance(i, pyrogram.InputMediaVideo):
if os.path.exists(i.media):
media = await self.send(
functions.messages.UploadMedia(
diff --git a/pyrogram/client/methods/messages/send_message.py b/pyrogram/client/methods/messages/send_message.py
index ebea756a..3251ece6 100644
--- a/pyrogram/client/methods/messages/send_message.py
+++ b/pyrogram/client/methods/messages/send_message.py
@@ -16,20 +16,25 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
+from typing import Union
+
+import pyrogram
from pyrogram.api import functions, types
-from pyrogram.client import types as pyrogram_types
-from ...ext import utils, BaseClient
+from ...ext import BaseClient
class SendMessage(BaseClient):
async def send_message(self,
- chat_id: int or str,
+ chat_id: Union[int, str],
text: str,
parse_mode: str = "",
disable_web_page_preview: bool = None,
disable_notification: bool = None,
reply_to_message_id: int = None,
- reply_markup=None):
+ reply_markup: Union["pyrogram.InlineKeyboardMarkup",
+ "pyrogram.ReplyKeyboardMarkup",
+ "pyrogram.ReplyKeyboardRemove",
+ "pyrogram.ForceReply"] = None) -> "pyrogram.Message":
"""Use this method to send text messages.
Args:
@@ -83,9 +88,13 @@ class SendMessage(BaseClient):
)
if isinstance(r, types.UpdateShortSentMessage):
- return pyrogram_types.Message(
+ return pyrogram.Message(
message_id=r.id,
- chat=pyrogram_types.Chat(id=list((await self.resolve_peer(chat_id)).__dict__.values())[0], type="private"),
+ chat=pyrogram.Chat(
+ id=list((await self.resolve_peer(chat_id)).__dict__.values())[0],
+ type="private",
+ client=self
+ ),
text=message,
date=r.date,
outgoing=r.out,
@@ -95,7 +104,7 @@ class SendMessage(BaseClient):
for i in r.updates:
if isinstance(i, (types.UpdateNewMessage, types.UpdateNewChannelMessage)):
- return await utils.parse_messages(
+ return await pyrogram.Message._parse(
self, i.message,
{i.id: i for i in r.users},
{i.id: i for i in r.chats}
diff --git a/pyrogram/client/methods/messages/send_photo.py b/pyrogram/client/methods/messages/send_photo.py
index 5edd89bf..aeeffa62 100644
--- a/pyrogram/client/methods/messages/send_photo.py
+++ b/pyrogram/client/methods/messages/send_photo.py
@@ -19,7 +19,9 @@
import binascii
import os
import struct
+from typing import Union
+import pyrogram
from pyrogram.api import functions, types
from pyrogram.api.errors import FileIdInvalid, FilePartMissing
from pyrogram.client.ext import BaseClient, utils
@@ -27,16 +29,19 @@ from pyrogram.client.ext import BaseClient, utils
class SendPhoto(BaseClient):
async def send_photo(self,
- chat_id: int or str,
+ chat_id: Union[int, str],
photo: str,
caption: str = "",
parse_mode: str = "",
ttl_seconds: int = None,
disable_notification: bool = None,
reply_to_message_id: int = None,
- reply_markup=None,
+ reply_markup: Union["pyrogram.InlineKeyboardMarkup",
+ "pyrogram.ReplyKeyboardMarkup",
+ "pyrogram.ReplyKeyboardRemove",
+ "pyrogram.ForceReply"] = None,
progress: callable = None,
- progress_args: tuple = ()):
+ progress_args: tuple = ()) -> "pyrogram.Message":
"""Use this method to send photos.
Args:
@@ -160,7 +165,7 @@ class SendPhoto(BaseClient):
else:
for i in r.updates:
if isinstance(i, (types.UpdateNewMessage, types.UpdateNewChannelMessage)):
- return await utils.parse_messages(
+ return await pyrogram.Message._parse(
self, i.message,
{i.id: i for i in r.users},
{i.id: i for i in r.chats}
diff --git a/pyrogram/client/methods/messages/send_sticker.py b/pyrogram/client/methods/messages/send_sticker.py
index 411c634b..688ee87b 100644
--- a/pyrogram/client/methods/messages/send_sticker.py
+++ b/pyrogram/client/methods/messages/send_sticker.py
@@ -19,7 +19,9 @@
import binascii
import os
import struct
+from typing import Union
+import pyrogram
from pyrogram.api import functions, types
from pyrogram.api.errors import FileIdInvalid, FilePartMissing
from pyrogram.client.ext import BaseClient, utils
@@ -27,13 +29,16 @@ from pyrogram.client.ext import BaseClient, utils
class SendSticker(BaseClient):
async def send_sticker(self,
- chat_id: int or str,
+ chat_id: Union[int, str],
sticker: str,
disable_notification: bool = None,
reply_to_message_id: int = None,
- reply_markup=None,
+ reply_markup: Union["pyrogram.InlineKeyboardMarkup",
+ "pyrogram.ReplyKeyboardMarkup",
+ "pyrogram.ReplyKeyboardRemove",
+ "pyrogram.ForceReply"] = None,
progress: callable = None,
- progress_args: tuple = ()):
+ progress_args: tuple = ()) -> "pyrogram.Message":
"""Use this method to send .webp stickers.
Args:
@@ -144,7 +149,7 @@ class SendSticker(BaseClient):
else:
for i in r.updates:
if isinstance(i, (types.UpdateNewMessage, types.UpdateNewChannelMessage)):
- return await utils.parse_messages(
+ return await pyrogram.Message._parse(
self, i.message,
{i.id: i for i in r.users},
{i.id: i for i in r.chats}
diff --git a/pyrogram/client/methods/messages/send_venue.py b/pyrogram/client/methods/messages/send_venue.py
index 4bdf0935..36da7e18 100644
--- a/pyrogram/client/methods/messages/send_venue.py
+++ b/pyrogram/client/methods/messages/send_venue.py
@@ -16,21 +16,27 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
+from typing import Union
+
+import pyrogram
from pyrogram.api import functions, types
-from pyrogram.client.ext import BaseClient, utils
+from pyrogram.client.ext import BaseClient
class SendVenue(BaseClient):
async def send_venue(self,
- chat_id: int or str,
- latitude: float,
- longitude: float,
- title: str,
- address: str,
- foursquare_id: str = "",
- foursquare_type: str = "",disable_notification: bool = None,
- reply_to_message_id: int = None,
- reply_markup=None):
+ chat_id: Union[int, str],
+ latitude: float,
+ longitude: float,
+ title: str,
+ address: str,
+ foursquare_id: str = "",
+ foursquare_type: str = "", disable_notification: bool = None,
+ reply_to_message_id: int = None,
+ reply_markup: Union["pyrogram.InlineKeyboardMarkup",
+ "pyrogram.ReplyKeyboardMarkup",
+ "pyrogram.ReplyKeyboardRemove",
+ "pyrogram.ForceReply"] = None) -> "pyrogram.Message":
"""Use this method to send information about a venue.
Args:
@@ -99,7 +105,7 @@ class SendVenue(BaseClient):
for i in r.updates:
if isinstance(i, (types.UpdateNewMessage, types.UpdateNewChannelMessage)):
- return await utils.parse_messages(
+ return await pyrogram.Message._parse(
self, i.message,
{i.id: i for i in r.users},
{i.id: i for i in r.chats}
diff --git a/pyrogram/client/methods/messages/send_video.py b/pyrogram/client/methods/messages/send_video.py
index 387b37fd..7f11ba5b 100644
--- a/pyrogram/client/methods/messages/send_video.py
+++ b/pyrogram/client/methods/messages/send_video.py
@@ -20,7 +20,9 @@ import binascii
import mimetypes
import os
import struct
+from typing import Union
+import pyrogram
from pyrogram.api import functions, types
from pyrogram.api.errors import FileIdInvalid, FilePartMissing
from pyrogram.client.ext import BaseClient, utils
@@ -28,7 +30,7 @@ from pyrogram.client.ext import BaseClient, utils
class SendVideo(BaseClient):
async def send_video(self,
- chat_id: int or str,
+ chat_id: Union[int, str],
video: str,
caption: str = "",
parse_mode: str = "",
@@ -39,9 +41,12 @@ class SendVideo(BaseClient):
supports_streaming: bool = True,
disable_notification: bool = None,
reply_to_message_id: int = None,
- reply_markup=None,
+ reply_markup: Union["pyrogram.InlineKeyboardMarkup",
+ "pyrogram.ReplyKeyboardMarkup",
+ "pyrogram.ReplyKeyboardRemove",
+ "pyrogram.ForceReply"] = None,
progress: callable = None,
- progress_args: tuple = ()):
+ progress_args: tuple = ()) -> "pyrogram.Message":
"""Use this method to send video files.
Args:
@@ -187,7 +192,7 @@ class SendVideo(BaseClient):
else:
for i in r.updates:
if isinstance(i, (types.UpdateNewMessage, types.UpdateNewChannelMessage)):
- return await utils.parse_messages(
+ return await pyrogram.Message._parse(
self, i.message,
{i.id: i for i in r.users},
{i.id: i for i in r.chats}
diff --git a/pyrogram/client/methods/messages/send_video_note.py b/pyrogram/client/methods/messages/send_video_note.py
index 192ec3f4..edb595af 100644
--- a/pyrogram/client/methods/messages/send_video_note.py
+++ b/pyrogram/client/methods/messages/send_video_note.py
@@ -20,7 +20,9 @@ import binascii
import mimetypes
import os
import struct
+from typing import Union
+import pyrogram
from pyrogram.api import functions, types
from pyrogram.api.errors import FileIdInvalid, FilePartMissing
from pyrogram.client.ext import BaseClient, utils
@@ -28,15 +30,18 @@ from pyrogram.client.ext import BaseClient, utils
class SendVideoNote(BaseClient):
async def send_video_note(self,
- chat_id: int or str,
+ chat_id: Union[int, str],
video_note: str,
duration: int = 0,
length: int = 1,
- thumb: str = None,disable_notification: bool = None,
+ thumb: str = None, disable_notification: bool = None,
reply_to_message_id: int = None,
- reply_markup=None,
+ reply_markup: Union["pyrogram.InlineKeyboardMarkup",
+ "pyrogram.ReplyKeyboardMarkup",
+ "pyrogram.ReplyKeyboardRemove",
+ "pyrogram.ForceReply"] = None,
progress: callable = None,
- progress_args: tuple = ()):
+ progress_args: tuple = ()) -> "pyrogram.Message":
"""Use this method to send video messages.
Args:
@@ -162,7 +167,7 @@ class SendVideoNote(BaseClient):
else:
for i in r.updates:
if isinstance(i, (types.UpdateNewMessage, types.UpdateNewChannelMessage)):
- return await utils.parse_messages(
+ return await pyrogram.Message._parse(
self, i.message,
{i.id: i for i in r.users},
{i.id: i for i in r.chats}
diff --git a/pyrogram/client/methods/messages/send_voice.py b/pyrogram/client/methods/messages/send_voice.py
index ed5a1080..ac2e876e 100644
--- a/pyrogram/client/methods/messages/send_voice.py
+++ b/pyrogram/client/methods/messages/send_voice.py
@@ -20,7 +20,9 @@ import binascii
import mimetypes
import os
import struct
+from typing import Union
+import pyrogram
from pyrogram.api import functions, types
from pyrogram.api.errors import FileIdInvalid, FilePartMissing
from pyrogram.client.ext import BaseClient, utils
@@ -28,16 +30,19 @@ from pyrogram.client.ext import BaseClient, utils
class SendVoice(BaseClient):
async def send_voice(self,
- chat_id: int or str,
+ chat_id: Union[int, str],
voice: str,
caption: str = "",
parse_mode: str = "",
duration: int = 0,
disable_notification: bool = None,
reply_to_message_id: int = None,
- reply_markup=None,
+ reply_markup: Union["pyrogram.InlineKeyboardMarkup",
+ "pyrogram.ReplyKeyboardMarkup",
+ "pyrogram.ReplyKeyboardRemove",
+ "pyrogram.ForceReply"] = None,
progress: callable = None,
- progress_args: tuple = ()):
+ progress_args: tuple = ()) -> "pyrogram.Message":
"""Use this method to send audio files.
Args:
@@ -163,7 +168,7 @@ class SendVoice(BaseClient):
else:
for i in r.updates:
if isinstance(i, (types.UpdateNewMessage, types.UpdateNewChannelMessage)):
- return await utils.parse_messages(
+ return await pyrogram.Message._parse(
self, i.message,
{i.id: i for i in r.users},
{i.id: i for i in r.chats}
diff --git a/pyrogram/client/methods/password/change_cloud_password.py b/pyrogram/client/methods/password/change_cloud_password.py
index 0aa14c1f..f0271f14 100644
--- a/pyrogram/client/methods/password/change_cloud_password.py
+++ b/pyrogram/client/methods/password/change_cloud_password.py
@@ -24,7 +24,10 @@ from ...ext import BaseClient
class ChangeCloudPassword(BaseClient):
- async def change_cloud_password(self, current_password: str, new_password: str, new_hint: str = ""):
+ async def change_cloud_password(self,
+ current_password: str,
+ new_password: str,
+ new_hint: str = "") -> bool:
"""Use this method to change your Two-Step Verification password (Cloud Password) with a new one.
Args:
diff --git a/pyrogram/client/methods/password/enable_cloud_password.py b/pyrogram/client/methods/password/enable_cloud_password.py
index 7ba147b3..0d57f2e0 100644
--- a/pyrogram/client/methods/password/enable_cloud_password.py
+++ b/pyrogram/client/methods/password/enable_cloud_password.py
@@ -24,7 +24,10 @@ from ...ext import BaseClient
class EnableCloudPassword(BaseClient):
- async def enable_cloud_password(self, password: str, hint: str = "", email: str = ""):
+ async def enable_cloud_password(self,
+ password: str,
+ hint: str = "",
+ email: str = "") -> bool:
"""Use this method to enable the Two-Step Verification security feature (Cloud Password) on your account.
This password will be asked when you log in on a new device in addition to the SMS code.
diff --git a/pyrogram/client/methods/password/remove_cloud_password.py b/pyrogram/client/methods/password/remove_cloud_password.py
index dd8e8887..e3e70aae 100644
--- a/pyrogram/client/methods/password/remove_cloud_password.py
+++ b/pyrogram/client/methods/password/remove_cloud_password.py
@@ -23,7 +23,8 @@ from ...ext import BaseClient
class RemoveCloudPassword(BaseClient):
- async def remove_cloud_password(self, password: str):
+ async def remove_cloud_password(self,
+ password: str) -> bool:
"""Use this method to turn off the Two-Step Verification security feature (Cloud Password) on your account.
Args:
diff --git a/pyrogram/client/methods/users/delete_user_profile_photos.py b/pyrogram/client/methods/users/delete_user_profile_photos.py
index 7ba40594..64c22fa8 100644
--- a/pyrogram/client/methods/users/delete_user_profile_photos.py
+++ b/pyrogram/client/methods/users/delete_user_profile_photos.py
@@ -18,13 +18,15 @@
from base64 import b64decode
from struct import unpack
+from typing import List, Union
from pyrogram.api import functions, types
from ...ext import BaseClient
class DeleteUserProfilePhotos(BaseClient):
- async def delete_user_profile_photos(self, id: str or list):
+ async def delete_user_profile_photos(self,
+ id: Union[str, List[str]]) -> bool:
"""Use this method to delete your own profile photos
Args:
diff --git a/pyrogram/client/methods/users/get_me.py b/pyrogram/client/methods/users/get_me.py
index d672bb08..390c3b2c 100644
--- a/pyrogram/client/methods/users/get_me.py
+++ b/pyrogram/client/methods/users/get_me.py
@@ -16,12 +16,13 @@
# 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, utils
+from ...ext import BaseClient
class GetMe(BaseClient):
- async def get_me(self):
+ async def get_me(self) -> "pyrogram.User":
"""A simple method for testing your authorization. Requires no parameters.
Returns:
@@ -30,10 +31,11 @@ class GetMe(BaseClient):
Raises:
:class:`Error ` in case of a Telegram RPC error.
"""
- r = await self.send(
- functions.users.GetFullUser(
- types.InputPeerSelf()
- )
+ return pyrogram.User._parse(
+ self,
+ await self.send(
+ functions.users.GetFullUser(
+ types.InputPeerSelf()
+ )
+ ).user
)
-
- return utils.parse_user(r.user)
diff --git a/pyrogram/client/methods/users/get_user_profile_photos.py b/pyrogram/client/methods/users/get_user_profile_photos.py
index 5e5c29e0..375eba8e 100644
--- a/pyrogram/client/methods/users/get_user_profile_photos.py
+++ b/pyrogram/client/methods/users/get_user_profile_photos.py
@@ -16,15 +16,18 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
+from typing import Union
+
+import pyrogram
from pyrogram.api import functions
-from ...ext import BaseClient, utils
+from ...ext import BaseClient
class GetUserProfilePhotos(BaseClient):
async def get_user_profile_photos(self,
- user_id: int or str,
+ user_id: Union[int, str],
offset: int = 0,
- limit: int = 100):
+ limit: int = 100) -> "pyrogram.UserProfilePhotos":
"""Use this method to get a list of profile pictures for a user.
Args:
@@ -47,7 +50,8 @@ class GetUserProfilePhotos(BaseClient):
Raises:
:class:`Error ` in case of a Telegram RPC error.
"""
- return utils.parse_profile_photos(
+ return pyrogram.UserProfilePhotos._parse(
+ self,
await self.send(
functions.photos.GetUserPhotos(
user_id=await self.resolve_peer(user_id),
diff --git a/pyrogram/client/methods/users/get_users.py b/pyrogram/client/methods/users/get_users.py
index decf933a..b8a331f6 100644
--- a/pyrogram/client/methods/users/get_users.py
+++ b/pyrogram/client/methods/users/get_users.py
@@ -17,13 +17,16 @@
# along with Pyrogram. If not, see .
import asyncio
+from typing import Iterable, Union, List
+import pyrogram
from pyrogram.api import functions
-from ...ext import BaseClient, utils
+from ...ext import BaseClient
class GetUsers(BaseClient):
- async def get_users(self, user_ids):
+ async def get_users(self,
+ user_ids: Iterable[Union[int, str]]) -> Union["pyrogram.User", List["pyrogram.User"]]:
"""Use this method to get information about a user.
You can retrieve up to 200 users at once.
@@ -34,9 +37,9 @@ class GetUsers(BaseClient):
Iterators and Generators are also accepted.
Returns:
- On success and in case *user_ids* was a list, the returned value will be a list of the requested
+ On success and in case *user_ids* was an iterable, the returned value will be a list of the requested
:obj:`Users ` even if a list contains just one element, otherwise if
- *user_ids* was an integer, the single requested :obj:`User` is returned.
+ *user_ids* was an integer or string, the single requested :obj:`User` is returned.
Raises:
:class:`Error ` in case of a Telegram RPC error.
@@ -54,6 +57,6 @@ class GetUsers(BaseClient):
users = []
for i in r:
- users.append(utils.parse_user(i))
+ users.append(pyrogram.User._parse(self, i))
return users if is_iterable else users[0]
diff --git a/pyrogram/client/methods/users/set_user_profile_photo.py b/pyrogram/client/methods/users/set_user_profile_photo.py
index b3ab66b1..f2a2c302 100644
--- a/pyrogram/client/methods/users/set_user_profile_photo.py
+++ b/pyrogram/client/methods/users/set_user_profile_photo.py
@@ -21,7 +21,8 @@ from ...ext import BaseClient
class SetUserProfilePhoto(BaseClient):
- def set_user_profile_photo(self, photo: str):
+ def set_user_profile_photo(self,
+ photo: str) -> bool:
"""Use this method to set a new profile photo.
This method only works for Users.
diff --git a/pyrogram/client/methods/utilities/download_media.py b/pyrogram/client/methods/utilities/download_media.py
index f532c84a..d9284d81 100644
--- a/pyrogram/client/methods/utilities/download_media.py
+++ b/pyrogram/client/methods/utilities/download_media.py
@@ -17,18 +17,19 @@
# along with Pyrogram. If not, see .
import asyncio
+from typing import Union
-from pyrogram.client import types as pyrogram_types
+import pyrogram
from ...ext import BaseClient
class DownloadMedia(BaseClient):
async def download_media(self,
- message: pyrogram_types.Message or str,
+ message: Union["pyrogram.Message", str],
file_name: str = "",
block: bool = True,
progress: callable = None,
- progress_args: tuple = ()):
+ progress_args: tuple = ()) -> Union[str, None]:
"""Use this method to download the media from a Message.
Args:
@@ -78,13 +79,14 @@ class DownloadMedia(BaseClient):
"""
error_message = "This message doesn't contain any downloadable media"
- if isinstance(message, pyrogram_types.Message):
+ if isinstance(message, pyrogram.Message):
if message.photo:
- media = pyrogram_types.Document(
+ 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
+ date=message.photo.date,
+ client=self
)
elif message.audio:
media = message.audio
@@ -103,30 +105,32 @@ class DownloadMedia(BaseClient):
else:
raise ValueError(error_message)
elif isinstance(message, (
- pyrogram_types.Photo,
- pyrogram_types.PhotoSize,
- pyrogram_types.Audio,
- pyrogram_types.Document,
- pyrogram_types.Video,
- pyrogram_types.Voice,
- pyrogram_types.VideoNote,
- pyrogram_types.Sticker,
- pyrogram_types.Animation
+ pyrogram.Photo,
+ pyrogram.PhotoSize,
+ pyrogram.Audio,
+ pyrogram.Document,
+ pyrogram.Video,
+ pyrogram.Voice,
+ pyrogram.VideoNote,
+ pyrogram.Sticker,
+ pyrogram.Animation
)):
- if isinstance(message, pyrogram_types.Photo):
- media = pyrogram_types.Document(
+ 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
+ date=message.date,
+ client=self
)
else:
media = message
elif isinstance(message, str):
- media = pyrogram_types.Document(
+ media = pyrogram.Document(
file_id=message,
file_size=0,
- mime_type=""
+ mime_type="",
+ client=self
)
else:
raise ValueError(error_message)
diff --git a/pyrogram/client/types/__init__.py b/pyrogram/client/types/__init__.py
index 74c97ca1..8289a947 100644
--- a/pyrogram/client/types/__init__.py
+++ b/pyrogram/client/types/__init__.py
@@ -33,7 +33,6 @@ from .messages_and_media import (
Sticker, Venue, Video, VideoNote, Voice, UserProfilePhotos,
Message, Messages, MessageEntity
)
-from .update import Update
from .user_and_chats import (
Chat, ChatMember, ChatMembers, ChatPhoto,
Dialog, Dialogs, User, UserStatus
diff --git a/pyrogram/client/types/bots/callback_query.py b/pyrogram/client/types/bots/callback_query.py
index 046981b7..c3c23333 100644
--- a/pyrogram/client/types/bots/callback_query.py
+++ b/pyrogram/client/types/bots/callback_query.py
@@ -16,10 +16,16 @@
# 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
+from base64 import b64encode
+from struct import pack
+
+import pyrogram
+from pyrogram.api import types
+from ..pyrogram_type import PyrogramType
+from ..user_and_chats import User
-class CallbackQuery(Object):
+class CallbackQuery(PyrogramType):
"""This object represents an incoming callback query from a callback button in an inline keyboard.
If the button that originated the query was attached to a message sent by the bot, the field message
will be present. If the button was attached to a message sent via the bot (in inline mode),
@@ -50,27 +56,64 @@ class CallbackQuery(Object):
Short name of a Game to be returned, serves as the unique identifier for the game.
"""
- ID = 0xb0700024
- def __init__(
- self,
- id: str,
- from_user,
- chat_instance: str,
- client=None,
- message=None,
- inline_message_id: str = None,
- data: bytes = None,
- game_short_name: str = None
- ):
- self._client = client
- self.id = id # string
- self.from_user = from_user # User
- self.message = message # flags.0?Message
- self.inline_message_id = inline_message_id # flags.1?string
- self.chat_instance = chat_instance # string
- self.data = data # flags.2?string
- self.game_short_name = game_short_name # flags.3?string
+ def __init__(self,
+ *,
+ client: "pyrogram.client.ext.BaseClient",
+ id: str,
+ from_user: User,
+ chat_instance: str,
+ message: "pyrogram.Message" = None,
+ inline_message_id: str = None,
+ data: bytes = None,
+ game_short_name: str = None):
+ super().__init__(client)
+
+ self.id = id
+ self.from_user = from_user
+ self.message = message
+ self.inline_message_id = inline_message_id
+ self.chat_instance = chat_instance
+ self.data = data
+ self.game_short_name = game_short_name
+
+ @staticmethod
+ def _parse(client, callback_query, users) -> "CallbackQuery":
+ message = None
+ inline_message_id = None
+
+ if isinstance(callback_query, types.UpdateBotCallbackQuery):
+ peer = callback_query.peer
+
+ if isinstance(peer, types.PeerUser):
+ peer_id = peer.user_id
+ elif isinstance(peer, types.PeerChat):
+ peer_id = -peer.chat_id
+ else:
+ peer_id = int("-100" + str(peer.channel_id))
+
+ message = client.get_messages(peer_id, callback_query.msg_id)
+ elif isinstance(callback_query, types.UpdateInlineBotCallbackQuery):
+ inline_message_id = b64encode(
+ pack(
+ "`.
diff --git a/pyrogram/client/types/bots/force_reply.py b/pyrogram/client/types/bots/force_reply.py
index 2d3cc98f..0c15b92a 100644
--- a/pyrogram/client/types/bots/force_reply.py
+++ b/pyrogram/client/types/bots/force_reply.py
@@ -16,11 +16,11 @@
# 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
from pyrogram.api.types import ReplyKeyboardForceReply
+from ..pyrogram_type import PyrogramType
-class ForceReply(Object):
+class ForceReply(PyrogramType):
"""Upon receiving a message with this object, Telegram clients will display a reply interface to the user
(act as if the user has selected the bot's message and tapped 'Reply').
This can be extremely useful if you want to create user-friendly step-by-step interfaces without having to
@@ -33,13 +33,14 @@ class ForceReply(Object):
2) if the bot's message is a reply (has reply_to_message_id), sender of the original message.
"""
- ID = 0xb0700018
+ def __init__(self,
+ selective: bool = None):
+ super().__init__(None)
- def __init__(self, selective: bool = None):
self.selective = selective
@staticmethod
- def read(o, *args):
+ def read(o):
return ForceReply(
selective=o.selective
)
diff --git a/pyrogram/client/types/bots/inline_keyboard_button.py b/pyrogram/client/types/bots/inline_keyboard_button.py
index 3d6c7b6b..655e78f4 100644
--- a/pyrogram/client/types/bots/inline_keyboard_button.py
+++ b/pyrogram/client/types/bots/inline_keyboard_button.py
@@ -16,15 +16,14 @@
# 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
-
from pyrogram.api.types import (
KeyboardButtonUrl, KeyboardButtonCallback,
KeyboardButtonSwitchInline
)
+from ..pyrogram_type import PyrogramType
-class InlineKeyboardButton(Object):
+class InlineKeyboardButton(PyrogramType):
"""This object represents one button of an inline keyboard. You must use exactly one of the optional fields.
Args:
@@ -54,18 +53,14 @@ class InlineKeyboardButton(Object):
# TODO: Add callback_game and pay fields
- ID = 0xb0700019
+ def __init__(self,
+ text: str,
+ callback_data: bytes = None,
+ url: str = None,
+ switch_inline_query: str = None,
+ switch_inline_query_current_chat: str = None):
+ super().__init__(None)
- def __init__(
- self,
- text: str,
- callback_data: bytes = None,
- url: str = None,
- switch_inline_query: str = None,
- switch_inline_query_current_chat: str = None,
- # callback_game=None,
- # pay: bool = None
- ):
self.text = text
self.url = url
self.callback_data = callback_data
@@ -75,29 +70,29 @@ class InlineKeyboardButton(Object):
# self.pay = pay
@staticmethod
- def read(b, *args):
- if isinstance(b, KeyboardButtonUrl):
+ def read(o):
+ if isinstance(o, KeyboardButtonUrl):
return InlineKeyboardButton(
- text=b.text,
- url=b.url
+ text=o.text,
+ url=o.url
)
- if isinstance(b, KeyboardButtonCallback):
+ if isinstance(o, KeyboardButtonCallback):
return InlineKeyboardButton(
- text=b.text,
- callback_data=b.data
+ text=o.text,
+ callback_data=o.data
)
- if isinstance(b, KeyboardButtonSwitchInline):
- if b.same_peer:
+ if isinstance(o, KeyboardButtonSwitchInline):
+ if o.same_peer:
return InlineKeyboardButton(
- text=b.text,
- switch_inline_query_current_chat=b.query
+ text=o.text,
+ switch_inline_query_current_chat=o.query
)
else:
return InlineKeyboardButton(
- text=b.text,
- switch_inline_query=b.query
+ text=o.text,
+ switch_inline_query=o.query
)
def write(self):
diff --git a/pyrogram/client/types/bots/inline_keyboard_markup.py b/pyrogram/client/types/bots/inline_keyboard_markup.py
index 2a6993c4..d958f306 100644
--- a/pyrogram/client/types/bots/inline_keyboard_markup.py
+++ b/pyrogram/client/types/bots/inline_keyboard_markup.py
@@ -16,13 +16,14 @@
# 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
+from typing import List
from pyrogram.api.types import ReplyInlineMarkup, KeyboardButtonRow
from . import InlineKeyboardButton
+from ..pyrogram_type import PyrogramType
-class InlineKeyboardMarkup(Object):
+class InlineKeyboardMarkup(PyrogramType):
"""This object represents an inline keyboard that appears right next to the message it belongs to.
Args:
@@ -30,16 +31,17 @@ class InlineKeyboardMarkup(Object):
List of button rows, each represented by a List of InlineKeyboardButton objects.
"""
- ID = 0xb0700020
+ def __init__(self,
+ inline_keyboard: List[List[InlineKeyboardButton]]):
+ super().__init__(None)
- def __init__(self, inline_keyboard: list):
self.inline_keyboard = inline_keyboard
@staticmethod
- def read(kb, *args):
+ def read(o):
inline_keyboard = []
- for i in kb.rows:
+ for i in o.rows:
row = []
for j in i.buttons:
diff --git a/pyrogram/client/types/bots/keyboard_button.py b/pyrogram/client/types/bots/keyboard_button.py
index b9af3b46..4b025375 100644
--- a/pyrogram/client/types/bots/keyboard_button.py
+++ b/pyrogram/client/types/bots/keyboard_button.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 pyrogram.api.core import Object
-
from pyrogram.api.types import KeyboardButton as RawKeyboardButton
from pyrogram.api.types import KeyboardButtonRequestPhone, KeyboardButtonRequestGeoLocation
+from ..pyrogram_type import PyrogramType
-class KeyboardButton(Object):
+class KeyboardButton(PyrogramType):
"""This object represents one button of the reply keyboard.
For simple text buttons String can be used instead of this object to specify text of the button.
Optional fields are mutually exclusive.
@@ -41,27 +40,30 @@ class KeyboardButton(Object):
Available in private chats only.
"""
- ID = 0xb0700021
+ def __init__(self,
+ text: str,
+ request_contact: bool = None,
+ request_location: bool = None):
+ super().__init__(None)
- def __init__(self, text: str, request_contact: bool = None, request_location: bool = None):
self.text = text
self.request_contact = request_contact
self.request_location = request_location
@staticmethod
- def read(b, *args):
- if isinstance(b, RawKeyboardButton):
- return b.text
+ def read(o):
+ if isinstance(o, RawKeyboardButton):
+ return o.text
- if isinstance(b, KeyboardButtonRequestPhone):
+ if isinstance(o, KeyboardButtonRequestPhone):
return KeyboardButton(
- text=b.text,
+ text=o.text,
request_contact=True
)
- if isinstance(b, KeyboardButtonRequestGeoLocation):
+ if isinstance(o, KeyboardButtonRequestGeoLocation):
return KeyboardButton(
- text=b.text,
+ text=o.text,
request_location=True
)
diff --git a/pyrogram/client/types/bots/reply_keyboard_markup.py b/pyrogram/client/types/bots/reply_keyboard_markup.py
index 29fc1081..85f38b10 100644
--- a/pyrogram/client/types/bots/reply_keyboard_markup.py
+++ b/pyrogram/client/types/bots/reply_keyboard_markup.py
@@ -16,15 +16,15 @@
# 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
+from typing import List
from pyrogram.api.types import KeyboardButtonRow
from pyrogram.api.types import ReplyKeyboardMarkup as RawReplyKeyboardMarkup
-
from . import KeyboardButton
+from ..pyrogram_type import PyrogramType
-class ReplyKeyboardMarkup(Object):
+class ReplyKeyboardMarkup(PyrogramType):
"""This object represents a custom keyboard with reply options.
Args:
@@ -49,22 +49,20 @@ class ReplyKeyboardMarkup(Object):
select the new language. Other users in the group don't see the keyboard.
"""
- ID = 0xb0700022
+ def __init__(self,
+ keyboard: List[List[KeyboardButton]],
+ resize_keyboard: bool = None,
+ one_time_keyboard: bool = None,
+ selective: bool = None):
+ super().__init__(None)
- def __init__(
- self,
- keyboard: list,
- resize_keyboard: bool = None,
- one_time_keyboard: bool = None,
- selective: bool = None
- ):
self.keyboard = keyboard
self.resize_keyboard = resize_keyboard
self.one_time_keyboard = one_time_keyboard
self.selective = selective
@staticmethod
- def read(kb, *args):
+ def read(kb):
keyboard = []
for i in kb.rows:
diff --git a/pyrogram/client/types/bots/reply_keyboard_remove.py b/pyrogram/client/types/bots/reply_keyboard_remove.py
index 3e2aebf5..def9917c 100644
--- a/pyrogram/client/types/bots/reply_keyboard_remove.py
+++ b/pyrogram/client/types/bots/reply_keyboard_remove.py
@@ -16,11 +16,11 @@
# 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
from pyrogram.api.types import ReplyKeyboardHide
+from ..pyrogram_type import PyrogramType
-class ReplyKeyboardRemove(Object):
+class ReplyKeyboardRemove(PyrogramType):
"""Upon receiving a message with this object, Telegram clients will remove the current custom keyboard and
display the default letter-keyboard. By default, custom keyboards are displayed until a new keyboard is sent
by a bot. An exception is made for one-time keyboards that are hidden immediately after the user presses a
@@ -35,13 +35,14 @@ class ReplyKeyboardRemove(Object):
keyboard for that user, while still showing the keyboard with poll options to users who haven't voted yet.
"""
- ID = 0xb0700023
+ def __init__(self,
+ selective: bool = None):
+ super().__init__(None)
- def __init__(self, selective: bool = None):
self.selective = selective
@staticmethod
- def read(o, *args):
+ def read(o):
return ReplyKeyboardRemove(
selective=o.selective
)
diff --git a/pyrogram/client/types/input_media/input_media.py b/pyrogram/client/types/input_media/input_media.py
index 611d5865..7a380f89 100644
--- a/pyrogram/client/types/input_media/input_media.py
+++ b/pyrogram/client/types/input_media/input_media.py
@@ -18,7 +18,10 @@
class InputMedia:
- def __init__(self, media: str, caption: str, parse_mode: str):
+ def __init__(self,
+ media: str,
+ caption: str,
+ parse_mode: str):
self.media = media
self.caption = caption
self.parse_mode = parse_mode
diff --git a/pyrogram/client/types/input_media/input_phone_contact.py b/pyrogram/client/types/input_media/input_phone_contact.py
index 0e61c006..eacecaf8 100644
--- a/pyrogram/client/types/input_media/input_phone_contact.py
+++ b/pyrogram/client/types/input_media/input_phone_contact.py
@@ -35,10 +35,16 @@ class InputPhoneContact:
Contact's last name
"""
- def __init__(self, phone: str, first_name: str, last_name: str = ""):
+ def __init__(self,
+ phone: str,
+ first_name: str,
+ last_name: str = ""):
pass
- def __new__(cls, phone: str, first_name: str, last_name: str = ""):
+ def __new__(cls,
+ phone: str,
+ first_name: str,
+ last_name: str = ""):
return RawInputPhoneContact(
client_id=MsgId(),
phone="+" + phone.strip("+"),
diff --git a/pyrogram/client/types/messages_and_media/animation.py b/pyrogram/client/types/messages_and_media/animation.py
index a8641e9e..6b7f7cf7 100644
--- a/pyrogram/client/types/messages_and_media/animation.py
+++ b/pyrogram/client/types/messages_and_media/animation.py
@@ -16,10 +16,16 @@
# 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
+from struct import pack
+
+import pyrogram
+from pyrogram.api import types
+from .photo_size import PhotoSize
+from ..pyrogram_type import PyrogramType
+from ...ext.utils import encode
-class Animation(Object):
+class Animation(PyrogramType):
"""This object represents an animation file (GIF or H.264/MPEG-4 AVC video without sound).
Args:
@@ -51,20 +57,20 @@ class Animation(Object):
Date the animation was sent in Unix time.
"""
- ID = 0xb0700025
+ def __init__(self,
+ *,
+ client: "pyrogram.client.ext.BaseClient",
+ file_id: str,
+ width: int,
+ height: int,
+ duration: int,
+ thumb: PhotoSize = None,
+ file_name: str = None,
+ mime_type: str = None,
+ file_size: int = None,
+ date: int = None):
+ super().__init__(client)
- def __init__(
- self,
- file_id: str,
- width: int,
- height: 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
self.thumb = thumb
self.file_name = file_name
@@ -74,3 +80,27 @@ class Animation(Object):
self.width = width
self.height = height
self.duration = duration
+
+ @staticmethod
+ def _parse(client, animation: types.Document, video_attributes: types.DocumentAttributeVideo,
+ file_name: str) -> "Animation":
+ return Animation(
+ file_id=encode(
+ pack(
+ ".
-from pyrogram.api.core import Object
+from struct import pack
+
+import pyrogram
+from pyrogram.api import types
+from .photo_size import PhotoSize
+from ..pyrogram_type import PyrogramType
+from ...ext.utils import encode
-class Audio(Object):
+class Audio(PyrogramType):
"""This object represents an audio file to be treated as music by the Telegram clients.
Args:
@@ -51,20 +57,20 @@ class Audio(Object):
Title of the audio as defined by sender or by audio tags.
"""
- ID = 0xb0700006
+ def __init__(self,
+ *,
+ client: "pyrogram.client.ext.BaseClient",
+ 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):
+ super().__init__(client)
- def __init__(
- self,
- file_id: str,
- duration: int,
- thumb=None,
- file_name: str = None,
- mime_type: str = None,
- file_size: int = None,
- date: int = None,
- performer: str = None,
- title: str = None
- ):
self.file_id = file_id
self.thumb = thumb
self.file_name = file_name
@@ -74,3 +80,27 @@ class Audio(Object):
self.duration = duration
self.performer = performer
self.title = title
+
+ @staticmethod
+ def _parse(client, audio: types.Document, audio_attributes: types.DocumentAttributeAudio,
+ file_name: str) -> "Audio":
+ return Audio(
+ file_id=encode(
+ pack(
+ ".
-from pyrogram.api.core import Object
+import pyrogram
+
+from pyrogram.api import types
+from ..pyrogram_type import PyrogramType
-class Contact(Object):
+class Contact(PyrogramType):
"""This object represents a phone contact.
Args:
@@ -39,18 +42,29 @@ class Contact(Object):
Additional data about the contact in the form of a vCard.
"""
- ID = 0xb0700011
+ def __init__(self,
+ *,
+ client: "pyrogram.client.ext.BaseClient",
+ phone_number: str,
+ first_name: str,
+ last_name: str = None,
+ user_id: int = None,
+ vcard: str = None):
+ super().__init__(client)
- def __init__(
- self,
- phone_number: str,
- first_name: str,
- last_name: str = None,
- user_id: int = None,
- vcard: str = None
- ):
self.phone_number = phone_number
self.first_name = first_name
self.last_name = last_name
self.user_id = user_id
self.vcard = vcard
+
+ @staticmethod
+ def _parse(client, contact: types.MessageMediaContact) -> "Contact":
+ return Contact(
+ phone_number=contact.phone_number,
+ first_name=contact.first_name,
+ last_name=contact.last_name or None,
+ vcard=contact.vcard or None,
+ user_id=contact.user_id or None,
+ client=client
+ )
diff --git a/pyrogram/client/types/messages_and_media/document.py b/pyrogram/client/types/messages_and_media/document.py
index d87fa666..db41df6c 100644
--- a/pyrogram/client/types/messages_and_media/document.py
+++ b/pyrogram/client/types/messages_and_media/document.py
@@ -16,10 +16,16 @@
# 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
+from struct import pack
+
+import pyrogram
+from pyrogram.api import types
+from .photo_size import PhotoSize
+from ..pyrogram_type import PyrogramType
+from ...ext.utils import encode
-class Document(Object):
+class Document(PyrogramType):
"""This object represents a general file (as opposed to photos, voice messages, audio files, ...).
Args:
@@ -42,20 +48,40 @@ class Document(Object):
Date the document was sent in Unix time.
"""
- ID = 0xb0700007
+ def __init__(self,
+ *,
+ client: "pyrogram.client.ext.BaseClient",
+ file_id: str,
+ thumb: PhotoSize = None,
+ file_name: str = None,
+ mime_type: str = None,
+ file_size: int = None,
+ date: int = None):
+ super().__init__(client)
- def __init__(
- self,
- file_id: str,
- thumb=None,
- file_name: str = None,
- mime_type: str = None,
- file_size: int = None,
- date: int = None
- ):
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
+
+ @staticmethod
+ def _parse(client, document: types.Document, file_name: str) -> "Document":
+ return Document(
+ file_id=encode(
+ pack(
+ ".
-from pyrogram.api.core import Object
+import pyrogram
+
+from pyrogram.api import types
+from ..pyrogram_type import PyrogramType
-class Location(Object):
+class Location(PyrogramType):
"""This object represents a point on the map.
Args:
@@ -30,8 +33,21 @@ class Location(Object):
Latitude as defined by sender.
"""
- ID = 0xb0700012
+ def __init__(self,
+ *,
+ client: "pyrogram.client.ext.BaseClient",
+ longitude: float,
+ latitude: float):
+ super().__init__(client)
- def __init__(self, longitude: float, latitude: float):
self.longitude = longitude
self.latitude = latitude
+
+ @staticmethod
+ def _parse(client, geo_point: types.GeoPoint) -> "Location":
+ if isinstance(geo_point, types.GeoPoint):
+ return Location(
+ longitude=geo_point.long,
+ latitude=geo_point.lat,
+ client=client
+ )
diff --git a/pyrogram/client/types/messages_and_media/message.py b/pyrogram/client/types/messages_and_media/message.py
index 3ace38bc..3267c4dc 100644
--- a/pyrogram/client/types/messages_and_media/message.py
+++ b/pyrogram/client/types/messages_and_media/message.py
@@ -16,11 +16,21 @@
# 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
-from ..bots import InlineKeyboardMarkup, ReplyKeyboardMarkup
+from typing import List, Match, Union
+
+import pyrogram
+from pyrogram.api import types
+from pyrogram.api.errors import MessageIdsEmpty
+from .contact import Contact
+from .location import Location
+from .message_entity import MessageEntity
+from ..messages_and_media.photo import Photo
+from ..pyrogram_type import PyrogramType
+from ..user_and_chats.chat import Chat
+from ..user_and_chats.user import User
-class Message(Object):
+class Message(PyrogramType):
"""This object represents a message.
Args:
@@ -193,18 +203,18 @@ class Message(Object):
via_bot (:obj:`User `):
The information of the bot that generated the message from an inline query of a user.
-
+
outgoing (``bool``, *optional*):
Whether the message is incoming or outgoing.
Messages received from other chats are incoming (*outgoing* is False).
Messages sent from yourself to other chats are outgoing (*outgoing* is True).
An exception is made for your own personal chat; messages sent there will be incoming.
- matches (``list``, *optional*):
+ matches (List of regex Matches, *optional*):
A list containing all `Match Objects `_ that match
the text of this message. Only applicable when using :obj:`Filters.regex `.
- command (``list``, *optional*):
+ command (List of ``str``, *optional*):
A list containing the command and its arguments, if any.
E.g.: "/start 1 2 3" would produce ["start", "1", "2", "3"].
Only applicable when using :obj:`Filters.command `.
@@ -215,114 +225,342 @@ class Message(Object):
"""
# TODO: Add game missing field. Also invoice, successful_payment, connected_website
- ID = 0xb0700003
- def __init__(
- self,
- message_id: int,
- client=None,
- date: int = None,
- chat=None,
- from_user=None,
- forward_from=None,
- forward_from_chat=None,
- forward_from_message_id: int = None,
- forward_signature: str = None,
- forward_date: int = None,
- reply_to_message=None,
- mentioned=None,
- empty=None,
- service=None,
- media=None,
- edit_date: int = None,
- media_group_id: str = None,
- author_signature: str = None,
- text: str = None,
- entities: list = None,
- caption_entities: list = None,
- audio=None,
- document=None,
- photo=None,
- sticker=None,
- animation=None,
- video=None,
- voice=None,
- video_note=None,
- caption: str = None,
- contact=None,
- location=None,
- venue=None,
- web_page=None,
- new_chat_members: list = None,
- left_chat_member=None,
- new_chat_title: str = None,
- new_chat_photo=None,
- delete_chat_photo: bool = None,
- group_chat_created: bool = None,
- supergroup_chat_created: bool = None,
- channel_chat_created: bool = None,
- migrate_to_chat_id: int = None,
- migrate_from_chat_id: int = None,
- pinned_message=None,
- views: int = None,
- via_bot=None,
- outgoing: bool = None,
- matches: list = None,
- command: list = None,
- reply_markup=None,
- ):
- self.message_id = message_id # int
- self._client = client
- self.date = date # int
- self.chat = chat # Chat
- self.from_user = from_user # flags.0?User
- self.forward_from = forward_from # flags.1?User
- self.forward_from_chat = forward_from_chat # flags.2?Chat
- self.forward_from_message_id = forward_from_message_id # flags.3?int
- self.forward_signature = forward_signature # flags.4?string
- self.forward_date = forward_date # flags.5?int
- self.reply_to_message = reply_to_message # flags.6?Message
+ def __init__(self,
+ *,
+ client: "pyrogram.client.ext.BaseClient",
+ message_id: int,
+ date: int = None,
+ chat: Chat = None,
+ from_user: User = None,
+ forward_from: User = None,
+ forward_from_chat: Chat = None,
+ forward_from_message_id: int = None,
+ forward_signature: str = None,
+ forward_date: int = None,
+ reply_to_message: "Message" = None,
+ mentioned: bool = None,
+ empty: bool = None,
+ service: bool = None,
+ media: bool = None,
+ edit_date: int = None,
+ media_group_id: str = None,
+ author_signature: str = None,
+ text: str = None,
+ entities: List["pyrogram.MessageEntity"] = None,
+ caption_entities: List["pyrogram.MessageEntity"] = None,
+ audio: "pyrogram.Audio" = None,
+ document: "pyrogram.Document" = None,
+ photo: "pyrogram.Photo" = None,
+ sticker: "pyrogram.Sticker" = None,
+ animation: "pyrogram.Animation" = None,
+ video: "pyrogram.Video" = None,
+ voice: "pyrogram.Voice" = None,
+ video_note: "pyrogram.VideoNote" = None,
+ caption: str = None,
+ contact: "pyrogram.Contact" = None,
+ location: "pyrogram.Location" = None,
+ venue: "pyrogram.Venue" = None,
+ web_page: bool = None,
+ new_chat_members: List[User] = None,
+ left_chat_member: User = None,
+ new_chat_title: str = None,
+ new_chat_photo: "pyrogram.Photo" = None,
+ delete_chat_photo: bool = None,
+ group_chat_created: bool = None,
+ supergroup_chat_created: bool = None,
+ channel_chat_created: bool = None,
+ migrate_to_chat_id: int = None,
+ migrate_from_chat_id: int = None,
+ pinned_message: "Message" = None,
+ views: int = None,
+ via_bot: User = None,
+ outgoing: bool = None,
+ matches: List[Match] = None,
+ command: List[str] = None,
+ reply_markup: Union["pyrogram.InlineKeyboardMarkup",
+ "pyrogram.ReplyKeyboardMarkup",
+ "pyrogram.ReplyKeyboardRemove",
+ "pyrogram.ForceReply"] = None):
+ super().__init__(client)
+
+ self.message_id = message_id
+ self.date = date
+ self.chat = chat
+ self.from_user = from_user
+ self.forward_from = forward_from
+ self.forward_from_chat = forward_from_chat
+ self.forward_from_message_id = forward_from_message_id
+ self.forward_signature = forward_signature
+ self.forward_date = forward_date
+ self.reply_to_message = reply_to_message
self.mentioned = mentioned
self.empty = empty
self.service = service
self.media = media
- self.edit_date = edit_date # flags.7?int
- self.media_group_id = media_group_id # flags.8?string
- self.author_signature = author_signature # flags.9?string
- self.text = text # flags.10?string
- self.entities = entities # flags.11?Vector
- self.caption_entities = caption_entities # flags.12?Vector
- self.audio = audio # flags.13?Audio
- self.document = document # flags.14?Document
- self.photo = photo # flags.16?Vector
- self.sticker = sticker # flags.17?Sticker
+ self.edit_date = edit_date
+ self.media_group_id = media_group_id
+ self.author_signature = author_signature
+ self.text = text
+ self.entities = entities
+ self.caption_entities = caption_entities
+ self.audio = audio
+ self.document = document
+ self.photo = photo
+ self.sticker = sticker
self.animation = animation
- self.video = video # flags.18?Video
- self.voice = voice # flags.19?Voice
- self.video_note = video_note # flags.20?VideoNote
- self.caption = caption # flags.21?string
- self.contact = contact # flags.22?Contact
- self.location = location # flags.23?Location
- self.venue = venue # flags.24?Venue
+ self.video = video
+ self.voice = voice
+ self.video_note = video_note
+ self.caption = caption
+ self.contact = contact
+ self.location = location
+ self.venue = venue
self.web_page = web_page
- self.new_chat_members = new_chat_members # flags.25?Vector
- self.left_chat_member = left_chat_member # flags.26?User
- self.new_chat_title = new_chat_title # flags.27?string
- self.new_chat_photo = new_chat_photo # flags.28?Vector
- self.delete_chat_photo = delete_chat_photo # flags.29?true
- self.group_chat_created = group_chat_created # flags.30?true
- self.supergroup_chat_created = supergroup_chat_created # flags.31?true
- self.channel_chat_created = channel_chat_created # flags.32?true
- self.migrate_to_chat_id = migrate_to_chat_id # flags.33?int
- self.migrate_from_chat_id = migrate_from_chat_id # flags.34?int
- self.pinned_message = pinned_message # flags.35?Message
- self.views = views # flags.39?int
- self.via_bot = via_bot # flags.40?User
+ self.new_chat_members = new_chat_members
+ self.left_chat_member = left_chat_member
+ self.new_chat_title = new_chat_title
+ self.new_chat_photo = new_chat_photo
+ self.delete_chat_photo = delete_chat_photo
+ self.group_chat_created = group_chat_created
+ self.supergroup_chat_created = supergroup_chat_created
+ self.channel_chat_created = channel_chat_created
+ self.migrate_to_chat_id = migrate_to_chat_id
+ self.migrate_from_chat_id = migrate_from_chat_id
+ self.pinned_message = pinned_message
+ self.views = views
+ self.via_bot = via_bot
self.outgoing = outgoing
self.matches = matches
self.command = command
self.reply_markup = reply_markup
+ @staticmethod
+ async def _parse(client, message: types.Message or types.MessageService or types.MessageEmpty, users: dict,
+ chats: dict, replies: int = 1):
+ if isinstance(message, types.MessageEmpty):
+ return Message(message_id=message.id, empty=True, client=client)
+
+ if isinstance(message, types.MessageService):
+ action = message.action
+
+ new_chat_members = None
+ left_chat_member = None
+ new_chat_title = None
+ delete_chat_photo = None
+ migrate_to_chat_id = None
+ migrate_from_chat_id = None
+ group_chat_created = None
+ channel_chat_created = None
+ new_chat_photo = None
+
+ if isinstance(action, types.MessageActionChatAddUser):
+ new_chat_members = [User._parse(client, users[i]) for i in action.users]
+ elif isinstance(action, types.MessageActionChatJoinedByLink):
+ new_chat_members = [User._parse(client, users[message.from_id])]
+ elif isinstance(action, types.MessageActionChatDeleteUser):
+ left_chat_member = User._parse(client, users[action.user_id])
+ elif isinstance(action, types.MessageActionChatEditTitle):
+ new_chat_title = action.title
+ elif isinstance(action, types.MessageActionChatDeletePhoto):
+ delete_chat_photo = True
+ elif isinstance(action, types.MessageActionChatMigrateTo):
+ migrate_to_chat_id = action.channel_id
+ elif isinstance(action, types.MessageActionChannelMigrateFrom):
+ migrate_from_chat_id = action.chat_id
+ elif isinstance(action, types.MessageActionChatCreate):
+ group_chat_created = True
+ elif isinstance(action, types.MessageActionChannelCreate):
+ channel_chat_created = True
+ elif isinstance(action, types.MessageActionChatEditPhoto):
+ new_chat_photo = Photo._parse(client, action.photo)
+
+ parsed_message = Message(
+ message_id=message.id,
+ date=message.date,
+ chat=Chat._parse(client, message, users, chats),
+ from_user=User._parse(client, users.get(message.from_id, None)),
+ service=True,
+ new_chat_members=new_chat_members,
+ left_chat_member=left_chat_member,
+ new_chat_title=new_chat_title,
+ new_chat_photo=new_chat_photo,
+ delete_chat_photo=delete_chat_photo,
+ migrate_to_chat_id=int("-100" + str(migrate_to_chat_id)) if migrate_to_chat_id else None,
+ migrate_from_chat_id=-migrate_from_chat_id if migrate_from_chat_id else None,
+ group_chat_created=group_chat_created,
+ channel_chat_created=channel_chat_created,
+ client=client
+ # TODO: supergroup_chat_created
+ )
+
+ if isinstance(action, types.MessageActionPinMessage):
+ try:
+ parsed_message.pinned_message = await client.get_messages(
+ parsed_message.chat.id,
+ reply_to_message_ids=message.id,
+ replies=0
+ )
+ except MessageIdsEmpty:
+ pass
+
+ return parsed_message
+
+ if isinstance(message, types.Message):
+ entities = [MessageEntity._parse(client, entity, users) for entity in message.entities]
+ entities = list(filter(lambda x: x is not None, entities))
+
+ forward_from = None
+ forward_from_chat = None
+ forward_from_message_id = None
+ forward_signature = None
+ forward_date = None
+
+ forward_header = message.fwd_from
+
+ if forward_header:
+ forward_date = forward_header.date
+
+ if forward_header.from_id:
+ forward_from = User._parse(client, users[forward_header.from_id])
+ else:
+ forward_from_chat = Chat._parse_channel_chat(client, chats[forward_header.channel_id])
+ forward_from_message_id = forward_header.channel_post
+ forward_signature = forward_header.post_author
+
+ photo = None
+ location = None
+ contact = None
+ venue = None
+ audio = None
+ voice = None
+ animation = None
+ video = None
+ video_note = None
+ sticker = None
+ document = None
+ web_page = None
+
+ media = message.media
+
+ if media:
+ if isinstance(media, types.MessageMediaPhoto):
+ photo = Photo._parse(client, media.photo)
+ elif isinstance(media, types.MessageMediaGeo):
+ location = Location._parse(client, media.geo)
+ elif isinstance(media, types.MessageMediaContact):
+ contact = Contact._parse(client, media)
+ elif isinstance(media, types.MessageMediaVenue):
+ venue = pyrogram.Venue._parse(client, media)
+ elif isinstance(media, types.MessageMediaDocument):
+ doc = media.document
+
+ if isinstance(doc, types.Document):
+ attributes = {type(i): i for i in doc.attributes}
+
+ file_name = getattr(
+ attributes.get(
+ types.DocumentAttributeFilename, None
+ ), "file_name", None
+ )
+
+ if types.DocumentAttributeAudio in attributes:
+ audio_attributes = attributes[types.DocumentAttributeAudio]
+
+ if audio_attributes.voice:
+ voice = pyrogram.Voice._parse(client, doc, audio_attributes)
+ else:
+ audio = pyrogram.Audio._parse(client, doc, audio_attributes, file_name)
+ elif types.DocumentAttributeAnimated in attributes:
+ video_attributes = attributes.get(types.DocumentAttributeVideo, None)
+
+ animation = pyrogram.Animation._parse(client, doc, video_attributes, file_name)
+ elif types.DocumentAttributeVideo in attributes:
+ video_attributes = attributes[types.DocumentAttributeVideo]
+
+ if video_attributes.round_message:
+ video_note = pyrogram.VideoNote._parse(client, doc, video_attributes)
+ else:
+ video = pyrogram.Video._parse(client, doc, video_attributes, file_name)
+ elif types.DocumentAttributeSticker in attributes:
+ sticker = await pyrogram.Sticker._parse(
+ client, doc,
+ attributes.get(types.DocumentAttributeImageSize, None),
+ attributes[types.DocumentAttributeSticker],
+ file_name
+ )
+ else:
+ document = pyrogram.Document._parse(client, doc, file_name)
+ elif isinstance(media, types.MessageMediaWebPage):
+ web_page = True
+ media = None
+ else:
+ media = None
+
+ reply_markup = message.reply_markup
+
+ if reply_markup:
+ if isinstance(reply_markup, types.ReplyKeyboardForceReply):
+ reply_markup = pyrogram.ForceReply.read(reply_markup)
+ elif isinstance(reply_markup, types.ReplyKeyboardMarkup):
+ reply_markup = pyrogram.ReplyKeyboardMarkup.read(reply_markup)
+ elif isinstance(reply_markup, types.ReplyInlineMarkup):
+ reply_markup = pyrogram.InlineKeyboardMarkup.read(reply_markup)
+ elif isinstance(reply_markup, types.ReplyKeyboardHide):
+ reply_markup = pyrogram.ReplyKeyboardRemove.read(reply_markup)
+ else:
+ reply_markup = None
+
+ parsed_message = Message(
+ message_id=message.id,
+ date=message.date,
+ chat=Chat._parse(client, message, users, chats),
+ from_user=User._parse(client, users.get(message.from_id, None)),
+ text=Str(message.message).init(client, entities) or None if media is None else None,
+ caption=Str(message.message).init(client, entities) or None if media is not None else None,
+ entities=entities or None if media is None else None,
+ caption_entities=entities or None if media is not None else None,
+ author_signature=message.post_author,
+ forward_from=forward_from,
+ forward_from_chat=forward_from_chat,
+ forward_from_message_id=forward_from_message_id,
+ forward_signature=forward_signature,
+ forward_date=forward_date,
+ mentioned=message.mentioned,
+ media=bool(media) or None,
+ edit_date=message.edit_date,
+ media_group_id=message.grouped_id,
+ photo=photo,
+ location=location,
+ contact=contact,
+ venue=venue,
+ audio=audio,
+ voice=voice,
+ animation=animation,
+ video=video,
+ video_note=video_note,
+ sticker=sticker,
+ document=document,
+ web_page=web_page,
+ views=message.views,
+ via_bot=User._parse(client, users.get(message.via_bot_id, None)),
+ outgoing=message.out,
+ reply_markup=reply_markup,
+ client=client
+ )
+
+ if message.reply_to_msg_id and replies:
+ try:
+ parsed_message.reply_to_message = await client.get_messages(
+ parsed_message.chat.id,
+ reply_to_message_ids=message.id,
+ replies=replies - 1
+ )
+ except MessageIdsEmpty:
+ pass
+
+ return parsed_message
+
async def reply(self,
text: str,
quote: bool = None,
@@ -586,9 +824,9 @@ class Message(Object):
``ValueError``: If the provided index or position is out of range or the button label was not found
``TimeoutError``: If, after clicking an inline button, the bot fails to answer within 10 seconds
"""
- if isinstance(self.reply_markup, ReplyKeyboardMarkup):
+ if isinstance(self.reply_markup, pyrogram.ReplyKeyboardMarkup):
return await self.reply(x)
- elif isinstance(self.reply_markup, InlineKeyboardMarkup):
+ elif isinstance(self.reply_markup, pyrogram.InlineKeyboardMarkup):
if isinstance(x, int) and y is None:
try:
button = [
@@ -687,3 +925,29 @@ class Message(Object):
progress=progress,
progress_args=progress_args,
)
+
+
+class Str(str):
+ def __init__(self, *args):
+ super().__init__()
+
+ self.client = None
+ self.entities = None
+
+ def init(self, client, entities):
+ self.client = client
+ self.entities = entities
+
+ return self
+
+ @property
+ def text(self):
+ return self
+
+ @property
+ def markdown(self):
+ return self.client.markdown.unparse(self, self.entities)
+
+ @property
+ def html(self):
+ return self.client.html.unparse(self, self.entities)
diff --git a/pyrogram/client/types/messages_and_media/message_entity.py b/pyrogram/client/types/messages_and_media/message_entity.py
index f8f41734..7544424c 100644
--- a/pyrogram/client/types/messages_and_media/message_entity.py
+++ b/pyrogram/client/types/messages_and_media/message_entity.py
@@ -16,10 +16,14 @@
# 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
+import pyrogram
+
+from pyrogram.api import types
+from ..pyrogram_type import PyrogramType
+from ..user_and_chats.user import User
-class MessageEntity(Object):
+class MessageEntity(PyrogramType):
"""This object represents one special entity in a text message.
For example, hashtags, usernames, URLs, etc.
@@ -43,18 +47,50 @@ class MessageEntity(Object):
For "text_mention" only, the mentioned user.
"""
- ID = 0xb0700004
+ 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",
+ types.MessageEntityBold.ID: "bold",
+ types.MessageEntityItalic.ID: "italic",
+ types.MessageEntityCode.ID: "code",
+ types.MessageEntityPre.ID: "pre",
+ types.MessageEntityTextUrl.ID: "text_link",
+ types.MessageEntityMentionName.ID: "text_mention",
+ types.MessageEntityPhone.ID: "phone_number"
+ }
+
+ def __init__(self,
+ *,
+ client: "pyrogram.client.ext.BaseClient",
+ type: str,
+ offset: int,
+ length: int,
+ url: str = None,
+ user: User = None):
+ super().__init__(client)
- 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
+
+ @staticmethod
+ def _parse(client, entity, users: dict) -> "MessageEntity" or None:
+ type = MessageEntity.ENTITIES.get(entity.ID, None)
+
+ if type is None:
+ return None
+
+ return MessageEntity(
+ type=type,
+ offset=entity.offset,
+ length=entity.length,
+ url=getattr(entity, "url", None),
+ user=User._parse(client, users.get(getattr(entity, "user_id", None), None)),
+ client=client
+ )
diff --git a/pyrogram/client/types/messages_and_media/messages.py b/pyrogram/client/types/messages_and_media/messages.py
index 7a2546a9..31cfb3df 100644
--- a/pyrogram/client/types/messages_and_media/messages.py
+++ b/pyrogram/client/types/messages_and_media/messages.py
@@ -16,10 +16,16 @@
# 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
+from typing import List
+
+import pyrogram
+from pyrogram.api import types
+from .message import Message
+from ..pyrogram_type import PyrogramType
+from ..user_and_chats import Chat
-class Messages(Object):
+class Messages(PyrogramType):
"""This object represents a chat's messages.
Args:
@@ -30,8 +36,55 @@ class Messages(Object):
Requested messages.
"""
- ID = 0xb0700026
+ def __init__(self,
+ *,
+ client: "pyrogram.client.ext.BaseClient",
+ total_count: int,
+ messages: List[Message]):
+ super().__init__(client)
- def __init__(self, total_count: int, messages: list):
self.total_count = total_count
self.messages = messages
+
+ @staticmethod
+ async def _parse(client, messages: types.messages.Messages) -> "Messages":
+ users = {i.id: i for i in messages.users}
+ chats = {i.id: i for i in messages.chats}
+
+ # TODO: WTF! Py 3.5 doesn't support await inside comprehensions
+ parsed_messages = []
+
+ for message in messages.messages:
+ parsed_messages.append(await Message._parse(client, message, users, chats))
+
+ return Messages(
+ total_count=getattr(messages, "count", len(messages.messages)),
+ messages=parsed_messages,
+ client=client
+ )
+
+ @staticmethod
+ def _parse_deleted(client, update) -> "Messages":
+ messages = update.messages
+ channel_id = getattr(update, "channel_id", None)
+
+ parsed_messages = []
+
+ for message in messages:
+ parsed_messages.append(
+ Message(
+ message_id=message,
+ chat=Chat(
+ id=int("-100" + str(channel_id)),
+ type="channel",
+ client=client
+ ) if channel_id is not None else None,
+ client=client
+ )
+ )
+
+ return Messages(
+ total_count=len(parsed_messages),
+ messages=parsed_messages,
+ client=client
+ )
diff --git a/pyrogram/client/types/messages_and_media/photo.py b/pyrogram/client/types/messages_and_media/photo.py
index 4037025b..a52a7aa2 100644
--- a/pyrogram/client/types/messages_and_media/photo.py
+++ b/pyrogram/client/types/messages_and_media/photo.py
@@ -16,10 +16,18 @@
# 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
+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 ..pyrogram_type import PyrogramType
+from ...ext.utils import encode
-class Photo(Object):
+class Photo(PyrogramType):
"""This object represents a Photo.
Args:
@@ -33,9 +41,61 @@ class Photo(Object):
Available sizes of this photo.
"""
- ID = 0xb0700027
+ def __init__(self,
+ *,
+ client: "pyrogram.client.ext.BaseClient",
+ id: str,
+ date: int,
+ sizes: List[PhotoSize]):
+ super().__init__(client)
- def __init__(self, id: str, date: int, sizes: list):
self.id = id
self.date = date
self.sizes = sizes
+
+ @staticmethod
+ def _parse(client, photo: types.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 pyrogram.api.core import Object
+from struct import pack
+
+import pyrogram
+from pyrogram.api import types
+from pyrogram.client.ext.utils import encode
+from ..pyrogram_type import PyrogramType
-class PhotoSize(Object):
+class PhotoSize(PyrogramType):
"""This object represents one size of a photo or a file/sticker thumbnail.
Args:
@@ -36,10 +41,42 @@ class PhotoSize(Object):
File size.
"""
- ID = 0xb0700005
+ def __init__(self,
+ *,
+ client: "pyrogram.client.ext.BaseClient",
+ file_id: str,
+ width: int,
+ height: int,
+ file_size: int):
+ super().__init__(client)
- def __init__(self, file_id: str, width: int, height: int, file_size: int):
self.file_id = file_id
self.width = width
self.height = height
self.file_size = file_size
+
+ @staticmethod
+ def _parse(client, photo_size: types.PhotoSize or types.PhotoCachedSize):
+ if isinstance(photo_size, (types.PhotoSize, types.PhotoCachedSize)):
+
+ if isinstance(photo_size, types.PhotoSize):
+ file_size = photo_size.size
+ elif isinstance(photo_size, types.PhotoCachedSize):
+ file_size = len(photo_size.bytes)
+ else:
+ file_size = 0
+
+ loc = photo_size.location
+
+ if isinstance(loc, types.FileLocation):
+ return PhotoSize(
+ file_id=encode(
+ pack(
+ ".
-from pyrogram.api.core import Object
+from functools import lru_cache
+from struct import pack
+
+import pyrogram
+from pyrogram.api import types, functions
+from pyrogram.api.errors import StickersetInvalid
+from .photo_size import PhotoSize
+from ..pyrogram_type import PyrogramType
+from ...ext.utils import encode
-class Sticker(Object):
+class Sticker(PyrogramType):
"""This object represents a sticker.
Args:
@@ -55,22 +63,22 @@ class Sticker(Object):
"""
# TODO: Add mask position
- ID = 0xb0700017
- def __init__(
- self,
- file_id: str,
- width: int,
- height: int,
- thumb=None,
- file_name: str = None,
- mime_type: str = None,
- file_size: int = None,
- date: int = None,
- emoji: str = None,
- set_name: str = None,
- mask_position=None
- ):
+ def __init__(self,
+ *,
+ client: "pyrogram.client.ext.BaseClient",
+ file_id: str,
+ width: int,
+ height: int,
+ thumb: PhotoSize = None,
+ file_name: str = None,
+ mime_type: str = None,
+ file_size: int = None,
+ date: int = None,
+ emoji: str = None,
+ set_name: str = None):
+ super().__init__(client)
+
self.file_id = file_id
self.thumb = thumb
self.file_name = file_name
@@ -81,4 +89,50 @@ class Sticker(Object):
self.height = height
self.emoji = emoji
self.set_name = set_name
- self.mask_position = mask_position
+ # self.mask_position = mask_position
+
+ @staticmethod
+ @lru_cache(maxsize=256)
+ async def get_sticker_set_name(send, input_sticker_set_id):
+ try:
+ return await send(
+ functions.messages.GetStickerSet(
+ types.InputStickerSetID(*input_sticker_set_id)
+ )
+ ).set.short_name
+ except StickersetInvalid:
+ return None
+
+ @staticmethod
+ async def _parse(client, sticker: types.Document, image_size_attributes: types.DocumentAttributeImageSize,
+ sticker_attributes: types.DocumentAttributeSticker, file_name: str) -> "Sticker":
+ sticker_set = sticker_attributes.stickerset
+
+ if isinstance(sticker_set, types.InputStickerSetID):
+ input_sticker_set_id = (sticker_set.id, sticker_set.access_hash)
+ set_name = await Sticker.get_sticker_set_name(client.send, input_sticker_set_id)
+ else:
+ set_name = None
+
+ return Sticker(
+ file_id=encode(
+ pack(
+ ".
-from pyrogram.api.core import Object
+from typing import List
+
+import pyrogram
+from .photo import Photo
+from ..pyrogram_type import PyrogramType
-class UserProfilePhotos(Object):
+class UserProfilePhotos(PyrogramType):
"""This object represents a user's profile pictures.
Args:
@@ -30,8 +34,20 @@ class UserProfilePhotos(Object):
Requested profile pictures.
"""
- ID = 0xb0700014
+ def __init__(self,
+ *,
+ client: "pyrogram.client.ext.BaseClient",
+ total_count: int,
+ photos: List[Photo]):
+ super().__init__(client)
- def __init__(self, total_count: int, photos: list):
self.total_count = total_count
self.photos = photos
+
+ @staticmethod
+ def _parse(client, photos) -> "UserProfilePhotos":
+ return UserProfilePhotos(
+ total_count=getattr(photos, "count", len(photos.photos)),
+ photos=[Photo._parse(client, photo) for photo in photos.photos],
+ client=client
+ )
diff --git a/pyrogram/client/types/messages_and_media/venue.py b/pyrogram/client/types/messages_and_media/venue.py
index 3c5b2b05..443f479a 100644
--- a/pyrogram/client/types/messages_and_media/venue.py
+++ b/pyrogram/client/types/messages_and_media/venue.py
@@ -16,10 +16,13 @@
# 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
+import pyrogram
+from pyrogram.api import types
+from .location import Location
+from ..pyrogram_type import PyrogramType
-class Venue(Object):
+class Venue(PyrogramType):
"""This object represents a venue.
Args:
@@ -41,18 +44,29 @@ class Venue(Object):
"""
- ID = 0xb0700013
+ def __init__(self,
+ *,
+ client: "pyrogram.client.ext.BaseClient",
+ location: Location,
+ title: str,
+ address: str,
+ foursquare_id: str = None,
+ foursquare_type: str = None):
+ super().__init__(client)
- def __init__(
- self,
- location,
- title: str,
- address: str,
- foursquare_id: str = None,
- foursquare_type: str = None
- ):
self.location = location
self.title = title
self.address = address
self.foursquare_id = foursquare_id
self.foursquare_type = foursquare_type
+
+ @staticmethod
+ def _parse(client, venue: types.MessageMediaVenue):
+ return Venue(
+ location=Location._parse(client, venue.geo),
+ title=venue.title,
+ address=venue.address,
+ foursquare_id=venue.venue_id or None,
+ foursquare_type=venue.venue_type,
+ client=client
+ )
diff --git a/pyrogram/client/types/messages_and_media/video.py b/pyrogram/client/types/messages_and_media/video.py
index 8b272a2d..2c476b39 100644
--- a/pyrogram/client/types/messages_and_media/video.py
+++ b/pyrogram/client/types/messages_and_media/video.py
@@ -16,10 +16,16 @@
# 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
+from struct import pack
+
+import pyrogram
+from pyrogram.api import types
+from .photo_size import PhotoSize
+from ..pyrogram_type import PyrogramType
+from ...ext.utils import encode
-class Video(Object):
+class Video(PyrogramType):
"""This object represents a video file.
Args:
@@ -51,20 +57,20 @@ class Video(Object):
Date the video was sent in Unix time.
"""
- ID = 0xb0700008
+ def __init__(self,
+ *,
+ client: "pyrogram.client.ext.BaseClient",
+ file_id: str,
+ width: int,
+ height: int,
+ duration: int,
+ thumb: PhotoSize = None,
+ file_name: str = None,
+ mime_type: str = None,
+ file_size: int = None,
+ date: int = None):
+ super().__init__(client)
- def __init__(
- self,
- file_id: str,
- width: int,
- height: 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
self.thumb = thumb
self.file_name = file_name
@@ -74,3 +80,27 @@ class Video(Object):
self.width = width
self.height = height
self.duration = duration
+
+ @staticmethod
+ def _parse(client, video: types.Document, video_attributes: types.DocumentAttributeVideo,
+ file_name: str) -> "Video":
+ return Video(
+ file_id=encode(
+ pack(
+ ".
-from pyrogram.api.core import Object
+from struct import pack
+
+import pyrogram
+from pyrogram.api import types
+from .photo_size import PhotoSize
+from ..pyrogram_type import PyrogramType
+from ...ext.utils import encode
-class VideoNote(Object):
+class VideoNote(PyrogramType):
"""This object represents a video message (available in Telegram apps as of v.4.0).
Args:
@@ -45,18 +51,18 @@ class VideoNote(Object):
Date the video note was sent in Unix time.
"""
- ID = 0xb0700010
+ def __init__(self,
+ *,
+ client: "pyrogram.client.ext.BaseClient",
+ file_id: str,
+ length: int,
+ duration: int,
+ thumb: PhotoSize = None,
+ mime_type: str = None,
+ file_size: int = None,
+ date: int = None):
+ super().__init__(client)
- def __init__(
- self,
- file_id: str,
- length: int,
- duration: int,
- thumb=None,
- mime_type: str = None,
- file_size: int = None,
- date: int = None
- ):
self.file_id = file_id
self.thumb = thumb
self.mime_type = mime_type
@@ -64,3 +70,24 @@ class VideoNote(Object):
self.date = date
self.length = length
self.duration = duration
+
+ @staticmethod
+ def _parse(client, video_note: types.Document, video_attributes: types.DocumentAttributeVideo) -> "VideoNote":
+ return VideoNote(
+ file_id=encode(
+ pack(
+ ".
-from pyrogram.api.core import Object
+from struct import pack
+
+import pyrogram
+from pyrogram.api import types
+from ..pyrogram_type import PyrogramType
+from ...ext.utils import encode
-class Voice(Object):
+class Voice(PyrogramType):
"""This object represents a voice note.
Args:
@@ -42,19 +47,40 @@ class Voice(Object):
Date the voice was sent in Unix time.
"""
- ID = 0xb0700009
+ def __init__(self,
+ *,
+ client: "pyrogram.client.ext.BaseClient",
+ file_id: str,
+ duration: int,
+ waveform: bytes = None,
+ mime_type: str = None,
+ file_size: int = None,
+ date: int = None):
+ super().__init__(client)
- def __init__(
- self,
- file_id: str,
- duration: int,
- waveform: bytes = None,
- mime_type: str = None,
- file_size: int = None,
- date: int = None):
self.file_id = file_id
self.duration = duration
self.waveform = waveform
self.mime_type = mime_type
self.file_size = file_size
self.date = date
+
+ @staticmethod
+ def _parse(client, voice: types.Document, attributes: types.DocumentAttributeAudio) -> "Voice":
+ return Voice(
+ file_id=encode(
+ pack(
+ "
+#
+# 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 collections import OrderedDict
+from json import dumps, JSONEncoder
+
+
+class PyrogramType:
+ def __init__(self, client):
+ self._client = client
+
+ def __str__(self):
+ return dumps(self, cls=Encoder, indent=4)
+
+ def __getitem__(self, item):
+ return getattr(self, item)
+
+
+def remove_none(obj):
+ if isinstance(obj, (list, tuple, set)):
+ return type(obj)(remove_none(x) for x in obj if x is not None)
+ elif isinstance(obj, dict):
+ return type(obj)((remove_none(k), remove_none(v)) for k, v in obj.items() if k is not None and v is not None)
+ else:
+ return obj
+
+
+class Encoder(JSONEncoder):
+ def default(self, o: PyrogramType):
+ try:
+ content = {
+ i: getattr(o, i)
+ for i in filter(lambda x: not x.startswith("_"), o.__dict__)
+ }
+ except AttributeError:
+ return repr(o)
+
+ return remove_none(
+ OrderedDict(
+ [("_", "pyrogram." + o.__class__.__name__)]
+ + [i for i in content.items()]
+ )
+ )
diff --git a/pyrogram/client/types/update.py b/pyrogram/client/types/update.py
deleted file mode 100644
index 748108de..00000000
--- a/pyrogram/client/types/update.py
+++ /dev/null
@@ -1,94 +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 pyrogram.api.core import Object
-
-
-class Update(Object):
- """This object represents an incoming update.
- At most one of the optional parameters can be present in any given update.
-
- Args:
- message (:obj:`Message `, *optional*):
- New incoming message of any kind — text, photo, sticker, etc.
-
- edited_message (:obj:`Message `, *optional*):
- New version of a message that is known to the bot and was edited.
-
- deleted_messages (:obj:`Messages `, *optional*):
- Deleted messages.
-
- channel_post (:obj:`Message `, *optional*):
- New incoming channel post of any kind — text, photo, sticker, etc.
-
- edited_channel_post (:obj:`Message `, *optional*):
- New version of a channel post that is known to the bot and was edited.
-
- deleted_channel_posts (:obj:`Messages `, *optional*):
- Deleted channel posts.
-
- inline_query (:obj:`InlineQuery `, *optional*):
- New incoming inline query.
-
- chosen_inline_result (:obj:`ChosenInlineResult `, *optional*):
- The result of an inline query that was chosen by a user and sent to their chat partner.
- Please see our documentation on the feedback collecting for details on how to enable these updates
- for your bot.
-
- callback_query (:obj:`CallbackQuery `, *optional*):
- New incoming callback query.
-
- shipping_query (:obj:`ShippingQuery `, *optional*):
- New incoming shipping query. Only for invoices with flexible price.
-
- pre_checkout_query (:obj:`PreCheckoutQuery `, *optional*):
- New incoming pre-checkout query. Contains full information about checkout.
-
- user_status (:obj:`UserStatus `, *optional*):
- User status (last seen date) update.
- """
-
- ID = 0xb0700000
-
- def __init__(
- self,
- message=None,
- edited_message=None,
- deleted_messages=None,
- channel_post=None,
- edited_channel_post=None,
- deleted_channel_posts=None,
- inline_query=None,
- chosen_inline_result=None,
- callback_query=None,
- shipping_query=None,
- pre_checkout_query=None,
- user_status=None
- ):
- self.message = message
- self.edited_message = edited_message
- self.deleted_messages = deleted_messages
- self.channel_post = channel_post
- self.edited_channel_post = edited_channel_post
- self.deleted_channel_posts = deleted_channel_posts
- self.inline_query = inline_query
- self.chosen_inline_result = chosen_inline_result
- self.callback_query = callback_query
- self.shipping_query = shipping_query
- self.pre_checkout_query = pre_checkout_query
- self.user_status = user_status
diff --git a/pyrogram/client/types/user_and_chats/chat.py b/pyrogram/client/types/user_and_chats/chat.py
index 68eaa775..5b5a54a8 100644
--- a/pyrogram/client/types/user_and_chats/chat.py
+++ b/pyrogram/client/types/user_and_chats/chat.py
@@ -16,10 +16,13 @@
# 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
+import pyrogram
+from pyrogram.api import types
+from .chat_photo import ChatPhoto
+from ..pyrogram_type import PyrogramType
-class Chat(Object):
+class Chat(PyrogramType):
"""This object represents a chat.
Args:
@@ -74,26 +77,26 @@ class Chat(Object):
The reason why this chat might be unavailable to some users.
"""
- ID = 0xb0700002
+ def __init__(self,
+ *,
+ client: "pyrogram.client.ext.BaseClient",
+ id: int,
+ type: str,
+ title: str = None,
+ username: str = None,
+ first_name: str = None,
+ last_name: str = None,
+ all_members_are_administrators: bool = None,
+ photo: ChatPhoto = None,
+ description: str = None,
+ invite_link: str = None,
+ pinned_message=None,
+ sticker_set_name: str = None,
+ can_set_sticker_set: bool = None,
+ members_count: int = None,
+ restriction_reason: str = None):
+ super().__init__(client)
- def __init__(
- self,
- id: int,
- type: str,
- title: str = None,
- username: str = None,
- first_name: str = None,
- last_name: str = None,
- all_members_are_administrators: bool = None,
- photo=None,
- description: str = None,
- invite_link: str = None,
- pinned_message=None,
- sticker_set_name: str = None,
- can_set_sticker_set: bool = None,
- members_count: int = None,
- restriction_reason: str = None
- ):
self.id = id
self.type = type
self.title = title
@@ -109,3 +112,100 @@ class Chat(Object):
self.can_set_sticker_set = can_set_sticker_set
self.members_count = members_count
self.restriction_reason = restriction_reason
+
+ @staticmethod
+ def _parse_user_chat(client, user: types.User) -> "Chat":
+ return Chat(
+ id=user.id,
+ type="private",
+ username=user.username,
+ first_name=user.first_name,
+ last_name=user.last_name,
+ photo=ChatPhoto._parse(client, user.photo),
+ restriction_reason=user.restriction_reason,
+ client=client
+ )
+
+ @staticmethod
+ def _parse_chat_chat(client, chat: types.Chat) -> "Chat":
+ admins_enabled = getattr(chat, "admins_enabled", None)
+
+ if admins_enabled is not None:
+ admins_enabled = not admins_enabled
+
+ return Chat(
+ id=-chat.id,
+ type="group",
+ title=chat.title,
+ all_members_are_administrators=admins_enabled,
+ photo=ChatPhoto._parse(client, getattr(chat, "photo", None)),
+ client=client
+ )
+
+ @staticmethod
+ def _parse_channel_chat(client, channel: types.Channel) -> "Chat":
+ return Chat(
+ id=int("-100" + str(channel.id)),
+ type="supergroup" if channel.megagroup else "channel",
+ title=channel.title,
+ username=getattr(channel, "username", None),
+ photo=ChatPhoto._parse(client, getattr(channel, "photo", None)),
+ restriction_reason=getattr(channel, "restriction_reason", None),
+ client=client
+ )
+
+ @staticmethod
+ def _parse(client, message: types.Message or types.MessageService, users: dict, chats: dict) -> "Chat":
+ if isinstance(message.to_id, types.PeerUser):
+ return Chat._parse_user_chat(client, users[message.to_id.user_id if message.out else message.from_id])
+
+ if isinstance(message.to_id, types.PeerChat):
+ return Chat._parse_chat_chat(client, chats[message.to_id.chat_id])
+
+ return Chat._parse_channel_chat(client, chats[message.to_id.channel_id])
+
+ @staticmethod
+ def _parse_dialog(client, peer, users: dict, chats: dict):
+ if isinstance(peer, types.PeerUser):
+ return Chat._parse_user_chat(client, users[peer.user_id])
+ elif isinstance(peer, types.PeerChat):
+ return Chat._parse_chat_chat(client, chats[peer.chat_id])
+ else:
+ return Chat._parse_channel_chat(client, chats[peer.channel_id])
+
+ @staticmethod
+ def _parse_full(client, chat_full: types.messages.ChatFull or types.UserFull) -> "Chat":
+ if isinstance(chat_full, types.UserFull):
+ parsed_chat = Chat._parse_user_chat(client, chat_full.user)
+ parsed_chat.description = chat_full.about
+ else:
+ full_chat = chat_full.full_chat
+ chat = None
+
+ for i in chat_full.chats:
+ if full_chat.id == i.id:
+ chat = i
+
+ if isinstance(full_chat, types.ChatFull):
+ parsed_chat = Chat._parse_chat_chat(client, chat)
+
+ if isinstance(full_chat.participants, types.ChatParticipants):
+ parsed_chat.members_count = len(full_chat.participants.participants)
+ else:
+ parsed_chat = Chat._parse_channel_chat(client, chat)
+ parsed_chat.members_count = full_chat.participants_count
+ parsed_chat.description = full_chat.about or None
+ # TODO: Add StickerSet type
+ parsed_chat.can_set_sticker_set = full_chat.can_set_stickers
+ parsed_chat.sticker_set_name = full_chat.stickerset
+
+ if full_chat.pinned_msg_id:
+ parsed_chat.pinned_message = client.get_messages(
+ parsed_chat.id,
+ message_ids=full_chat.pinned_msg_id
+ )
+
+ if isinstance(full_chat.exported_invite, types.ChatInviteExported):
+ parsed_chat.invite_link = full_chat.exported_invite.link
+
+ return parsed_chat
diff --git a/pyrogram/client/types/user_and_chats/chat_member.py b/pyrogram/client/types/user_and_chats/chat_member.py
index 71267d27..fa43f526 100644
--- a/pyrogram/client/types/user_and_chats/chat_member.py
+++ b/pyrogram/client/types/user_and_chats/chat_member.py
@@ -16,10 +16,13 @@
# 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
+import pyrogram
+
+from pyrogram.api import types
+from ..pyrogram_type import PyrogramType
-class ChatMember(Object):
+class ChatMember(PyrogramType):
"""This object contains information about one member of a chat.
Args:
@@ -78,40 +81,92 @@ class ChatMember(Object):
Restricted only. True, if user may add web page previews to his messages, implies can_send_media_messages.
"""
- ID = 0xb0700016
+ def __init__(self,
+ *,
+ client: "pyrogram.client.ext.BaseClient",
+ user: "pyrogram.User",
+ status: str,
+ until_date: int = None,
+ can_be_edited: bool = None,
+ can_change_info: bool = None,
+ can_post_messages: bool = None,
+ can_edit_messages: bool = None,
+ can_delete_messages: bool = None,
+ can_invite_users: bool = None,
+ can_restrict_members: bool = None,
+ can_pin_messages: bool = None,
+ can_promote_members: bool = None,
+ can_send_messages: bool = None,
+ can_send_media_messages: bool = None,
+ can_send_other_messages: bool = None,
+ can_add_web_page_previews: bool = None):
+ super().__init__(client)
- def __init__(
- self,
- user,
- status: str,
- until_date: int = None,
- can_be_edited: bool = None,
- can_change_info: bool = None,
- can_post_messages: bool = None,
- can_edit_messages: bool = None,
- can_delete_messages: bool = None,
- can_invite_users: bool = None,
- can_restrict_members: bool = None,
- can_pin_messages: bool = None,
- can_promote_members: bool = None,
- can_send_messages: bool = None,
- can_send_media_messages: bool = None,
- can_send_other_messages: bool = None,
- can_add_web_page_previews: bool = None
- ):
- self.user = user # User
- self.status = status # string
- self.until_date = until_date # flags.0?int
- self.can_be_edited = can_be_edited # flags.1?Bool
- self.can_change_info = can_change_info # flags.2?Bool
- self.can_post_messages = can_post_messages # flags.3?Bool
- self.can_edit_messages = can_edit_messages # flags.4?Bool
- self.can_delete_messages = can_delete_messages # flags.5?Bool
- self.can_invite_users = can_invite_users # flags.6?Bool
- self.can_restrict_members = can_restrict_members # flags.7?Bool
- self.can_pin_messages = can_pin_messages # flags.8?Bool
- self.can_promote_members = can_promote_members # flags.9?Bool
- self.can_send_messages = can_send_messages # flags.10?Bool
- self.can_send_media_messages = can_send_media_messages # flags.11?Bool
- self.can_send_other_messages = can_send_other_messages # flags.12?Bool
- self.can_add_web_page_previews = can_add_web_page_previews # flags.13?Bool
+ self.user = user
+ self.status = status
+ self.until_date = until_date
+ self.can_be_edited = can_be_edited
+ self.can_change_info = can_change_info
+ self.can_post_messages = can_post_messages
+ self.can_edit_messages = can_edit_messages
+ self.can_delete_messages = can_delete_messages
+ self.can_invite_users = can_invite_users
+ self.can_restrict_members = can_restrict_members
+ self.can_pin_messages = can_pin_messages
+ self.can_promote_members = can_promote_members
+ self.can_send_messages = can_send_messages
+ self.can_send_media_messages = can_send_media_messages
+ self.can_send_other_messages = can_send_other_messages
+ self.can_add_web_page_previews = can_add_web_page_previews
+
+ @staticmethod
+ def _parse(client, member, user) -> "ChatMember":
+ user = pyrogram.User._parse(client, user)
+
+ if isinstance(member, (types.ChannelParticipant, types.ChannelParticipantSelf, types.ChatParticipant)):
+ return ChatMember(user=user, status="member", client=client)
+
+ if isinstance(member, (types.ChannelParticipantCreator, types.ChatParticipantCreator)):
+ return ChatMember(user=user, status="creator", client=client)
+
+ if isinstance(member, types.ChatParticipantAdmin):
+ return ChatMember(user=user, status="administrator", client=client)
+
+ if isinstance(member, types.ChannelParticipantAdmin):
+ rights = member.admin_rights
+
+ return 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,
+ client=client
+ )
+
+ if isinstance(member, types.ChannelParticipantBanned):
+ rights = member.banned_rights
+
+ chat_member = 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,
+ client=client
+ )
+
+ 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
+
+ return chat_member
diff --git a/pyrogram/client/types/user_and_chats/chat_members.py b/pyrogram/client/types/user_and_chats/chat_members.py
index 622f8abc..838517ab 100644
--- a/pyrogram/client/types/user_and_chats/chat_members.py
+++ b/pyrogram/client/types/user_and_chats/chat_members.py
@@ -16,10 +16,16 @@
# 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
+from typing import List
+
+import pyrogram
+from pyrogram.api import types
+from .chat_member import ChatMember
+from .user import User
+from ..pyrogram_type import PyrogramType
-class ChatMembers(Object):
+class ChatMembers(PyrogramType):
"""This object contains information about the members list of a chat.
Args:
@@ -30,8 +36,34 @@ class ChatMembers(Object):
Requested chat members.
"""
- ID = 0xb0700030
+ def __init__(self,
+ *,
+ client: "pyrogram.client.ext.BaseClient",
+ total_count: int,
+ chat_members: List[ChatMember]):
+ super().__init__(client)
- def __init__(self, total_count: int, chat_members: list):
self.total_count = total_count
self.chat_members = chat_members
+
+ @staticmethod
+ def _parse(client, members):
+ users = {i.id: i for i in members.users}
+ chat_members = []
+
+ if isinstance(members, types.channels.ChannelParticipants):
+ total_count = members.count
+ members = members.participants
+ else:
+ members = members.full_chat.participants.participants
+ total_count = len(members)
+
+ for member in members:
+ user = User._parse(client, users[member.user_id])
+ chat_members.append(ChatMember._parse(client, member, user))
+
+ return ChatMembers(
+ total_count=total_count,
+ chat_members=chat_members,
+ client=client
+ )
diff --git a/pyrogram/client/types/user_and_chats/chat_photo.py b/pyrogram/client/types/user_and_chats/chat_photo.py
index e5877309..ad4b3151 100644
--- a/pyrogram/client/types/user_and_chats/chat_photo.py
+++ b/pyrogram/client/types/user_and_chats/chat_photo.py
@@ -16,10 +16,15 @@
# 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
+from struct import pack
+
+import pyrogram
+from pyrogram.api import types
+from ..pyrogram_type import PyrogramType
+from ...ext.utils import encode
-class ChatPhoto(Object):
+class ChatPhoto(PyrogramType):
"""This object represents a chat photo.
Args:
@@ -30,8 +35,43 @@ class ChatPhoto(Object):
Unique file identifier of big (640x640) chat photo. This file_id can be used only for photo download.
"""
- ID = 0xb0700015
+ def __init__(self,
+ *,
+ client: "pyrogram.client.ext.BaseClient",
+ small_file_id: str,
+ big_file_id: str):
+ super().__init__(client)
- def __init__(self, small_file_id: str, big_file_id: str):
- self.small_file_id = small_file_id # string
- self.big_file_id = big_file_id # string
+ self.small_file_id = small_file_id
+ self.big_file_id = big_file_id
+
+ @staticmethod
+ def _parse(client, chat_photo: types.UserProfilePhoto or types.ChatPhoto):
+ 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(
+ ".
-from pyrogram.api.core import Object
+import pyrogram
+
+from pyrogram.api import types
+from ..pyrogram_type import PyrogramType
+from ..user_and_chats import Chat
-class Dialog(Object):
+class Dialog(PyrogramType):
"""This object represents a dialog.
Args:
@@ -41,18 +45,42 @@ class Dialog(Object):
is_pinned (``bool``):
True, if the dialog is pinned.
"""
- ID = 0xb0700028
def __init__(self,
- chat,
- top_message,
+ *,
+ client: "pyrogram.client.ext.BaseClient",
+ chat: Chat,
+ top_message: "pyrogram.Message",
unread_messages_count: int,
unread_mentions_count: int,
unread_mark: bool,
is_pinned: bool):
+ super().__init__(client)
+
self.chat = chat
self.top_message = top_message
self.unread_messages_count = unread_messages_count
self.unread_mentions_count = unread_mentions_count
self.unread_mark = unread_mark
self.is_pinned = is_pinned
+
+ @staticmethod
+ def _parse(client, dialog, messages, users, chats) -> "Dialog":
+ chat_id = dialog.peer
+
+ if isinstance(chat_id, types.PeerUser):
+ chat_id = chat_id.user_id
+ elif isinstance(chat_id, types.PeerChat):
+ chat_id = -chat_id.chat_id
+ else:
+ chat_id = int("-100" + str(chat_id.channel_id))
+
+ return Dialog(
+ chat=Chat._parse_dialog(client, dialog.peer, users, chats),
+ top_message=messages.get(chat_id),
+ unread_messages_count=dialog.unread_count,
+ unread_mentions_count=dialog.unread_mentions_count,
+ unread_mark=dialog.unread_mark,
+ is_pinned=dialog.pinned,
+ client=client
+ )
diff --git a/pyrogram/client/types/user_and_chats/dialogs.py b/pyrogram/client/types/user_and_chats/dialogs.py
index cdf1d951..2492d5e2 100644
--- a/pyrogram/client/types/user_and_chats/dialogs.py
+++ b/pyrogram/client/types/user_and_chats/dialogs.py
@@ -16,10 +16,16 @@
# 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
+from typing import List
+
+import pyrogram
+from pyrogram.api import types
+from .dialog import Dialog
+from ..messages_and_media import Message
+from ..pyrogram_type import PyrogramType
-class Dialogs(Object):
+class Dialogs(PyrogramType):
"""This object represents a user's dialogs chunk
Args:
@@ -29,8 +35,41 @@ class Dialogs(Object):
dialogs (List of :obj:`Dialog `):
Requested dialogs.
"""
- ID = 0xb0700029
- def __init__(self, total_count: int, dialogs: list):
+ def __init__(self,
+ *,
+ client: "pyrogram.client.ext.BaseClient",
+ total_count: int,
+ dialogs: List[Dialog]):
+ super().__init__(client)
+
self.total_count = total_count
self.dialogs = dialogs
+
+ @staticmethod
+ def _parse(client, dialogs) -> "Dialogs":
+ users = {i.id: i for i in dialogs.users}
+ chats = {i.id: i for i in dialogs.chats}
+
+ messages = {}
+
+ for message in dialogs.messages:
+ to_id = message.to_id
+
+ if isinstance(to_id, types.PeerUser):
+ if message.out:
+ chat_id = to_id.user_id
+ else:
+ chat_id = message.from_id
+ elif isinstance(to_id, types.PeerChat):
+ chat_id = -to_id.chat_id
+ else:
+ chat_id = int("-100" + str(to_id.channel_id))
+
+ messages[chat_id] = Message._parse(client, message, 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],
+ client=client
+ )
diff --git a/pyrogram/client/types/user_and_chats/user.py b/pyrogram/client/types/user_and_chats/user.py
index 06045b00..354e8a09 100644
--- a/pyrogram/client/types/user_and_chats/user.py
+++ b/pyrogram/client/types/user_and_chats/user.py
@@ -16,10 +16,14 @@
# 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
+import pyrogram
+from pyrogram.api import types
+from .chat_photo import ChatPhoto
+from .user_status import UserStatus
+from ..pyrogram_type import PyrogramType
-class User(Object):
+class User(PyrogramType):
"""This object represents a Telegram user or bot.
Args:
@@ -66,25 +70,25 @@ class User(Object):
The reason why this bot might be unavailable to some users.
"""
- ID = 0xb0700001
+ def __init__(self,
+ *,
+ client: "pyrogram.client.ext.BaseClient",
+ 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,
+ status: UserStatus = None,
+ username: str = None,
+ language_code: str = None,
+ phone_number: str = None,
+ photo: ChatPhoto = None,
+ restriction_reason: str = None):
+ super().__init__(client)
- def __init__(
- self,
- id: int,
- is_self: bool,
- is_contact: bool,
- is_mutual_contact: bool,
- is_deleted: bool,
- is_bot: bool,
- first_name: str,
- status=None,
- last_name: str = None,
- username: str = None,
- language_code: str = None,
- phone_number: str = None,
- photo=None,
- restriction_reason: str = None
- ):
self.id = id
self.is_self = is_self
self.is_contact = is_contact
@@ -92,10 +96,33 @@ class User(Object):
self.is_deleted = is_deleted
self.is_bot = is_bot
self.first_name = first_name
- self.status = status
self.last_name = last_name
+ self.status = status
self.username = username
self.language_code = language_code
self.phone_number = phone_number
self.photo = photo
self.restriction_reason = restriction_reason
+
+ @staticmethod
+ def _parse(client, user: types.User) -> "User" or None:
+ if user is None:
+ return None
+
+ return 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,
+ 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),
+ restriction_reason=user.restriction_reason,
+ client=client
+ )
diff --git a/pyrogram/client/types/user_and_chats/user_status.py b/pyrogram/client/types/user_and_chats/user_status.py
index cc96df52..69c1921b 100644
--- a/pyrogram/client/types/user_and_chats/user_status.py
+++ b/pyrogram/client/types/user_and_chats/user_status.py
@@ -16,10 +16,13 @@
# 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
+import pyrogram
+
+from pyrogram.api import types
+from ..pyrogram_type import PyrogramType
-class UserStatus(Object):
+class UserStatus(PyrogramType):
"""This object represents a User status (Last Seen privacy).
.. note::
@@ -28,8 +31,8 @@ class UserStatus(Object):
"recently", "within_week", "within_month" or "long_time_ago" fields set.
Args:
- user_id (``int``, *optional*):
- User's id. Only available for incoming UserStatus updates.
+ user_id (``int``):
+ User's id.
online (``bool``, *optional*):
True if the user is online in this very moment, None otherwise.
@@ -61,19 +64,19 @@ class UserStatus(Object):
always shown to blocked users), None otherwise.
"""
- ID = 0xb0700031
+ def __init__(self,
+ *,
+ client: "pyrogram.client.ext.BaseClient",
+ user_id: int,
+ online: bool = None,
+ offline: bool = None,
+ date: int = None,
+ recently: bool = None,
+ within_week: bool = None,
+ within_month: bool = None,
+ long_time_ago: bool = None):
+ super().__init__(client)
- def __init__(
- self,
- user_id: int = None,
- online: bool = None,
- offline: bool = None,
- date: int = None,
- recently: bool = None,
- within_week: bool = None,
- within_month: bool = None,
- long_time_ago: bool = None
- ):
self.user_id = user_id
self.online = online
self.offline = offline
@@ -82,3 +85,27 @@ class UserStatus(Object):
self.within_week = within_week
self.within_month = within_month
self.long_time_ago = long_time_ago
+
+ @staticmethod
+ def _parse(client, user_status, user_id: int, is_bot: bool = False):
+ if is_bot:
+ return None
+
+ status = UserStatus(user_id=user_id, client=client)
+
+ if isinstance(user_status, types.UserStatusOnline):
+ status.online = True
+ status.date = user_status.expires
+ elif isinstance(user_status, types.UserStatusOffline):
+ status.offline = True
+ status.date = user_status.was_online
+ elif isinstance(user_status, types.UserStatusRecently):
+ status.recently = True
+ elif isinstance(user_status, types.UserStatusLastWeek):
+ status.within_week = True
+ elif isinstance(user_status, types.UserStatusLastMonth):
+ status.within_month = True
+ else:
+ status.long_time_ago = True
+
+ return status
diff --git a/requirements.txt b/requirements.txt
index 17447fdf..8f1eea95 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,2 +1,3 @@
pyaes==1.6.1
pysocks==1.6.8
+typing==3.6.6
\ No newline at end of file