Merge branch 'develop' into asyncio

# Conflicts:
#	pyrogram/client/client.py
#	pyrogram/client/dispatcher/dispatcher.py
#	pyrogram/client/ext/utils.py
#	pyrogram/client/methods/bots/get_inline_bot_results.py
#	pyrogram/client/methods/bots/request_callback_answer.py
#	pyrogram/client/methods/bots/send_inline_bot_result.py
#	pyrogram/client/methods/chats/delete_chat_photo.py
#	pyrogram/client/methods/chats/export_chat_invite_link.py
#	pyrogram/client/methods/chats/get_chat.py
#	pyrogram/client/methods/chats/get_chat_member.py
#	pyrogram/client/methods/chats/get_chat_members.py
#	pyrogram/client/methods/chats/get_chat_members_count.py
#	pyrogram/client/methods/chats/get_dialogs.py
#	pyrogram/client/methods/chats/join_chat.py
#	pyrogram/client/methods/chats/kick_chat_member.py
#	pyrogram/client/methods/chats/leave_chat.py
#	pyrogram/client/methods/chats/pin_chat_message.py
#	pyrogram/client/methods/chats/promote_chat_member.py
#	pyrogram/client/methods/chats/restrict_chat_member.py
#	pyrogram/client/methods/chats/set_chat_description.py
#	pyrogram/client/methods/chats/set_chat_photo.py
#	pyrogram/client/methods/chats/set_chat_title.py
#	pyrogram/client/methods/chats/unban_chat_member.py
#	pyrogram/client/methods/chats/unpin_chat_message.py
#	pyrogram/client/methods/contacts/add_contacts.py
#	pyrogram/client/methods/contacts/delete_contacts.py
#	pyrogram/client/methods/messages/delete_messages.py
#	pyrogram/client/methods/messages/edit_message_caption.py
#	pyrogram/client/methods/messages/edit_message_media.py
#	pyrogram/client/methods/messages/edit_message_reply_markup.py
#	pyrogram/client/methods/messages/edit_message_text.py
#	pyrogram/client/methods/messages/forward_messages.py
#	pyrogram/client/methods/messages/get_history.py
#	pyrogram/client/methods/messages/get_messages.py
#	pyrogram/client/methods/messages/send_animation.py
#	pyrogram/client/methods/messages/send_audio.py
#	pyrogram/client/methods/messages/send_chat_action.py
#	pyrogram/client/methods/messages/send_contact.py
#	pyrogram/client/methods/messages/send_document.py
#	pyrogram/client/methods/messages/send_location.py
#	pyrogram/client/methods/messages/send_media_group.py
#	pyrogram/client/methods/messages/send_message.py
#	pyrogram/client/methods/messages/send_photo.py
#	pyrogram/client/methods/messages/send_sticker.py
#	pyrogram/client/methods/messages/send_venue.py
#	pyrogram/client/methods/messages/send_video.py
#	pyrogram/client/methods/messages/send_video_note.py
#	pyrogram/client/methods/messages/send_voice.py
#	pyrogram/client/methods/password/change_cloud_password.py
#	pyrogram/client/methods/password/enable_cloud_password.py
#	pyrogram/client/methods/password/remove_cloud_password.py
#	pyrogram/client/methods/users/delete_user_profile_photos.py
#	pyrogram/client/methods/users/get_me.py
#	pyrogram/client/methods/users/get_user_profile_photos.py
#	pyrogram/client/methods/users/get_users.py
#	pyrogram/client/methods/utilities/download_media.py
#	pyrogram/client/types/messages_and_media/message.py
This commit is contained in:
Dan 2018-12-22 12:23:08 +01:00
commit e6667be10b
102 changed files with 2137 additions and 1956 deletions

View File

@ -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():

View File

@ -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
)

View File

@ -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

View File

@ -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,

File diff suppressed because it is too large Load Diff

View File

@ -16,6 +16,8 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
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,

View File

@ -16,13 +16,15 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
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

View File

@ -16,13 +16,15 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
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,

View File

@ -16,12 +16,15 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
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.

View File

@ -16,12 +16,15 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
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.

View File

@ -16,12 +16,16 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
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)

View File

@ -16,14 +16,17 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
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))

View File

@ -16,8 +16,11 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
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,

View File

@ -16,12 +16,15 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
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:

View File

@ -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)

View File

@ -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:

View File

@ -16,16 +16,18 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
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}

View File

@ -16,12 +16,16 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
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:

View File

@ -16,12 +16,17 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
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.

View File

@ -16,14 +16,16 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
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.

View File

@ -16,19 +16,21 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
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.

View File

@ -16,12 +16,16 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
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.

View File

@ -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.

View File

@ -16,12 +16,16 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
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.

View File

@ -16,14 +16,16 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
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.

View File

@ -16,12 +16,15 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
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.

View File

