diff --git a/.gitignore b/.gitignore index 0b1a0699..ce3407dd 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,9 @@ pyrogram/api/all.py # PyCharm stuff .idea/ +# VS Code +.vscode/ + # Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] @@ -78,6 +81,7 @@ instance/ # Sphinx documentation docs/_build/ +docs/source/_build # PyBuilder target/ diff --git a/compiler/api/compiler.py b/compiler/api/compiler.py index 3995fd5f..255884db 100644 --- a/compiler/api/compiler.py +++ b/compiler/api/compiler.py @@ -478,7 +478,6 @@ def start(): f.write("\n 0xbc799737: \"pyrogram.api.core.BoolFalse\",") f.write("\n 0x997275b5: \"pyrogram.api.core.BoolTrue\",") - f.write("\n 0x56730bcc: \"pyrogram.api.core.Null\",") f.write("\n 0x1cb5c415: \"pyrogram.api.core.Vector\",") f.write("\n 0x73f1f8dc: \"pyrogram.api.core.MsgContainer\",") f.write("\n 0xae500895: \"pyrogram.api.core.FutureSalts\",") diff --git a/docs/source/faq.rst b/docs/source/faq.rst index 2dde12f2..a05ff39c 100644 --- a/docs/source/faq.rst +++ b/docs/source/faq.rst @@ -192,7 +192,6 @@ dismissed and their IP addresses are now kept as aliases to the nearest one. Thanks to `@FrayxRulez `_ for telling about alias DCs. - I want to migrate my account from DCX to DCY. --------------------------------------------- @@ -246,9 +245,13 @@ The error in question is ``[400 PEER_ID_INVALID]``, and could mean several thing - The chat id you tried to use is simply wrong, double check it. - The chat id refers to a group or channel you are not a member of. -- The chat id refers to a user you have't seen yet (from contacts, groups in common, forwarded messages or private - chats). - The chat id argument you passed is in form of a string; you have to convert it into an integer with ``int(chat_id)``. +- The chat id refers to a user your current session haven't met yet. + +About the last point: in order for you to meet a user and thus communicate with them, you should ask yourself how to +contact people using official apps. The answer is the same for Pyrogram too and involves normal usages such as searching +for usernames, meet them in a common group, have their phone contacts saved, getting a message mentioning them (either a +forward or a mention in the message text). UnicodeEncodeError: '' codec can't encode … ----------------------------------------------------- @@ -258,6 +261,14 @@ shows up when you try to print something and has very little to do with Pyrogram your own terminal. To fix it, either find a way to change the encoding settings of your terminal to UTF-8 or switch to a better terminal altogether. +Uploading with URLs gives error WEBPAGE_CURL_FAILED +--------------------------------------------------- + +When uploading media files using an URL, the server automatically tries to download the media and uploads it to the +Telegram cloud. This error usually happens in case the provided URL is not publicly accessible by Telegram itself or the +media exceeds 20 MB in size. In such cases, your only option is to download the media yourself and upload from your +local machine. + My verification code expires immediately! ----------------------------------------- diff --git a/docs/source/index.rst b/docs/source/index.rst index 5cb9bb2e..f6961bc6 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -45,8 +45,9 @@ Welcome to Pyrogram topics/tgcrypto topics/storage-engines topics/text-formatting - topics/serialize + topics/serializing topics/proxy + topics/scheduling topics/bots-interaction topics/mtproto-vs-botapi topics/debugging diff --git a/docs/source/topics/scheduling.rst b/docs/source/topics/scheduling.rst new file mode 100644 index 00000000..3cb95ec7 --- /dev/null +++ b/docs/source/topics/scheduling.rst @@ -0,0 +1,87 @@ +Scheduling Tasks +================ + +Scheduling tasks means executing one or more functions periodically at pre-defined intervals or after a delay. This is +useful, for example, to send recurring messages to specific chats or users. + +Since there's no built-in task scheduler in Pyrogram, this page will only show examples on how to integrate Pyrogram +with the main Python schedule libraries such as ``schedule`` and ``apscheduler``. For more detailed information, you can +visit and learn from each library documentation. + +Using ``schedule`` +------------------ + +- Install with ``pip3 install schedule`` +- Documentation: https://schedule.readthedocs.io + +.. code-block:: python + + import time + + import schedule + + from pyrogram import Client + + app = Client("my_account") + + + def job(): + app.send_message("me", "Hi!") + + + schedule.every(3).seconds.do(job) + + with app: + while True: + schedule.run_pending() + time.sleep(1) + + + +Using ``apscheduler`` +--------------------- + +- Install with ``pip3 install apscheduler`` +- Documentation: https://apscheduler.readthedocs.io + +.. code-block:: python + + from apscheduler.schedulers.background import BackgroundScheduler + + from pyrogram import Client + + app = Client("my_account") + + + def job(): + app.send_message("me", "Hi!") + + + scheduler = BackgroundScheduler() + scheduler.add_job(job, "interval", seconds=3) + + scheduler.start() + app.run() + +``apscheduler`` does also support async code, here's an example with +`Pyrogram Asyncio `_: + +.. code-block:: python + + from apscheduler.schedulers.asyncio import AsyncIOScheduler + + from pyrogram import Client + + app = Client("my_account") + + + async def job(): + await app.send_message("me", "Hi!") + + + scheduler = AsyncIOScheduler() + scheduler.add_job(job, "interval", seconds=3) + + scheduler.start() + app.run() + diff --git a/docs/source/topics/serialize.rst b/docs/source/topics/serializing.rst similarity index 100% rename from docs/source/topics/serialize.rst rename to docs/source/topics/serializing.rst diff --git a/pyrogram/api/__init__.py b/pyrogram/api/__init__.py index 8d7831ff..78f1a579 100644 --- a/pyrogram/api/__init__.py +++ b/pyrogram/api/__init__.py @@ -19,8 +19,7 @@ from importlib import import_module from .all import objects -from .core.tl_object import TLObject for k, v in objects.items(): path, name = v.rsplit(".", 1) - TLObject.all[k] = getattr(import_module(path), name) + objects[k] = getattr(import_module(path), name) diff --git a/pyrogram/api/core/__init__.py b/pyrogram/api/core/__init__.py index aaf5a324..ff4fc9c5 100644 --- a/pyrogram/api/core/__init__.py +++ b/pyrogram/api/core/__init__.py @@ -22,8 +22,5 @@ from .gzip_packed import GzipPacked from .list import List from .message import Message from .msg_container import MsgContainer -from .primitives import ( - Bool, BoolTrue, BoolFalse, Bytes, Double, - Int, Long, Int128, Int256, Null, String, Vector -) +from .primitives import * from .tl_object import TLObject diff --git a/pyrogram/api/core/primitives/__init__.py b/pyrogram/api/core/primitives/__init__.py index 8885878b..f86e3cab 100644 --- a/pyrogram/api/core/primitives/__init__.py +++ b/pyrogram/api/core/primitives/__init__.py @@ -16,10 +16,11 @@ # You should have received a copy of the GNU Lesser General Public License # along with Pyrogram. If not, see . -from .bool import Bool, BoolTrue, BoolFalse +from .bool import Bool, BoolFalse, BoolTrue from .bytes import Bytes from .double import Double from .int import Int, Long, Int128, Int256 -from .null import Null from .string import String from .vector import Vector + +__all__ = ["Bool", "BoolFalse", "BoolTrue", "Bytes", "Double", "Int", "Long", "Int128", "Int256", "String", "Vector"] diff --git a/pyrogram/api/core/primitives/null.py b/pyrogram/api/core/primitives/null.py deleted file mode 100644 index ffddea94..00000000 --- a/pyrogram/api/core/primitives/null.py +++ /dev/null @@ -1,32 +0,0 @@ -# Pyrogram - Telegram MTProto API Client Library for Python -# Copyright (C) 2017-2019 Dan Tès -# -# This file is part of Pyrogram. -# -# Pyrogram is free software: you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License as published -# by the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Pyrogram is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with Pyrogram. If not, see . - -from io import BytesIO - -from ..tl_object import TLObject - - -class Null(TLObject): - ID = 0x56730bcc - - @staticmethod - def read(b: BytesIO, *args) -> None: - return None - - def __new__(cls) -> bytes: - return cls.ID.to_bytes(4, "little") diff --git a/pyrogram/api/core/tl_object.py b/pyrogram/api/core/tl_object.py index 4b951404..d39a8ae2 100644 --- a/pyrogram/api/core/tl_object.py +++ b/pyrogram/api/core/tl_object.py @@ -20,17 +20,17 @@ from collections import OrderedDict from io import BytesIO from json import dumps +from ..all import objects + class TLObject: - all = {} - __slots__ = [] QUALNAME = "Base" @staticmethod def read(b: BytesIO, *args): # TODO: Rename b -> data - return TLObject.all[int.from_bytes(b.read(4), "little")].read(b, *args) + return objects[int.from_bytes(b.read(4), "little")].read(b, *args) def write(self, *args) -> bytes: pass diff --git a/pyrogram/client/client.py b/pyrogram/client/client.py index 55f20743..0b9fa076 100644 --- a/pyrogram/client/client.py +++ b/pyrogram/client/client.py @@ -1031,7 +1031,7 @@ class Client(Methods, BaseClient): access_hash = 0 peer_type = "group" elif isinstance(peer, (types.Channel, types.ChannelForbidden)): - peer_id = int("-100" + str(peer.id)) + peer_id = utils.get_channel_id(peer.id) access_hash = peer.access_hash username = getattr(peer, "username", None) @@ -1139,7 +1139,7 @@ class Client(Methods, BaseClient): try: diff = await self.send( functions.updates.GetChannelDifference( - channel=await self.resolve_peer(int("-100" + str(channel_id))), + channel=await self.resolve_peer(utils.get_channel_id(channel_id)), filter=types.ChannelMessagesFilter( ranges=[types.MessageRange( min_id=update.message.id, @@ -1527,33 +1527,38 @@ class Client(Methods, BaseClient): except KeyError: raise PeerIdInvalid - if peer_id > 0: + peer_type = utils.get_type(peer_id) + + if peer_type == "user": self.fetch_peers( await self.send( functions.users.GetUsers( - id=[types.InputUser( - user_id=peer_id, - access_hash=0 - )] + id=[ + types.InputUser( + user_id=peer_id, + access_hash=0 + ) + ] ) ) ) + elif peer_type == "chat": + await self.send( + functions.messages.GetChats( + id=[-peer_id] + ) + ) else: - if str(peer_id).startswith("-100"): - await self.send( - functions.channels.GetChannels( - id=[types.InputChannel( - channel_id=int(str(peer_id)[4:]), + await self.send( + functions.channels.GetChannels( + id=[ + types.InputChannel( + channel_id=utils.get_channel_id(peer_id), access_hash=0 - )] - ) - ) - else: - await self.send( - functions.messages.GetChats( - id=[-peer_id] - ) + ) + ] ) + ) try: return self.storage.get_peer_by_id(peer_id) diff --git a/pyrogram/client/ext/dispatcher.py b/pyrogram/client/ext/dispatcher.py index d4388ddd..744df2a8 100644 --- a/pyrogram/client/ext/dispatcher.py +++ b/pyrogram/client/ext/dispatcher.py @@ -171,8 +171,13 @@ class Dispatcher: args = None if isinstance(handler, handler_type): - if handler.check(parsed_update): - args = (parsed_update,) + try: + if handler.check(parsed_update): + args = (parsed_update,) + except Exception as e: + log.error(e, exc_info=True) + continue + elif isinstance(handler, RawUpdateHandler): args = (update, users, chats) diff --git a/pyrogram/client/ext/utils.py b/pyrogram/client/ext/utils.py index 30f7e476..4093d645 100644 --- a/pyrogram/client/ext/utils.py +++ b/pyrogram/client/ext/utils.py @@ -21,10 +21,11 @@ import base64 import struct import sys from concurrent.futures.thread import ThreadPoolExecutor -from typing import Union, List +from typing import List +from typing import Union import pyrogram - +from pyrogram.api.types import PeerUser, PeerChat, PeerChannel from . import BaseClient from ...api import types @@ -33,10 +34,17 @@ def decode(s: str) -> bytes: s = base64.urlsafe_b64decode(s + "=" * (-len(s) % 4)) r = b"" - assert s[-1] == 2 + try: + assert s[-1] == 2 + skip = 1 + except AssertionError: + assert s[-2] == 22 + assert s[-1] == 4 + skip = 2 i = 0 - while i < len(s) - 1: + + while i < len(s) - skip: if s[i] != 0: r += bytes([s[i]]) else: @@ -52,7 +60,7 @@ def encode(s: bytes) -> str: r = b"" n = 0 - for i in s + bytes([2]): + for i in s + bytes([22]) + bytes([4]): if i == 0: n += 1 else: @@ -74,23 +82,6 @@ async def ainput(prompt: str = ""): )).rstrip() -def get_peer_id(input_peer) -> int: - return ( - input_peer.user_id if isinstance(input_peer, types.InputPeerUser) - else -input_peer.chat_id if isinstance(input_peer, types.InputPeerChat) - else int("-100" + str(input_peer.channel_id)) - ) - - -def get_input_peer(peer_id: int, access_hash: int): - return ( - types.InputPeerUser(user_id=peer_id, access_hash=access_hash) if peer_id > 0 - else types.InputPeerChannel(channel_id=int(str(peer_id)[4:]), access_hash=access_hash) - if (str(peer_id).startswith("-100") and access_hash) - else types.InputPeerChat(chat_id=-peer_id) - ) - - def get_offset_date(dialogs): for m in reversed(dialogs.messages): if isinstance(m, types.MessageEmpty): @@ -195,7 +186,7 @@ def parse_deleted_messages(client, update) -> List["pyrogram.Message"]: pyrogram.Message( message_id=message, chat=pyrogram.Chat( - id=int("-100" + str(channel_id)), + id=get_channel_id(channel_id), type="channel", client=client ) if channel_id is not None else None, @@ -215,3 +206,39 @@ def unpack_inline_message_id(inline_message_id: str) -> types.InputBotInlineMess id=r[1], access_hash=r[2] ) + + +MIN_CHANNEL_ID = -1002147483647 +MAX_CHANNEL_ID = -1000000000000 +MIN_CHAT_ID = -2147483647 +MAX_USER_ID = 2147483647 + + +def get_peer_id(peer: Union[PeerUser, PeerChat, PeerChannel]) -> int: + if isinstance(peer, PeerUser): + return peer.user_id + + if isinstance(peer, PeerChat): + return -peer.chat_id + + if isinstance(peer, PeerChannel): + return MAX_CHANNEL_ID - peer.channel_id + + raise ValueError("Peer type invalid: {}".format(peer)) + + +def get_type(peer_id: int) -> str: + if peer_id < 0: + if MIN_CHAT_ID <= peer_id: + return "chat" + + if MIN_CHANNEL_ID <= peer_id < MAX_CHANNEL_ID: + return "channel" + elif 0 < peer_id <= MAX_USER_ID: + return "user" + + raise ValueError("Peer id invalid: {}".format(peer_id)) + + +def get_channel_id(peer_id: int) -> int: + return MAX_CHANNEL_ID - peer_id diff --git a/pyrogram/client/methods/chats/get_chat.py b/pyrogram/client/methods/chats/get_chat.py index 6def6aea..785886ad 100644 --- a/pyrogram/client/methods/chats/get_chat.py +++ b/pyrogram/client/methods/chats/get_chat.py @@ -20,7 +20,7 @@ from typing import Union import pyrogram from pyrogram.api import functions, types -from ...ext import BaseClient +from ...ext import BaseClient, utils class GetChat(BaseClient): @@ -70,7 +70,7 @@ class GetChat(BaseClient): chat_id = -r.chat.id if isinstance(r.chat, types.Channel): - chat_id = int("-100" + str(r.chat.id)) + chat_id = utils.get_channel_id(r.chat.id) peer = await self.resolve_peer(chat_id) diff --git a/pyrogram/client/methods/chats/get_dialogs.py b/pyrogram/client/methods/chats/get_dialogs.py index 907ee41c..ec25249d 100644 --- a/pyrogram/client/methods/chats/get_dialogs.py +++ b/pyrogram/client/methods/chats/get_dialogs.py @@ -24,7 +24,7 @@ import pyrogram from pyrogram.api import functions, types from pyrogram.errors import FloodWait -from ...ext import BaseClient +from ...ext import BaseClient, utils log = logging.getLogger(__name__) @@ -101,10 +101,8 @@ class GetDialogs(BaseClient): 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)) + chat_id = utils.get_peer_id(to_id) messages[chat_id] = await pyrogram.Message._parse(self, message, users, chats) diff --git a/pyrogram/client/methods/users/block_user.py b/pyrogram/client/methods/users/block_user.py index 77ffcaba..5b60d5f8 100644 --- a/pyrogram/client/methods/users/block_user.py +++ b/pyrogram/client/methods/users/block_user.py @@ -19,7 +19,6 @@ from typing import Union from pyrogram.api import functions - from ...ext import BaseClient diff --git a/pyrogram/client/methods/users/delete_profile_photos.py b/pyrogram/client/methods/users/delete_profile_photos.py index ce919eb7..6b96e0bb 100644 --- a/pyrogram/client/methods/users/delete_profile_photos.py +++ b/pyrogram/client/methods/users/delete_profile_photos.py @@ -21,7 +21,6 @@ from typing import List, Union from pyrogram.api import functions, types from pyrogram.client.ext import utils - from ...ext import BaseClient diff --git a/pyrogram/client/methods/users/get_profile_photos.py b/pyrogram/client/methods/users/get_profile_photos.py index 49f6a713..ac8380a9 100644 --- a/pyrogram/client/methods/users/get_profile_photos.py +++ b/pyrogram/client/methods/users/get_profile_photos.py @@ -21,7 +21,6 @@ from typing import Union, List import pyrogram from pyrogram.api import functions, types from pyrogram.client.ext import utils - from ...ext import BaseClient diff --git a/pyrogram/client/methods/users/get_profile_photos_count.py b/pyrogram/client/methods/users/get_profile_photos_count.py index 87348194..f40d5974 100644 --- a/pyrogram/client/methods/users/get_profile_photos_count.py +++ b/pyrogram/client/methods/users/get_profile_photos_count.py @@ -19,7 +19,6 @@ from typing import Union from pyrogram.api import functions, types - from ...ext import BaseClient diff --git a/pyrogram/client/methods/users/unblock_user.py b/pyrogram/client/methods/users/unblock_user.py index e9433b8a..9821734d 100644 --- a/pyrogram/client/methods/users/unblock_user.py +++ b/pyrogram/client/methods/users/unblock_user.py @@ -19,7 +19,6 @@ from typing import Union from pyrogram.api import functions - from ...ext import BaseClient diff --git a/pyrogram/client/parser/__init__.py b/pyrogram/client/parser/__init__.py index 4769038d..53806619 100644 --- a/pyrogram/client/parser/__init__.py +++ b/pyrogram/client/parser/__init__.py @@ -16,4 +16,4 @@ # You should have received a copy of the GNU Lesser General Public License # along with Pyrogram. If not, see . -from .parser import Parser \ No newline at end of file +from .parser import Parser diff --git a/pyrogram/client/storage/__init__.py b/pyrogram/client/storage/__init__.py index 00d2f144..657c06eb 100644 --- a/pyrogram/client/storage/__init__.py +++ b/pyrogram/client/storage/__init__.py @@ -16,6 +16,6 @@ # You should have received a copy of the GNU Lesser General Public License # along with Pyrogram. If not, see . -from .memory_storage import MemoryStorage from .file_storage import FileStorage +from .memory_storage import MemoryStorage from .storage import Storage diff --git a/pyrogram/client/types/bots_and_keyboards/callback_game.py b/pyrogram/client/types/bots_and_keyboards/callback_game.py index acf6df60..338cfb06 100644 --- a/pyrogram/client/types/bots_and_keyboards/callback_game.py +++ b/pyrogram/client/types/bots_and_keyboards/callback_game.py @@ -25,7 +25,5 @@ class CallbackGame(Object): Use BotFather to set up your game. """ - __slots__ = [] - def __init__(self): super().__init__() diff --git a/pyrogram/client/types/bots_and_keyboards/callback_query.py b/pyrogram/client/types/bots_and_keyboards/callback_query.py index 27cebd7e..7f355312 100644 --- a/pyrogram/client/types/bots_and_keyboards/callback_query.py +++ b/pyrogram/client/types/bots_and_keyboards/callback_query.py @@ -25,6 +25,7 @@ from pyrogram.api import types from ..object import Object from ..update import Update from ..user_and_chats import User +from ...ext import utils class CallbackQuery(Object, Update): @@ -60,8 +61,6 @@ class CallbackQuery(Object, Update): """ - __slots__ = ["id", "from_user", "chat_instance", "message", "inline_message_id", "data", "game_short_name"] - def __init__( self, *, @@ -90,16 +89,7 @@ class CallbackQuery(Object, Update): 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 = await client.get_messages(peer_id, callback_query.msg_id) + message = await client.get_messages(utils.get_peer_id(callback_query.peer), callback_query.msg_id) elif isinstance(callback_query, types.UpdateInlineBotCallbackQuery): inline_message_id = b64encode( pack( diff --git a/pyrogram/client/types/bots_and_keyboards/force_reply.py b/pyrogram/client/types/bots_and_keyboards/force_reply.py index 6c542aa8..ef5c0ccb 100644 --- a/pyrogram/client/types/bots_and_keyboards/force_reply.py +++ b/pyrogram/client/types/bots_and_keyboards/force_reply.py @@ -37,8 +37,6 @@ class ForceReply(Object): 2) if the bot's message is a reply (has reply_to_message_id), sender of the original message. """ - __slots__ = ["selective"] - def __init__( self, selective: bool = None diff --git a/pyrogram/client/types/bots_and_keyboards/game_high_score.py b/pyrogram/client/types/bots_and_keyboards/game_high_score.py index 5d576ad4..38e2242a 100644 --- a/pyrogram/client/types/bots_and_keyboards/game_high_score.py +++ b/pyrogram/client/types/bots_and_keyboards/game_high_score.py @@ -37,8 +37,6 @@ class GameHighScore(Object): Position in high score table for the game. """ - __slots__ = ["user", "score", "position"] - def __init__( self, *, diff --git a/pyrogram/client/types/bots_and_keyboards/inline_keyboard_button.py b/pyrogram/client/types/bots_and_keyboards/inline_keyboard_button.py index cfc969e7..22e728e6 100644 --- a/pyrogram/client/types/bots_and_keyboards/inline_keyboard_button.py +++ b/pyrogram/client/types/bots_and_keyboards/inline_keyboard_button.py @@ -23,6 +23,7 @@ from pyrogram.api.types import ( KeyboardButtonUrl, KeyboardButtonCallback, KeyboardButtonSwitchInline, KeyboardButtonGame ) + from .callback_game import CallbackGame from ..object import Object @@ -59,10 +60,6 @@ class InlineKeyboardButton(Object): # TODO: Add callback_game and pay fields - __slots__ = [ - "text", "url", "callback_data", "switch_inline_query", "switch_inline_query_current_chat", "callback_game" - ] - def __init__( self, text: str, diff --git a/pyrogram/client/types/bots_and_keyboards/inline_keyboard_markup.py b/pyrogram/client/types/bots_and_keyboards/inline_keyboard_markup.py index 7b811f88..811c4365 100644 --- a/pyrogram/client/types/bots_and_keyboards/inline_keyboard_markup.py +++ b/pyrogram/client/types/bots_and_keyboards/inline_keyboard_markup.py @@ -19,6 +19,7 @@ from typing import List from pyrogram.api.types import ReplyInlineMarkup, KeyboardButtonRow + from . import InlineKeyboardButton from ..object import Object @@ -31,8 +32,6 @@ class InlineKeyboardMarkup(Object): List of button rows, each represented by a List of InlineKeyboardButton objects. """ - __slots__ = ["inline_keyboard"] - def __init__( self, inline_keyboard: List[List[InlineKeyboardButton]] diff --git a/pyrogram/client/types/bots_and_keyboards/keyboard_button.py b/pyrogram/client/types/bots_and_keyboards/keyboard_button.py index 8374db1b..21c03613 100644 --- a/pyrogram/client/types/bots_and_keyboards/keyboard_button.py +++ b/pyrogram/client/types/bots_and_keyboards/keyboard_button.py @@ -41,8 +41,6 @@ class KeyboardButton(Object): Available in private chats only. """ - __slots__ = ["text", "request_contact", "request_location"] - def __init__( self, text: str, diff --git a/pyrogram/client/types/bots_and_keyboards/reply_keyboard_markup.py b/pyrogram/client/types/bots_and_keyboards/reply_keyboard_markup.py index 4e666d1f..12799bd7 100644 --- a/pyrogram/client/types/bots_and_keyboards/reply_keyboard_markup.py +++ b/pyrogram/client/types/bots_and_keyboards/reply_keyboard_markup.py @@ -20,6 +20,7 @@ from typing import List, Union from pyrogram.api.types import KeyboardButtonRow from pyrogram.api.types import ReplyKeyboardMarkup as RawReplyKeyboardMarkup + from . import KeyboardButton from ..object import Object @@ -49,8 +50,6 @@ class ReplyKeyboardMarkup(Object): select the new language. Other users in the group don't see the keyboard. """ - __slots__ = ["keyboard", "resize_keyboard", "one_time_keyboard", "selective"] - def __init__( self, keyboard: List[List[Union[KeyboardButton, str]]], diff --git a/pyrogram/client/types/bots_and_keyboards/reply_keyboard_remove.py b/pyrogram/client/types/bots_and_keyboards/reply_keyboard_remove.py index d451a8e8..1623c9bd 100644 --- a/pyrogram/client/types/bots_and_keyboards/reply_keyboard_remove.py +++ b/pyrogram/client/types/bots_and_keyboards/reply_keyboard_remove.py @@ -38,8 +38,6 @@ class ReplyKeyboardRemove(Object): keyboard for that user, while still showing the keyboard with poll options to users who haven't voted yet. """ - __slots__ = ["selective"] - def __init__( self, selective: bool = None diff --git a/pyrogram/client/types/inline_mode/inline_query.py b/pyrogram/client/types/inline_mode/inline_query.py index 12f1bbaf..36514a97 100644 --- a/pyrogram/client/types/inline_mode/inline_query.py +++ b/pyrogram/client/types/inline_mode/inline_query.py @@ -48,7 +48,6 @@ class InlineQuery(Object, Update): location (:obj:`Location`. *optional*): Sender location, only for bots that request user location. """ - __slots__ = ["id", "from_user", "query", "offset", "location"] def __init__( self, diff --git a/pyrogram/client/types/inline_mode/inline_query_result.py b/pyrogram/client/types/inline_mode/inline_query_result.py index e7f5904e..02a5e11e 100644 --- a/pyrogram/client/types/inline_mode/inline_query_result.py +++ b/pyrogram/client/types/inline_mode/inline_query_result.py @@ -53,8 +53,6 @@ class InlineQueryResult(Object): - :obj:`InlineQueryResultAnimation` """ - __slots__ = ["type", "id", "input_message_content", "reply_markup"] - def __init__( self, type: str, diff --git a/pyrogram/client/types/inline_mode/inline_query_result_animation.py b/pyrogram/client/types/inline_mode/inline_query_result_animation.py index 4d2d5596..c4cb26e4 100644 --- a/pyrogram/client/types/inline_mode/inline_query_result_animation.py +++ b/pyrogram/client/types/inline_mode/inline_query_result_animation.py @@ -68,11 +68,6 @@ class InlineQueryResultAnimation(InlineQueryResult): Content of the message to be sent instead of the photo. """ - __slots__ = [ - "animation_url", "thumb_url", "title", "description", "caption", "parse_mode", "reply_markup", - "input_message_content" - ] - def __init__( self, animation_url: str, diff --git a/pyrogram/client/types/inline_mode/inline_query_result_article.py b/pyrogram/client/types/inline_mode/inline_query_result_article.py index a887a0ba..33b6deff 100644 --- a/pyrogram/client/types/inline_mode/inline_query_result_article.py +++ b/pyrogram/client/types/inline_mode/inline_query_result_article.py @@ -49,8 +49,6 @@ class InlineQueryResultArticle(InlineQueryResult): Inline keyboard attached to the message. """ - __slots__ = ["title", "url", "description", "thumb_url"] - def __init__( self, title: str, diff --git a/pyrogram/client/types/inline_mode/inline_query_result_photo.py b/pyrogram/client/types/inline_mode/inline_query_result_photo.py index 3442764e..ffcc21c0 100644 --- a/pyrogram/client/types/inline_mode/inline_query_result_photo.py +++ b/pyrogram/client/types/inline_mode/inline_query_result_photo.py @@ -68,11 +68,6 @@ class InlineQueryResultPhoto(InlineQueryResult): Content of the message to be sent instead of the photo. """ - __slots__ = [ - "photo_url", "thumb_url", "title", "description", "caption", "parse_mode", "reply_markup", - "input_message_content" - ] - def __init__( self, photo_url: str, diff --git a/pyrogram/client/types/input_media/input_media.py b/pyrogram/client/types/input_media/input_media.py index 2b5d7f0f..9b89fe12 100644 --- a/pyrogram/client/types/input_media/input_media.py +++ b/pyrogram/client/types/input_media/input_media.py @@ -30,7 +30,6 @@ class InputMedia(Object): - :obj:`InputMediaPhoto` - :obj:`InputMediaVideo` """ - __slots__ = ["media", "caption", "parse_mode"] def __init__(self, media: str, caption: str, parse_mode: str): super().__init__() diff --git a/pyrogram/client/types/input_media/input_media_animation.py b/pyrogram/client/types/input_media/input_media_animation.py index d6c67d56..dc70cbec 100644 --- a/pyrogram/client/types/input_media/input_media_animation.py +++ b/pyrogram/client/types/input_media/input_media_animation.py @@ -56,8 +56,6 @@ class InputMediaAnimation(InputMedia): Animation duration. """ - __slots__ = ["thumb", "width", "height", "duration"] - def __init__( self, media: str, diff --git a/pyrogram/client/types/input_media/input_media_audio.py b/pyrogram/client/types/input_media/input_media_audio.py index f01444a8..5ed670a6 100644 --- a/pyrogram/client/types/input_media/input_media_audio.py +++ b/pyrogram/client/types/input_media/input_media_audio.py @@ -58,8 +58,6 @@ class InputMediaAudio(InputMedia): Title of the audio """ - __slots__ = ["thumb", "duration", "performer", "title"] - def __init__( self, media: str, diff --git a/pyrogram/client/types/input_media/input_media_document.py b/pyrogram/client/types/input_media/input_media_document.py index af549c81..14756e02 100644 --- a/pyrogram/client/types/input_media/input_media_document.py +++ b/pyrogram/client/types/input_media/input_media_document.py @@ -47,8 +47,6 @@ class InputMediaDocument(InputMedia): Pass None to completely disable style parsing. """ - __slots__ = ["thumb"] - def __init__( self, media: str, diff --git a/pyrogram/client/types/input_media/input_media_photo.py b/pyrogram/client/types/input_media/input_media_photo.py index 30c53777..5e18cdd6 100644 --- a/pyrogram/client/types/input_media/input_media_photo.py +++ b/pyrogram/client/types/input_media/input_media_photo.py @@ -43,8 +43,6 @@ class InputMediaPhoto(InputMedia): Pass None to completely disable style parsing. """ - __slots__ = [] - def __init__( self, media: str, diff --git a/pyrogram/client/types/input_media/input_media_video.py b/pyrogram/client/types/input_media/input_media_video.py index 3500ff55..6b64caa8 100644 --- a/pyrogram/client/types/input_media/input_media_video.py +++ b/pyrogram/client/types/input_media/input_media_video.py @@ -61,8 +61,6 @@ class InputMediaVideo(InputMedia): Pass True, if the uploaded video is suitable for streaming. """ - __slots__ = ["thumb", "width", "height", "duration", "supports_streaming"] - def __init__( self, media: str, diff --git a/pyrogram/client/types/input_media/input_phone_contact.py b/pyrogram/client/types/input_media/input_phone_contact.py index 9c03694d..7498768d 100644 --- a/pyrogram/client/types/input_media/input_phone_contact.py +++ b/pyrogram/client/types/input_media/input_phone_contact.py @@ -37,8 +37,6 @@ class InputPhoneContact(Object): Contact's last name """ - __slots__ = [] - def __init__(self, phone: str, first_name: str, last_name: str = ""): super().__init__(None) diff --git a/pyrogram/client/types/input_message_content/input_message_content.py b/pyrogram/client/types/input_message_content/input_message_content.py index b02c6b38..6561b5a8 100644 --- a/pyrogram/client/types/input_message_content/input_message_content.py +++ b/pyrogram/client/types/input_message_content/input_message_content.py @@ -31,8 +31,6 @@ class InputMessageContent(Object): - :obj:`InputTextMessageContent` """ - __slots__ = [] - def __init__(self): super().__init__() diff --git a/pyrogram/client/types/input_message_content/input_text_message_content.py b/pyrogram/client/types/input_message_content/input_text_message_content.py index 7fa9d9dd..f9815cfc 100644 --- a/pyrogram/client/types/input_message_content/input_text_message_content.py +++ b/pyrogram/client/types/input_message_content/input_text_message_content.py @@ -41,8 +41,6 @@ class InputTextMessageContent(InputMessageContent): Disables link previews for links in this message. """ - __slots__ = ["message_text", "parse_mode", "disable_web_page_preview"] - def __init__(self, message_text: str, parse_mode: Union[str, None] = object, disable_web_page_preview: bool = None): super().__init__() diff --git a/pyrogram/client/types/messages_and_media/animation.py b/pyrogram/client/types/messages_and_media/animation.py index 5441a114..ba6744ce 100644 --- a/pyrogram/client/types/messages_and_media/animation.py +++ b/pyrogram/client/types/messages_and_media/animation.py @@ -58,8 +58,6 @@ class Animation(Object): Animation thumbnails. """ - __slots__ = ["file_id", "file_name", "mime_type", "file_size", "date", "width", "height", "duration", "thumbs"] - def __init__( self, *, diff --git a/pyrogram/client/types/messages_and_media/audio.py b/pyrogram/client/types/messages_and_media/audio.py index 3d9cf8a6..6d8a12e9 100644 --- a/pyrogram/client/types/messages_and_media/audio.py +++ b/pyrogram/client/types/messages_and_media/audio.py @@ -58,10 +58,6 @@ class Audio(Object): Thumbnails of the music file album cover. """ - __slots__ = [ - "file_id", "file_name", "mime_type", "file_size", "date", "duration", "performer", "title", "thumbs" - ] - def __init__( self, *, diff --git a/pyrogram/client/types/messages_and_media/contact.py b/pyrogram/client/types/messages_and_media/contact.py index d18f5e18..ad263397 100644 --- a/pyrogram/client/types/messages_and_media/contact.py +++ b/pyrogram/client/types/messages_and_media/contact.py @@ -42,8 +42,6 @@ class Contact(Object): Additional data about the contact in the form of a vCard. """ - __slots__ = ["phone_number", "first_name", "last_name", "user_id", "vcard"] - def __init__( self, *, diff --git a/pyrogram/client/types/messages_and_media/document.py b/pyrogram/client/types/messages_and_media/document.py index 45994e16..4bb40980 100644 --- a/pyrogram/client/types/messages_and_media/document.py +++ b/pyrogram/client/types/messages_and_media/document.py @@ -49,8 +49,6 @@ class Document(Object): Document thumbnails as defined by sender. """ - __slots__ = ["file_id", "file_name", "mime_type", "file_size", "date", "thumbs"] - def __init__( self, *, diff --git a/pyrogram/client/types/messages_and_media/game.py b/pyrogram/client/types/messages_and_media/game.py index 2b400e65..38c00fdf 100644 --- a/pyrogram/client/types/messages_and_media/game.py +++ b/pyrogram/client/types/messages_and_media/game.py @@ -48,8 +48,6 @@ class Game(Object): Upload via BotFather. """ - __slots__ = ["id", "title", "short_name", "description", "photo", "animation"] - def __init__( self, *, diff --git a/pyrogram/client/types/messages_and_media/location.py b/pyrogram/client/types/messages_and_media/location.py index 5af55f0f..4dec0277 100644 --- a/pyrogram/client/types/messages_and_media/location.py +++ b/pyrogram/client/types/messages_and_media/location.py @@ -33,8 +33,6 @@ class Location(Object): Latitude as defined by sender. """ - __slots__ = ["longitude", "latitude"] - def __init__( self, *, diff --git a/pyrogram/client/types/messages_and_media/message.py b/pyrogram/client/types/messages_and_media/message.py index 43041ee6..58c461bd 100644 --- a/pyrogram/client/types/messages_and_media/message.py +++ b/pyrogram/client/types/messages_and_media/message.py @@ -31,7 +31,8 @@ from ..object import Object from ..update import Update from ..user_and_chats.chat import Chat from ..user_and_chats.user import User -from ...parser import utils, Parser +from ...ext import utils +from ...parser import utils as parser_utils, Parser class Str(str): @@ -54,7 +55,7 @@ class Str(str): return Parser.unparse(self, self.entities, True) def __getitem__(self, item): - return utils.remove_surrogates(utils.add_surrogates(self)[item]) + return parser_utils.remove_surrogates(parser_utils.add_surrogates(self)[item]) class Message(Object, Update): @@ -263,17 +264,6 @@ class Message(Object, Update): # TODO: Add game missing field. Also invoice, successful_payment, connected_website - __slots__ = [ - "message_id", "date", "chat", "from_user", "forward_from", "forward_sender_name", "forward_from_chat", - "forward_from_message_id", "forward_signature", "forward_date", "reply_to_message", "mentioned", "empty", - "service", "media", "edit_date", "media_group_id", "author_signature", "text", "entities", "caption_entities", - "audio", "document", "photo", "sticker", "animation", "game", "video", "voice", "video_note", "caption", - "contact", "location", "venue", "web_page", "poll", "new_chat_members", "left_chat_member", "new_chat_title", - "new_chat_photo", "delete_chat_photo", "group_chat_created", "supergroup_chat_created", "channel_chat_created", - "migrate_to_chat_id", "migrate_from_chat_id", "pinned_message", "game_high_score", "views", "via_bot", - "outgoing", "matches", "command", "reply_markup" - ] - def __init__( self, *, @@ -446,7 +436,7 @@ class Message(Object, Update): 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_to_chat_id=utils.get_channel_id(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, @@ -602,10 +592,26 @@ class Message(Object, Update): 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(entities) or None if media is None else None, - caption=Str(message.message).init(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, + text=( + Str(message.message).init(entities) or None + if media is None or web_page is not None + else None + ), + caption=( + Str(message.message).init(entities) or None + if media is not None and web_page is None + else None + ), + entities=( + entities or None + if media is None or web_page is not None + else None + ), + caption_entities=( + entities or None + if media is not None and web_page is None + else None + ), author_signature=message.post_author, forward_from=forward_from, forward_sender_name=forward_sender_name, diff --git a/pyrogram/client/types/messages_and_media/message_entity.py b/pyrogram/client/types/messages_and_media/message_entity.py index 1c3076a2..63aeb447 100644 --- a/pyrogram/client/types/messages_and_media/message_entity.py +++ b/pyrogram/client/types/messages_and_media/message_entity.py @@ -47,8 +47,6 @@ class MessageEntity(Object): For "text_mention" only, the mentioned user. """ - __slots__ = ["type", "offset", "length", "url", "user"] - ENTITIES = { types.MessageEntityMention.ID: "mention", types.MessageEntityHashtag.ID: "hashtag", diff --git a/pyrogram/client/types/messages_and_media/photo.py b/pyrogram/client/types/messages_and_media/photo.py index 653fe4c0..8ccaaf19 100644 --- a/pyrogram/client/types/messages_and_media/photo.py +++ b/pyrogram/client/types/messages_and_media/photo.py @@ -49,8 +49,6 @@ class Photo(Object): Available thumbnails of this photo. """ - __slots__ = ["file_id", "width", "height", "file_size", "date", "thumbs"] - def __init__( self, *, diff --git a/pyrogram/client/types/messages_and_media/poll.py b/pyrogram/client/types/messages_and_media/poll.py index 2570fdf1..fecc5f7d 100644 --- a/pyrogram/client/types/messages_and_media/poll.py +++ b/pyrogram/client/types/messages_and_media/poll.py @@ -48,8 +48,6 @@ class Poll(Object, Update): Index of your chosen option (0-9), None in case you haven't voted yet. """ - __slots__ = ["id", "question", "options", "is_closed", "total_voters", "chosen_option"] - def __init__( self, *, diff --git a/pyrogram/client/types/messages_and_media/poll_option.py b/pyrogram/client/types/messages_and_media/poll_option.py index 35f6b071..2882860a 100644 --- a/pyrogram/client/types/messages_and_media/poll_option.py +++ b/pyrogram/client/types/messages_and_media/poll_option.py @@ -35,8 +35,6 @@ class PollOption(Object): The data this poll option is holding. """ - __slots__ = ["text", "voter_count", "data"] - def __init__( self, *, diff --git a/pyrogram/client/types/messages_and_media/sticker.py b/pyrogram/client/types/messages_and_media/sticker.py index 6460cd81..4a9f6d8c 100644 --- a/pyrogram/client/types/messages_and_media/sticker.py +++ b/pyrogram/client/types/messages_and_media/sticker.py @@ -66,10 +66,6 @@ class Sticker(Object): # TODO: Add mask position - __slots__ = [ - "file_id", "file_name", "mime_type", "file_size", "date", "width", "height", "emoji", "set_name", "thumbs" - ] - def __init__( self, *, diff --git a/pyrogram/client/types/messages_and_media/stripped_thumbnail.py b/pyrogram/client/types/messages_and_media/stripped_thumbnail.py index 1c967042..ea24e071 100644 --- a/pyrogram/client/types/messages_and_media/stripped_thumbnail.py +++ b/pyrogram/client/types/messages_and_media/stripped_thumbnail.py @@ -29,8 +29,6 @@ class StrippedThumbnail(Object): Thumbnail data """ - __slots__ = ["data"] - def __init__( self, *, diff --git a/pyrogram/client/types/messages_and_media/thumbnail.py b/pyrogram/client/types/messages_and_media/thumbnail.py index ee173b1c..936241c6 100644 --- a/pyrogram/client/types/messages_and_media/thumbnail.py +++ b/pyrogram/client/types/messages_and_media/thumbnail.py @@ -43,8 +43,6 @@ class Thumbnail(Object): File size. """ - __slots__ = ["file_id", "width", "height", "file_size"] - def __init__( self, *, diff --git a/pyrogram/client/types/messages_and_media/venue.py b/pyrogram/client/types/messages_and_media/venue.py index 45d9368f..419af318 100644 --- a/pyrogram/client/types/messages_and_media/venue.py +++ b/pyrogram/client/types/messages_and_media/venue.py @@ -44,8 +44,6 @@ class Venue(Object): """ - __slots__ = ["location", "title", "address", "foursquare_id", "foursquare_type"] - def __init__( self, *, diff --git a/pyrogram/client/types/messages_and_media/video.py b/pyrogram/client/types/messages_and_media/video.py index 0a7f47cd..d9c2c37f 100644 --- a/pyrogram/client/types/messages_and_media/video.py +++ b/pyrogram/client/types/messages_and_media/video.py @@ -61,11 +61,6 @@ class Video(Object): Video thumbnails. """ - __slots__ = [ - "file_id", "width", "height", "duration", "file_name", "mime_type", "supports_streaming", "file_size", "date", - "thumbs" - ] - def __init__( self, *, diff --git a/pyrogram/client/types/messages_and_media/video_note.py b/pyrogram/client/types/messages_and_media/video_note.py index 54c9ec8d..e419d692 100644 --- a/pyrogram/client/types/messages_and_media/video_note.py +++ b/pyrogram/client/types/messages_and_media/video_note.py @@ -52,8 +52,6 @@ class VideoNote(Object): Video thumbnails. """ - __slots__ = ["file_id", "mime_type", "file_size", "date", "length", "duration", "thumbs"] - def __init__( self, *, diff --git a/pyrogram/client/types/messages_and_media/voice.py b/pyrogram/client/types/messages_and_media/voice.py index e4256197..0f480ad5 100644 --- a/pyrogram/client/types/messages_and_media/voice.py +++ b/pyrogram/client/types/messages_and_media/voice.py @@ -47,8 +47,6 @@ class Voice(Object): Date the voice was sent in Unix time. """ - __slots__ = ["file_id", "duration", "waveform", "mime_type", "file_size", "date"] - def __init__( self, *, diff --git a/pyrogram/client/types/messages_and_media/webpage.py b/pyrogram/client/types/messages_and_media/webpage.py index 9ddc7c6c..d65d34d8 100644 --- a/pyrogram/client/types/messages_and_media/webpage.py +++ b/pyrogram/client/types/messages_and_media/webpage.py @@ -83,12 +83,6 @@ class WebPage(Object): Author of the webpage, eg the Twitter user for a tweet, or the author in an article. """ - __slots__ = [ - "id", "url", "display_url", "type", "site_name", "title", "description", - "audio", "document", "photo", "animation", "video", - "embed_url", "embed_type", "embed_width", "embed_height", "duration", "author" - ] - def __init__( self, *, diff --git a/pyrogram/client/types/object.py b/pyrogram/client/types/object.py index f7fc413f..5978203f 100644 --- a/pyrogram/client/types/object.py +++ b/pyrogram/client/types/object.py @@ -29,8 +29,6 @@ class Meta(type, metaclass=type("", (type,), {"__str__": lambda _: "~hi"})): class Object(metaclass=Meta): - __slots__ = ["_client"] - def __init__(self, client: "pyrogram.BaseClient" = None): self._client = client @@ -50,7 +48,7 @@ class Object(metaclass=Meta): else (attr, str(datetime.fromtimestamp(getattr(obj, attr)))) if attr.endswith("date") else (attr, getattr(obj, attr)) - for attr in getattr(obj, "__slots__", []) + for attr in filter(lambda x: not x.startswith("_"), obj.__dict__) if getattr(obj, attr) is not None ] ) @@ -63,13 +61,13 @@ class Object(metaclass=Meta): self.__class__.__name__, ", ".join( "{}={}".format(attr, repr(getattr(self, attr))) - for attr in self.__slots__ + for attr in filter(lambda x: not x.startswith("_"), self.__dict__) if getattr(self, attr) is not None ) ) def __eq__(self, other: "Object") -> bool: - for attr in self.__slots__: + for attr in self.__dict__: try: if getattr(self, attr) != getattr(other, attr): return False diff --git a/pyrogram/client/types/update.py b/pyrogram/client/types/update.py index f129b4ce..37307111 100644 --- a/pyrogram/client/types/update.py +++ b/pyrogram/client/types/update.py @@ -26,8 +26,6 @@ class ContinuePropagation(StopAsyncIteration): class Update: - __slots__ = [] - def stop_propagation(self): raise StopPropagation diff --git a/pyrogram/client/types/user_and_chats/chat.py b/pyrogram/client/types/user_and_chats/chat.py index a4d51d1f..d3606b82 100644 --- a/pyrogram/client/types/user_and_chats/chat.py +++ b/pyrogram/client/types/user_and_chats/chat.py @@ -23,6 +23,7 @@ from pyrogram.api import types from .chat_permissions import ChatPermissions from .chat_photo import ChatPhoto from ..object import Object +from ...ext import utils class Chat(Object): @@ -94,12 +95,6 @@ class Chat(Object): Information about the chat default permissions, for groups and supergroups. """ - __slots__ = [ - "id", "type", "is_verified", "is_restricted", "is_scam", "is_support", "title", "username", "first_name", - "last_name", "photo", "description", "invite_link", "pinned_message", "sticker_set_name", "can_set_sticker_set", - "members_count", "restriction_reason", "permissions" - ] - def __init__( self, *, @@ -180,7 +175,7 @@ class Chat(Object): @staticmethod def _parse_channel_chat(client, channel: types.Channel) -> "Chat": - peer_id = int("-100" + str(channel.id)) + peer_id = utils.get_channel_id(channel.id) return Chat( id=peer_id, diff --git a/pyrogram/client/types/user_and_chats/chat_member.py b/pyrogram/client/types/user_and_chats/chat_member.py index 7451012c..42eb08f3 100644 --- a/pyrogram/client/types/user_and_chats/chat_member.py +++ b/pyrogram/client/types/user_and_chats/chat_member.py @@ -54,8 +54,6 @@ class ChatMember(Object): Information about the member permissions. """ - __slots__ = ["user", "status", "date", "is_member", "invited_by", "promoted_by", "restricted_by", "permissions"] - def __init__( self, *, diff --git a/pyrogram/client/types/user_and_chats/chat_permissions.py b/pyrogram/client/types/user_and_chats/chat_permissions.py index 84099955..551dc667 100644 --- a/pyrogram/client/types/user_and_chats/chat_permissions.py +++ b/pyrogram/client/types/user_and_chats/chat_permissions.py @@ -94,13 +94,6 @@ class ChatPermissions(Object): True, if polls can be sent, implies can_send_media_messages. """ - __slots__ = [ - "until_date", "can_be_edited", "can_change_info", "can_post_messages", "can_edit_messages", - "can_delete_messages", "can_restrict_members", "can_invite_users", "can_pin_messages", "can_promote_members", - "can_send_messages", "can_send_media_messages", "can_send_other_messages", "can_add_web_page_previews", - "can_send_polls" - ] - def __init__( self, *, diff --git a/pyrogram/client/types/user_and_chats/chat_photo.py b/pyrogram/client/types/user_and_chats/chat_photo.py index 1584a286..70e114af 100644 --- a/pyrogram/client/types/user_and_chats/chat_photo.py +++ b/pyrogram/client/types/user_and_chats/chat_photo.py @@ -35,8 +35,6 @@ class ChatPhoto(Object): Unique file identifier of big (640x640) chat photo. This file_id can be used only for photo download. """ - __slots__ = ["small_file_id", "big_file_id"] - def __init__( self, *, diff --git a/pyrogram/client/types/user_and_chats/chat_preview.py b/pyrogram/client/types/user_and_chats/chat_preview.py index 781f85c8..10754170 100644 --- a/pyrogram/client/types/user_and_chats/chat_preview.py +++ b/pyrogram/client/types/user_and_chats/chat_preview.py @@ -45,8 +45,6 @@ class ChatPreview(Object): Preview of some of the chat members. """ - __slots__ = ["title", "type", "members_count", "photo", "members"] - def __init__( self, *, diff --git a/pyrogram/client/types/user_and_chats/dialog.py b/pyrogram/client/types/user_and_chats/dialog.py index 4ea82184..471c4319 100644 --- a/pyrogram/client/types/user_and_chats/dialog.py +++ b/pyrogram/client/types/user_and_chats/dialog.py @@ -21,6 +21,7 @@ import pyrogram from pyrogram.api import types from ..object import Object from ..user_and_chats import Chat +from ...ext import utils class Dialog(Object): @@ -46,8 +47,6 @@ class Dialog(Object): True, if the dialog is pinned. """ - __slots__ = ["chat", "top_message", "unread_messages_count", "unread_mentions_count", "unread_mark", "is_pinned"] - def __init__( self, *, @@ -70,18 +69,9 @@ class Dialog(Object): @staticmethod def _parse(client, dialog: types.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), + top_message=messages.get(utils.get_peer_id(dialog.peer)), unread_messages_count=dialog.unread_count, unread_mentions_count=dialog.unread_mentions_count, unread_mark=dialog.unread_mark, diff --git a/pyrogram/client/types/user_and_chats/user.py b/pyrogram/client/types/user_and_chats/user.py index b0bc1bfe..bfc1fc08 100644 --- a/pyrogram/client/types/user_and_chats/user.py +++ b/pyrogram/client/types/user_and_chats/user.py @@ -106,12 +106,6 @@ class User(Object, Update): This field is available only in case *is_restricted* is True. """ - __slots__ = [ - "id", "is_self", "is_contact", "is_mutual_contact", "is_deleted", "is_bot", "is_verified", "is_restricted", - "is_scam", "is_support", "first_name", "last_name", "status", "last_online_date", "next_offline_date", - "username", "language_code", "dc_id", "phone_number", "photo", "restriction_reason" - ] - def __init__( self, *, diff --git a/pyrogram/errors/rpc_error.py b/pyrogram/errors/rpc_error.py index 806b5373..9969d3fa 100644 --- a/pyrogram/errors/rpc_error.py +++ b/pyrogram/errors/rpc_error.py @@ -21,8 +21,9 @@ from datetime import datetime from importlib import import_module from typing import Type -from pyrogram.api.core import TLObject from pyrogram.api.types import RpcError as RawRPCError + +from pyrogram.api.core import TLObject from .exceptions.all import exceptions diff --git a/pyrogram/session/auth.py b/pyrogram/session/auth.py index 135100e2..ba0f5aed 100644 --- a/pyrogram/session/auth.py +++ b/pyrogram/session/auth.py @@ -28,7 +28,6 @@ from pyrogram.api import functions, types from pyrogram.api.core import TLObject, Long, Int from pyrogram.connection import Connection from pyrogram.crypto import AES, RSA, Prime - from .internals import MsgId log = logging.getLogger(__name__) diff --git a/pyrogram/session/internals/msg_factory.py b/pyrogram/session/internals/msg_factory.py index 2b833ce8..453eefc1 100644 --- a/pyrogram/session/internals/msg_factory.py +++ b/pyrogram/session/internals/msg_factory.py @@ -16,9 +16,10 @@ # You should have received a copy of the GNU Lesser General Public License # along with Pyrogram. If not, see . -from pyrogram.api.core import Message, MsgContainer, TLObject from pyrogram.api.functions import Ping from pyrogram.api.types import MsgsAck, HttpWait + +from pyrogram.api.core import Message, MsgContainer, TLObject from .msg_id import MsgId from .seq_no import SeqNo diff --git a/pyrogram/session/session.py b/pyrogram/session/session.py index e4699f7d..a0d879b4 100644 --- a/pyrogram/session/session.py +++ b/pyrogram/session/session.py @@ -22,15 +22,15 @@ from datetime import datetime, timedelta from hashlib import sha1 from io import BytesIO +from pyrogram.api.all import layer + import pyrogram from pyrogram import __copyright__, __license__, __version__ from pyrogram.api import functions, types -from pyrogram.api.all import layer from pyrogram.api.core import TLObject, MsgContainer, Int, Long, FutureSalt, FutureSalts from pyrogram.connection import Connection from pyrogram.crypto import MTProto from pyrogram.errors import RPCError, InternalServerError, AuthKeyDuplicated - from .internals import MsgId, MsgFactory log = logging.getLogger(__name__)