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