@ -16,17 +16,21 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
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 <pyrogram.InputPhoneContact>`
contacts (List of :obj:`InputPhoneContact <pyrogram.InputPhoneContact>`):
The contact list to be added
Returns:
On success, the added contacts are returned.

View File

@ -16,17 +16,20 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
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).

View File

@ -16,13 +16,18 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
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

View File

@ -16,13 +16,18 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
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

View File

@ -17,17 +17,18 @@
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
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:

View File

@ -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`.

View File

@ -16,12 +16,16 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
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

View File

@ -16,13 +16,18 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
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

View File

@ -16,15 +16,17 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
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.

View File

@ -16,17 +16,20 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
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}

View File

@ -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}

View File

@ -16,15 +16,18 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
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}

View File

@ -16,18 +16,21 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
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}

View File

@ -16,16 +16,19 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
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 <pyrogram.Message>` even if a list contains just one element, otherwise if
*message_ids* was an integer, the single forwarded :obj:`Message <pyrogram.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]

View File

@ -16,14 +16,16 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
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 <pyrogram.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
)

View File

@ -16,16 +16,19 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
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 <pyrogram.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 <pyrogram.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 <pyrogram.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 <pyrogram.Message>` is returned.
Raises:
:class:`Error <pyrogram.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]

View File

@ -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}

View File

@ -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}

View File

@ -16,14 +16,16 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
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.

View File

@ -16,19 +16,25 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
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}

View File

@ -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}

View File

@ -16,18 +16,24 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
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}

View File

@ -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(

View File

@ -16,20 +16,25 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
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}

View File

@ -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}

View File

@ -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}

View File

@ -16,21 +16,27 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
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}

View File

@ -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}

View File

@ -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}

View File

@ -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}

View File

@ -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:

View File

@ -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.

View File

@ -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:

View File

@ -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:

View File

@ -16,12 +16,13 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
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 <pyrogram.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)

View File

@ -16,15 +16,18 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
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 <pyrogram.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),

View File

