diff --git a/pyrogram/client.py b/pyrogram/client.py index 6907ee05fc..874ccec5c9 100644 --- a/pyrogram/client.py +++ b/pyrogram/client.py @@ -362,6 +362,8 @@ def __init__( self.message_cache = Cache(self.max_message_cache_size) self.business_user_connection_cache = Cache(self.max_business_user_connection_cache_size) + self.app_constant: dict[str, "types.ClientConfigurationOption"] = {} + # Sometimes, for some reason, the server will stop sending updates and will only respond to pings. # This watchdog will invoke updates.GetState in order to wake up the server and enable it sending updates again # after some idle time has been detected. diff --git a/pyrogram/methods/bots/answer_inline_query.py b/pyrogram/methods/bots/answer_inline_query.py index c3a450a015..c8d851ab46 100644 --- a/pyrogram/methods/bots/answer_inline_query.py +++ b/pyrogram/methods/bots/answer_inline_query.py @@ -96,6 +96,8 @@ async def answer_inline_query( InputTextMessageContent("Message content"))]) """ + utils.check_valid_length(client=self, text=results, arg_type="inline_query_results_max") + return await self.invoke( raw.functions.messages.SetInlineBotResults( query_id=int(inline_query_id), diff --git a/pyrogram/methods/chats/set_administrator_title.py b/pyrogram/methods/chats/set_administrator_title.py index 2c77066ed7..8951d31fd9 100644 --- a/pyrogram/methods/chats/set_administrator_title.py +++ b/pyrogram/methods/chats/set_administrator_title.py @@ -16,7 +16,7 @@ # You should have received a copy of the GNU Lesser General Public License # along with Pyrogram. If not, see . -from typing import Union +from typing import Optional, Union import pyrogram from pyrogram import raw @@ -27,7 +27,7 @@ async def set_administrator_title( self: "pyrogram.Client", chat_id: Union[int, str], user_id: Union[int, str], - title: str, + title: Optional[str] = None, ) -> bool: """Set a custom title (rank) to an administrator of a supergroup. @@ -45,6 +45,7 @@ async def set_administrator_title( For a contact that exists in your Telegram address book you can use his phone number (str). title (``str``, *optional*): + New custom title for the administrator; 0-16 characters, emoji are not allowed. A custom title that will be shown to all members instead of "Owner" or "Admin". Pass None or "" (empty string) to remove the custom title. @@ -56,6 +57,10 @@ async def set_administrator_title( await app.set_administrator_title(chat_id, user_id, "Admin Title") """ + + if title: + utils.check_valid_length(client=self, text=title, arg_type="administrator_title_length_max") + chat_id = await self.resolve_peer(chat_id) user_id = await self.resolve_peer(user_id) diff --git a/pyrogram/methods/messages/edit_message_text.py b/pyrogram/methods/messages/edit_message_text.py index 32925fdf4a..5a9f72d634 100644 --- a/pyrogram/methods/messages/edit_message_text.py +++ b/pyrogram/methods/messages/edit_message_text.py @@ -94,6 +94,7 @@ async def edit_message_text( ) ) """ + if disable_web_page_preview and link_preview_options: raise ValueError( "Parameters `disable_web_page_preview` and `link_preview_options` are mutually " diff --git a/pyrogram/methods/messages/send_message.py b/pyrogram/methods/messages/send_message.py index 600c23b3ae..0397c6e95f 100644 --- a/pyrogram/methods/messages/send_message.py +++ b/pyrogram/methods/messages/send_message.py @@ -161,6 +161,7 @@ async def send_message( ] ])) """ + if disable_web_page_preview and link_preview_options: raise ValueError( "Parameters `disable_web_page_preview` and `link_preview_options` are mutually " @@ -196,6 +197,9 @@ async def send_message( ) message, entities = (await utils.parse_text_entities(self, text, parse_mode, entities)).values() + if message: + utils.check_valid_length(client=self, text=message, arg_type="message_length_max") + session = None business_connection = None if business_connection_id: diff --git a/pyrogram/methods/users/update_profile.py b/pyrogram/methods/users/update_profile.py index 6c44ffe505..b347b05c67 100644 --- a/pyrogram/methods/users/update_profile.py +++ b/pyrogram/methods/users/update_profile.py @@ -63,6 +63,12 @@ async def update_profile( await app.update_profile(last_name="") """ + for var_name in ("first_name", "last_name",): + if var_value := locals()[var_name]: + utils.check_valid_length(client=self, text=var_value, arg_type="name_length_max") + if bio: + utils.check_valid_length(client=self, text=bio, arg_type="about_length_max") + return bool( await self.invoke( raw.functions.account.UpdateProfile( diff --git a/pyrogram/session/session.py b/pyrogram/session/session.py index 5df270bdae..4dfc82ddab 100644 --- a/pyrogram/session/session.py +++ b/pyrogram/session/session.py @@ -24,7 +24,7 @@ from io import BytesIO import pyrogram -from pyrogram import raw +from pyrogram import raw, types from pyrogram.connection import Connection from pyrogram.crypto import mtproto from pyrogram.errors import ( @@ -125,7 +125,7 @@ async def start(self): await self.send(raw.functions.Ping(ping_id=0), timeout=self.START_TIMEOUT) if not self.is_cdn: - await self.send( + cfg = await self.send( raw.functions.InvokeWithLayer( layer=layer, query=raw.functions.InitConnection( @@ -146,6 +146,57 @@ async def start(self): ), timeout=self.START_TIMEOUT ) + if isinstance(cfg, raw.types.Config): # TODO + for key in [ + "chat_size_max", + "megagroup_size_max", + "forwarded_count_max", + "online_update_period_ms", + "online_cloud_timeout_ms", + "edit_time_limit", + "revoke_time_limit", + "revoke_pm_time_limit", + "stickers_recent_limit", + "channels_read_media_period", + "me_url_prefix", + "caption_length_max", + "message_length_max", + "gif_search_username", + "venue_search_username", + "img_search_username", + "autologin_token", + ]: + self.client.app_constant[ + key + ] = types.ClientConfigurationOption( + key=key, + value=getattr(cfg, key, None) + ) if getattr(cfg, key, None) else None + self.client.app_constant[ + "name_length_max" + ] = types.ClientConfigurationOption( + key="name_length_max", + value=64 + ) + self.client.app_constant[ + "administrator_title_length_max" + ] = types.ClientConfigurationOption( + key="administrator_title_length_max", + value=16 + ) + self.client.app_constant[ + "inline_query_results_max" + ] = types.ClientConfigurationOption( + key="inline_query_results_max", + value=50 + ) + # TODO + self.client.app_constant[ + "about_length_max" + ] = types.ClientConfigurationOption( + key="about_length_max", + value=70, # 140 + ) self.ping_task = self.loop.create_task(self.ping_worker()) diff --git a/pyrogram/types/__init__.py b/pyrogram/types/__init__.py index d9b19d3d83..a219d7618c 100644 --- a/pyrogram/types/__init__.py +++ b/pyrogram/types/__init__.py @@ -23,6 +23,7 @@ from .bots_and_keyboards import * from .chat_drafts import * from .chat_topics import * +from .client_configuration import * from .inline_mode import * from .input_media import * from .input_paid_media import * diff --git a/pyrogram/types/chat_topics/__init__.py b/pyrogram/types/chat_topics/__init__.py index 5546352284..2474bef682 100644 --- a/pyrogram/types/chat_topics/__init__.py +++ b/pyrogram/types/chat_topics/__init__.py @@ -1,5 +1,5 @@ # Pyrogram - Telegram MTProto API Client Library for Python -# Copyright (C) 2017-present Dan +# Copyright (C) 2017-present # # This file is part of Pyrogram. # diff --git a/pyrogram/types/client_configuration/__init__.py b/pyrogram/types/client_configuration/__init__.py new file mode 100644 index 0000000000..ecac61b410 --- /dev/null +++ b/pyrogram/types/client_configuration/__init__.py @@ -0,0 +1,24 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-present +# +# 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 .client_configuration_option import ClientConfigurationOption + + +__all__ = [ + "ClientConfigurationOption", +] diff --git a/pyrogram/types/client_configuration/client_configuration_option.py b/pyrogram/types/client_configuration/client_configuration_option.py new file mode 100644 index 0000000000..a652441359 --- /dev/null +++ b/pyrogram/types/client_configuration/client_configuration_option.py @@ -0,0 +1,46 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-present +# +# This file is part of Pyrogram. +# +# Pyrogram is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pyrogram is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Pyrogram. If not, see . + + +from typing import Optional, Union + +from ..object import Object + + +class ClientConfigurationOption(Object): + """This object represents the value of an option. + + Parameters: + key (``str``): + The name of the option. + + value (``bool`` | ``int`` | ``str``, *optional*): + The value of the option. Can be None if it is an unknown option or an option which has a default value. + + """ + + def __init__( + self, + *, + key: str = None, + value: Union[bool, int, str] = None, + ): + super().__init__() + + self.key = key + self.value = value diff --git a/pyrogram/utils.py b/pyrogram/utils.py index a75891ff64..fe07216f36 100644 --- a/pyrogram/utils.py +++ b/pyrogram/utils.py @@ -659,3 +659,22 @@ def is_list_like(obj): Ported from https://github.com/LonamiWebs/Telethon/blob/1cb5ff1dd54ecfad41711fc5a4ecf36d2ad8eaf6/telethon/utils.py#L902 """ return isinstance(obj, (list, tuple, set, dict, range)) + + +def check_valid_length( + client: "pyrogram.Client", + text: Union[list, str], + arg_type: str, +): + if not isinstance(text, (str, list)): + raise ValueError(f"Argument {arg_type} must be a str | list") + + text_length = len(text) + max_length = client.app_constant.get(arg_type) + + if not max_length: + raise ValueError(f"Argument {arg_type} is not supported") + + error_info = f"\nInvalid length of {text_length} for arg {arg_type}\nValid Length: {max_length.value}" + + assert bool(text_length <= max_length.value), error_info