@ -17,13 +17,16 @@
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
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 <User>` 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 <pyrogram.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]

View File

@ -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.

View File

@ -17,18 +17,19 @@
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
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)

View File

@ -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

View File

@ -16,10 +16,16 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
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(
"<iqq",
callback_query.msg_id.dc_id,
callback_query.msg_id.id,
callback_query.msg_id.access_hash
),
b"-_"
).decode().rstrip("=")
return CallbackQuery(
id=str(callback_query.query_id),
from_user=User._parse(client, users[callback_query.user_id]),
message=message,
inline_message_id=inline_message_id,
chat_instance=str(callback_query.chat_instance),
data=callback_query.data,
game_short_name=callback_query.game_short_name,
client=client
)
def answer(self, text: str = None, show_alert: bool = None, url: str = None, cache_time: int = 0):
"""Bound method *answer* of :obj:`CallbackQuery <pyrogram.CallbackQuery>`.

View File

@ -16,11 +16,11 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
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
)

View File

@ -16,15 +16,14 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
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):

View File

@ -16,13 +16,14 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
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:

View File

@ -16,13 +16,12 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
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
)

View File

@ -16,15 +16,15 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
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:

View File

@ -16,11 +16,11 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
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
)

View File

@ -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

View File

@ -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("+"),

View File

@ -16,10 +16,16 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
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(
"<iiqq",
10,
animation.dc_id,
animation.id,
animation.access_hash
)
),
width=getattr(video_attributes, "w", 0),
height=getattr(video_attributes, "h", 0),
duration=getattr(video_attributes, "duration", 0),
thumb=PhotoSize._parse(client, animation.thumb),
mime_type=animation.mime_type,
file_size=animation.size,
file_name=file_name,
date=animation.date,
client=client
)

View File

@ -16,10 +16,16 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
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(
"<iiqq",
9,
audio.dc_id,
audio.id,
audio.access_hash
)
),
duration=audio_attributes.duration,
performer=audio_attributes.performer,
title=audio_attributes.title,
mime_type=audio.mime_type,
file_size=audio.size,
thumb=PhotoSize._parse(client, audio.thumb),
file_name=file_name,
date=audio.date,
client=client
)

View File

@ -16,10 +16,13 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
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
)

View File

@ -16,10 +16,16 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
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(
"<iiqq",
5,
document.dc_id,
document.id,
document.access_hash
)
),
thumb=PhotoSize._parse(client, document.thumb),
file_name=file_name,
mime_type=document.mime_type,
file_size=document.size,
date=document.date,
client=client
)

View File

@ -16,10 +16,13 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
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
)

View File

@ -16,11 +16,21 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
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 <pyrogram.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 <https://docs.python.org/3/library/re.html#match-objects>`_ that match
the text of this message. Only applicable when using :obj:`Filters.regex <pyrogram.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 <pyrogram.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<MessageEntity>
self.caption_entities = caption_entities # flags.12?Vector<MessageEntity>
self.audio = audio # flags.13?Audio
self.document = document # flags.14?Document
self.photo = photo # flags.16?Vector<PhotoSize>
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<User>
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<PhotoSize>
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)

View File

@ -16,10 +16,14 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
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
)

View File

@ -16,10 +16,16 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
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
)

View File

@ -16,10 +16,18 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
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(
"<iiqqqqi",
2, loc.dc_id, photo.id, photo.access_hash,
loc.volume_id, loc.secret, loc.local_id)),
width=raw_size.w,
height=raw_size.h,
file_size=file_size,
client=client
)
sizes.append(size)
return Photo(
id=b64encode(
pack(
"<qq",
photo.id,
photo.access_hash
),
b"-_"
).decode().rstrip("="),
date=photo.date,
sizes=sizes,
client=client
)

View File

@ -16,10 +16,15 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
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(
"<iiqqqqi",
0, loc.dc_id, 0, 0,
loc.volume_id, loc.secret, loc.local_id)),
width=photo_size.w,
height=photo_size.h,
file_size=file_size,
client=client
)

View File

@ -16,10 +16,18 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
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(
"<iiqq",
8,
sticker.dc_id,
sticker.id,
sticker.access_hash
)
),
width=image_size_attributes.w if image_size_attributes else 0,
height=image_size_attributes.h if image_size_attributes else 0,
thumb=PhotoSize._parse(client, sticker.thumb),
# TODO: mask_position
set_name=set_name,
emoji=sticker_attributes.alt or None,
file_size=sticker.size,
mime_type=sticker.mime_type,
file_name=file_name,
date=sticker.date,
client=client
)

View File

@ -16,10 +16,14 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
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
)

View File

@ -16,10 +16,13 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
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
)

View File

@ -16,10 +16,16 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
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(
"<iiqq",
4,
video.dc_id,
video.id,
video.access_hash
)
),
width=video_attributes.w,
height=video_attributes.h,
duration=video_attributes.duration,
thumb=PhotoSize._parse(client, video.thumb),
mime_type=video.mime_type,
file_size=video.size,
file_name=file_name,
date=video.date,
client=client
)

View File

@ -16,10 +16,16 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
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(
"<iiqq",
13,
video_note.dc_id,
video_note.id,
video_note.access_hash
)
),
length=video_attributes.w,
duration=video_attributes.duration,
thumb=PhotoSize._parse(client, video_note.thumb),
file_size=video_note.size,
mime_type=video_note.mime_type,
date=video_note.date,
client=client
)

View File

@ -16,10 +16,15 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
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(
"<iiqq",
3,
voice.dc_id,
voice.id,
voice.access_hash
)
),
duration=attributes.duration,
mime_type=voice.mime_type,
file_size=voice.size,
waveform=attributes.waveform,
date=voice.date,
client=client
)

View File

@ -0,0 +1,58 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
#
# 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 <http://www.gnu.org/licenses/>.
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()]
)
)

View File

@ -1,94 +0,0 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
#
# 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 <http://www.gnu.org/licenses/>.
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 <pyrogram.Message>`, *optional*):
New incoming message of any kind text, photo, sticker, etc.
edited_message (:obj:`Message <pyrogram.Message>`, *optional*):
New version of a message that is known to the bot and was edited.
deleted_messages (:obj:`Messages <pyrogram.Messages>`, *optional*):
Deleted messages.
channel_post (:obj:`Message <pyrogram.Message>`, *optional*):
New incoming channel post of any kind text, photo, sticker, etc.
edited_channel_post (:obj:`Message <pyrogram.Message>`, *optional*):
New version of a channel post that is known to the bot and was edited.
deleted_channel_posts (:obj:`Messages <pyrogram.Messages>`, *optional*):
Deleted channel posts.
inline_query (:obj:`InlineQuery <pyrogram.InlineQuery>`, *optional*):
New incoming inline query.
chosen_inline_result (:obj:`ChosenInlineResult <pyrogram.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 <pyrogram.CallbackQuery>`, *optional*):
New incoming callback query.
shipping_query (:obj:`ShippingQuery <pyrogram.ShippingQuery>`, *optional*):
New incoming shipping query. Only for invoices with flexible price.
pre_checkout_query (:obj:`PreCheckoutQuery <pyrogram.PreCheckoutQuery>`, *optional*):
New incoming pre-checkout query. Contains full information about checkout.
user_status (:obj:`UserStatus <pyrogram.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

View File

@ -16,10 +16,13 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
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

View File

@ -16,10 +16,13 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
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

View File

@ -16,10 +16,16 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
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
)

View File

@ -16,10 +16,15 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
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(
"<iiqqqqi",
1, loc_small.dc_id, photo_id, 0, loc_small.volume_id, loc_small.secret, loc_small.local_id
)
),
big_file_id=encode(
pack(
"<iiqqqqi",
1, loc_big.dc_id, photo_id, 0, loc_big.volume_id, loc_big.secret, loc_big.local_id
)
),
client=client
)

View File

@ -16,10 +16,14 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
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
)

View File

@ -16,10 +16,16 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
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 <pyrogram.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
)

View File

@ -16,10 +16,14 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
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
)

Some files were not shown because too many files have changed in this diff Show More