diff --git a/compiler/api/compiler.py b/compiler/api/compiler.py index e584d55b..de211355 100644 --- a/compiler/api/compiler.py +++ b/compiler/api/compiler.py @@ -4,7 +4,6 @@ import json import re import shutil -from functools import partial from pathlib import Path from typing import NamedTuple @@ -45,7 +44,10 @@ # # # # # # # # # # # # # # # # # # # # # # # # """.strip() -open = partial(open, encoding="utf-8") + +def open_utf8(path: str | Path, mode: str = "r", *args, **kwargs): + return open(path, mode, encoding="utf-8", *args, **kwargs) + types_to_constructors: dict[str, list[str]] = {} types_to_functions: dict[str, list[str]] = {} @@ -55,7 +57,7 @@ namespaces_to_functions: dict[str, list[str]] = {} try: - with open(API_HOME_PATH / "docs.json") as f: + with open_utf8(API_HOME_PATH / "docs.json") as f: docs = json.load(f) except FileNotFoundError: docs = {"type": {}, "constructor": {}, "method": {}} @@ -190,23 +192,23 @@ def start() -> None: # noqa: C901 shutil.rmtree(DESTINATION_PATH / "base", ignore_errors=True) with ( - open(API_HOME_PATH / "source/auth_key.tl") as f1, - open(API_HOME_PATH / "source/sys_msgs.tl") as f2, - open(API_HOME_PATH / "source/main_api.tl") as f3, + open_utf8(API_HOME_PATH / "source/auth_key.tl") as f1, + open_utf8(API_HOME_PATH / "source/sys_msgs.tl") as f2, + open_utf8(API_HOME_PATH / "source/main_api.tl") as f3, ): - schema = (f1.read() + f2.read() + f3.read()).splitlines() + schema = (str(f1.read()) + str(f2.read()) + str(f3.read())).splitlines() with ( - open(API_HOME_PATH / "template/type.txt") as f1, - open(API_HOME_PATH / "template/combinator.txt") as f2, + open_utf8(API_HOME_PATH / "template/type.txt") as f1, + open_utf8(API_HOME_PATH / "template/combinator.txt") as f2, ): - type_tmpl = f1.read() - combinator_tmpl = f2.read() + type_tmpl = str(f1.read()) + combinator_tmpl = str(f2.read()) layer = None combinators: list[Combinator] = [] - section = None + section = "" for line in schema: if section_match := SECTION_RE.match(line): section = section_match.group(1) @@ -319,7 +321,7 @@ def start() -> None: # noqa: C901 if references: docstring += f"\n\n Functions:\n This object can be returned by {ref_count} function{'s' if ref_count > 1 else ''}.\n\n .. currentmodule:: pyrogram.raw.functions\n\n .. autosummary::\n :nosignatures:\n\n {references}" - with open(dir_path / f"{snake(module)}.py", "w") as f: + with open_utf8(dir_path / f"{snake(module)}.py", "w") as f: f.write( type_tmpl.format( warning=WARNING, @@ -499,8 +501,18 @@ def start() -> None: # noqa: C901 slots = ", ".join([f'"{i[0]}"' for i in sorted_args]) return_arguments = ", ".join([f"{i[0]}={i[0]}" for i in sorted_args]) + base_class = ( + f"raw.base.{c.qualtype}" + if c.qualtype in types_to_constructors + else "TLObject" + ) + + if c.section == "functions": + base_class = "TLObject" + compiled_combinator = combinator_tmpl.format( warning=WARNING, + base=base_class, name=c.name, docstring=docstring, slots=slots, @@ -524,7 +536,7 @@ def start() -> None: # noqa: C901 if module == "Updates": module = "UpdatesT" - with open(dir_path / f"{snake(module)}.py", "w") as f: + with open_utf8(dir_path / f"{snake(module)}.py", "w") as f: f.write(compiled_combinator) d = ( @@ -539,7 +551,9 @@ def start() -> None: # noqa: C901 d[c.namespace].append(c.name) for namespace, types in namespaces_to_types.items(): - with open(DESTINATION_PATH / "base" / namespace / "__init__.py", "w") as f: + with open_utf8( + DESTINATION_PATH / "base" / namespace / "__init__.py", "w" + ) as f: f.write(f"{WARNING}\n\n") all = [] @@ -567,7 +581,9 @@ def start() -> None: # noqa: C901 f.write("]\n") for namespace, types in namespaces_to_constructors.items(): - with open(DESTINATION_PATH / "types" / namespace / "__init__.py", "w") as f: + with open_utf8( + DESTINATION_PATH / "types" / namespace / "__init__.py", "w" + ) as f: f.write(f"{WARNING}\n\n") all = [] @@ -595,7 +611,7 @@ def start() -> None: # noqa: C901 f.write("]\n") for namespace, types in namespaces_to_functions.items(): - with open( + with open_utf8( DESTINATION_PATH / "functions" / namespace / "__init__.py", "w", ) as f: @@ -625,7 +641,7 @@ def start() -> None: # noqa: C901 f.write(f' "{it}",\n') f.write("]\n") - with open(DESTINATION_PATH / "all.py", "w", encoding="utf-8") as f: + with open_utf8(DESTINATION_PATH / "all.py", "w") as f: f.write(WARNING + "\n\n") f.write(f"layer = {layer}\n\n") f.write("objects = {") diff --git a/compiler/api/template/combinator.txt b/compiler/api/template/combinator.txt index 379b3fb9..d86c6486 100644 --- a/compiler/api/template/combinator.txt +++ b/compiler/api/template/combinator.txt @@ -8,7 +8,7 @@ from typing import List, Optional, Any {warning} -class {name}(TLObject): # type: ignore +class {name}({base}): # type: ignore """{docstring} """ diff --git a/compiler/api/template/type.txt b/compiler/api/template/type.txt index 0aaf00e9..2178b29a 100644 --- a/compiler/api/template/type.txt +++ b/compiler/api/template/type.txt @@ -1,13 +1,8 @@ {warning} -from typing import Union -from pyrogram import raw from pyrogram.raw.core import TLObject -{name} = Union[{types}] - - -class {name}: # type: ignore +class {name}(TLObject): # type: ignore """{docstring} """ diff --git a/compiler/docs/compiler.py b/compiler/docs/compiler.py index f28b0144..84f8bfa1 100644 --- a/compiler/docs/compiler.py +++ b/compiler/docs/compiler.py @@ -6,6 +6,8 @@ from pathlib import Path # Paths +page_template = "" +toctree = "" HOME = "compiler/docs" DESTINATION = "docs/source/telegram" PYROGRAM_API_DEST = "docs/source/api" diff --git a/pyrogram/errors/rpc_error.py b/pyrogram/errors/rpc_error.py index cbd2f432..ad071b07 100644 --- a/pyrogram/errors/rpc_error.py +++ b/pyrogram/errors/rpc_error.py @@ -21,7 +21,7 @@ class RPCError(Exception): def __init__( self, - value: int | str | raw.types.RpcError = None, + value: int | str | raw.types.RpcError | None = None, rpc_name: str | None = None, is_unknown: bool = False, is_signed: bool = False, diff --git a/pyrogram/file_id.py b/pyrogram/file_id.py index 80d44408..20259eae 100644 --- a/pyrogram/file_id.py +++ b/pyrogram/file_id.py @@ -154,8 +154,8 @@ def __init__( media_id: int | None = None, access_hash: int | None = None, volume_id: int | None = None, - thumbnail_source: ThumbnailSource = None, - thumbnail_file_type: FileType = None, + thumbnail_source: ThumbnailSource | None = None, + thumbnail_file_type: FileType | None = None, thumbnail_size: str = "", secret: int | None = None, local_id: int | None = None, diff --git a/pyrogram/handlers/deleted_bot_business_messages_handler.py b/pyrogram/handlers/deleted_bot_business_messages_handler.py index 4d518d01..806141dd 100644 --- a/pyrogram/handlers/deleted_bot_business_messages_handler.py +++ b/pyrogram/handlers/deleted_bot_business_messages_handler.py @@ -36,7 +36,7 @@ class DeletedBotBusinessMessagesHandler(Handler): The deleted messages, as list. """ - def __init__(self, callback: Callable, filters: Filter = None) -> None: + def __init__(self, callback: Callable, filters: Filter | None = None) -> None: super().__init__(callback, filters) async def check(self, client: pyrogram.Client, messages: list[Message]) -> bool: diff --git a/pyrogram/handlers/deleted_messages_handler.py b/pyrogram/handlers/deleted_messages_handler.py index 27865961..caccf96c 100644 --- a/pyrogram/handlers/deleted_messages_handler.py +++ b/pyrogram/handlers/deleted_messages_handler.py @@ -36,7 +36,7 @@ class DeletedMessagesHandler(Handler): The deleted messages, as list. """ - def __init__(self, callback: Callable, filters: Filter = None) -> None: + def __init__(self, callback: Callable, filters: Filter | None = None) -> None: super().__init__(callback, filters) async def check(self, client: pyrogram.Client, messages: list[Message]) -> bool: diff --git a/pyrogram/handlers/handler.py b/pyrogram/handlers/handler.py index d4673a9f..cc820f55 100644 --- a/pyrogram/handlers/handler.py +++ b/pyrogram/handlers/handler.py @@ -12,7 +12,7 @@ class Handler: - def __init__(self, callback: Callable, filters: Filter = None) -> None: + def __init__(self, callback: Callable, filters: Filter | None = None) -> None: self.callback = callback self.filters = filters diff --git a/pyrogram/methods/bots/delete_bot_commands.py b/pyrogram/methods/bots/delete_bot_commands.py index b0409a14..b62f8d9e 100644 --- a/pyrogram/methods/bots/delete_bot_commands.py +++ b/pyrogram/methods/bots/delete_bot_commands.py @@ -7,7 +7,7 @@ class DeleteBotCommands: async def delete_bot_commands( self: pyrogram.Client, - scope: types.BotCommandScope = None, + scope: types.BotCommandScope | None = None, language_code: str = "", ) -> bool: """Delete the list of the bot's commands for the given scope and user language. diff --git a/pyrogram/methods/bots/get_bot_commands.py b/pyrogram/methods/bots/get_bot_commands.py index 6a6af5c6..dc62a5c6 100644 --- a/pyrogram/methods/bots/get_bot_commands.py +++ b/pyrogram/methods/bots/get_bot_commands.py @@ -7,7 +7,7 @@ class GetBotCommands: async def get_bot_commands( self: pyrogram.Client, - scope: types.BotCommandScope = None, + scope: types.BotCommandScope | None = None, language_code: str = "", ) -> list[types.BotCommand]: """Get the current list of the bot's commands for the given scope and user language. diff --git a/pyrogram/methods/bots/send_game.py b/pyrogram/methods/bots/send_game.py index a579f91e..ecc03baf 100644 --- a/pyrogram/methods/bots/send_game.py +++ b/pyrogram/methods/bots/send_game.py @@ -19,7 +19,8 @@ async def send_game( reply_markup: types.InlineKeyboardMarkup | types.ReplyKeyboardMarkup | types.ReplyKeyboardRemove - | types.ForceReply = None, + | types.ForceReply + | None = None, ) -> types.Message: """Send a game. diff --git a/pyrogram/methods/bots/set_bot_commands.py b/pyrogram/methods/bots/set_bot_commands.py index cdc11091..bc416607 100644 --- a/pyrogram/methods/bots/set_bot_commands.py +++ b/pyrogram/methods/bots/set_bot_commands.py @@ -8,7 +8,7 @@ class SetBotCommands: async def set_bot_commands( self: pyrogram.Client, commands: list[types.BotCommand], - scope: types.BotCommandScope = None, + scope: types.BotCommandScope | None = None, language_code: str = "", ) -> bool: """Set the list of the bot's commands. diff --git a/pyrogram/methods/bots/set_bot_default_privileges.py b/pyrogram/methods/bots/set_bot_default_privileges.py index 9c427765..574a6b54 100644 --- a/pyrogram/methods/bots/set_bot_default_privileges.py +++ b/pyrogram/methods/bots/set_bot_default_privileges.py @@ -7,7 +7,7 @@ class SetBotDefaultPrivileges: async def set_bot_default_privileges( self: pyrogram.Client, - privileges: types.ChatPrivileges = None, + privileges: types.ChatPrivileges | None = None, for_channels: bool | None = None, ) -> bool: """Change the default privileges requested by the bot when it's added as an administrator to groups or channels. diff --git a/pyrogram/methods/bots/set_chat_menu_button.py b/pyrogram/methods/bots/set_chat_menu_button.py index db2dd1ef..495ddd67 100644 --- a/pyrogram/methods/bots/set_chat_menu_button.py +++ b/pyrogram/methods/bots/set_chat_menu_button.py @@ -8,7 +8,7 @@ class SetChatMenuButton: async def set_chat_menu_button( self: pyrogram.Client, chat_id: int | str | None = None, - menu_button: types.MenuButton = None, + menu_button: types.MenuButton | None = None, ) -> bool: """Change the bot's menu button in a private chat, or the default menu button. diff --git a/pyrogram/methods/business/send_invoice.py b/pyrogram/methods/business/send_invoice.py index 84218bef..f7044bbc 100644 --- a/pyrogram/methods/business/send_invoice.py +++ b/pyrogram/methods/business/send_invoice.py @@ -19,13 +19,13 @@ async def send_invoice( photo_size: int | None = None, photo_mime_type: str | None = None, start_parameter: str | None = None, - extended_media: types.InputMedia = None, + extended_media: types.InputMedia | None = None, reply_to_message_id: int | None = None, message_thread_id: int | None = None, quote_text: str | None = None, allow_paid_broadcast: bool | None = None, quote_entities: list[types.MessageEntity] | None = None, - reply_markup: types.InlineKeyboardMarkup = None, + reply_markup: types.InlineKeyboardMarkup | None = None, ): """Use this method to send invoices. diff --git a/pyrogram/methods/chats/get_chat_event_log.py b/pyrogram/methods/chats/get_chat_event_log.py index f337692e..6b35a5e8 100644 --- a/pyrogram/methods/chats/get_chat_event_log.py +++ b/pyrogram/methods/chats/get_chat_event_log.py @@ -16,7 +16,7 @@ async def get_chat_event_log( query: str = "", offset_id: int = 0, limit: int = 0, - filters: types.ChatEventFilter = None, + filters: types.ChatEventFilter | None = None, user_ids: list[int | str] | None = None, ) -> AsyncGenerator[types.ChatEvent, None] | None: """Get the actions taken by chat members and administrators in the last 48h. diff --git a/pyrogram/methods/chats/promote_chat_member.py b/pyrogram/methods/chats/promote_chat_member.py index 8dcdcf9b..497097eb 100644 --- a/pyrogram/methods/chats/promote_chat_member.py +++ b/pyrogram/methods/chats/promote_chat_member.py @@ -9,7 +9,7 @@ async def promote_chat_member( self: pyrogram.Client, chat_id: int | str, user_id: int | str, - privileges: types.ChatPrivileges = None, + privileges: types.ChatPrivileges | None = None, title: str | None = None, ) -> bool: """Promote or demote a user in a supergroup or a channel. diff --git a/pyrogram/methods/chats/update_folder.py b/pyrogram/methods/chats/update_folder.py index 2f187e55..88b5dd9a 100644 --- a/pyrogram/methods/chats/update_folder.py +++ b/pyrogram/methods/chats/update_folder.py @@ -20,7 +20,7 @@ async def update_folder( exclude_muted: bool | None = None, exclude_read: bool | None = None, exclude_archived: bool | None = None, - color: enums.FolderColor = None, + color: enums.FolderColor | None = None, emoji: str | None = None, ) -> bool: """Create or update a user's folder. diff --git a/pyrogram/methods/messages/copy_message.py b/pyrogram/methods/messages/copy_message.py index 3df514b6..8b76f42d 100644 --- a/pyrogram/methods/messages/copy_message.py +++ b/pyrogram/methods/messages/copy_message.py @@ -31,6 +31,7 @@ async def copy_message( allow_paid_broadcast: bool | None = None, invert_media: bool = False, reply_markup: types.InlineKeyboardMarkup + | None | types.ReplyKeyboardMarkup | types.ReplyKeyboardRemove | types.ForceReply = None, diff --git a/pyrogram/methods/messages/edit_inline_caption.py b/pyrogram/methods/messages/edit_inline_caption.py index 6c60b53e..3cf6ddc2 100644 --- a/pyrogram/methods/messages/edit_inline_caption.py +++ b/pyrogram/methods/messages/edit_inline_caption.py @@ -13,7 +13,7 @@ async def edit_inline_caption( inline_message_id: str, caption: str, parse_mode: enums.ParseMode | None = None, - reply_markup: types.InlineKeyboardMarkup = None, + reply_markup: types.InlineKeyboardMarkup | None = None, invert_media: bool | None = None, ) -> bool: """Edit the caption of inline media messages. diff --git a/pyrogram/methods/messages/edit_inline_media.py b/pyrogram/methods/messages/edit_inline_media.py index 9a89a900..c185a8fe 100644 --- a/pyrogram/methods/messages/edit_inline_media.py +++ b/pyrogram/methods/messages/edit_inline_media.py @@ -22,7 +22,7 @@ async def edit_inline_media( self: pyrogram.Client, inline_message_id: str, media: types.InputMedia, - reply_markup: types.InlineKeyboardMarkup = None, + reply_markup: types.InlineKeyboardMarkup | None = None, ) -> bool: """Edit animation, audio, document, photo or video messages, or replace text with animation, audio, document, photo or video messages. diff --git a/pyrogram/methods/messages/edit_inline_reply_markup.py b/pyrogram/methods/messages/edit_inline_reply_markup.py index bf5d93a3..48984c4a 100644 --- a/pyrogram/methods/messages/edit_inline_reply_markup.py +++ b/pyrogram/methods/messages/edit_inline_reply_markup.py @@ -10,7 +10,7 @@ class EditInlineReplyMarkup: async def edit_inline_reply_markup( self: pyrogram.Client, inline_message_id: str, - reply_markup: types.InlineKeyboardMarkup = None, + reply_markup: types.InlineKeyboardMarkup | None = None, ) -> bool: """Edit only the reply markup of inline messages sent via the bot (for inline bots). diff --git a/pyrogram/methods/messages/edit_inline_text.py b/pyrogram/methods/messages/edit_inline_text.py index afb5480c..6d3a910b 100644 --- a/pyrogram/methods/messages/edit_inline_text.py +++ b/pyrogram/methods/messages/edit_inline_text.py @@ -13,7 +13,7 @@ async def edit_inline_text( text: str, parse_mode: enums.ParseMode | None = None, disable_web_page_preview: bool | None = None, - reply_markup: types.InlineKeyboardMarkup = None, + reply_markup: types.InlineKeyboardMarkup | None = None, invert_media: bool | None = None, ) -> bool: """Edit the text of inline messages. diff --git a/pyrogram/methods/messages/edit_message_caption.py b/pyrogram/methods/messages/edit_message_caption.py index 82880392..31a03450 100644 --- a/pyrogram/methods/messages/edit_message_caption.py +++ b/pyrogram/methods/messages/edit_message_caption.py @@ -16,7 +16,7 @@ async def edit_message_caption( parse_mode: enums.ParseMode | None = None, caption_entities: list[types.MessageEntity] | None = None, invert_media: bool = False, - reply_markup: types.InlineKeyboardMarkup = None, + reply_markup: types.InlineKeyboardMarkup | None = None, business_connection_id: str | None = None, ) -> types.Message: """Edit the caption of media messages. diff --git a/pyrogram/methods/messages/edit_message_media.py b/pyrogram/methods/messages/edit_message_media.py index 1f49ae77..3cf94bca 100644 --- a/pyrogram/methods/messages/edit_message_media.py +++ b/pyrogram/methods/messages/edit_message_media.py @@ -3,6 +3,7 @@ import io import re from pathlib import Path +from typing import Any, cast from anyio import Path as AsyncPath @@ -17,12 +18,12 @@ async def edit_message_media( chat_id: int | str, message_id: int, media: types.InputMedia, - reply_markup: types.InlineKeyboardMarkup = None, + reply_markup: types.InlineKeyboardMarkup | None = None, file_name: str | None = None, parse_mode: enums.ParseMode | None = None, business_connection_id: str | None = None, invert_media: bool = False, - ) -> types.Message: + ) -> types.Message | None: """Edit animation, audio, document, photo or video messages, or replace text with animation, 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, the @@ -79,17 +80,22 @@ async def edit_message_media( """ caption = media.caption caption_entities = media.caption_entities - message, entities = None, None + message: str | None = None + entities: list[raw.base.MessageEntity] | None = None if caption is not None: - message, entities = ( - await utils.parse_text_entities( - self, - caption, - parse_mode, - caption_entities, - ) - ).values() + parsed = await utils.parse_text_entities( + self, + caption, + parse_mode, + caption_entities, + ) + message = cast("Any", parsed["message"]) + entities = cast("Any", parsed["entities"]) + + raw_media: raw.base.InputMedia | None = None + + peer = cast("raw.base.InputPeer", await self.resolve_peer(chat_id)) if isinstance(media, types.InputMediaPhoto): if isinstance(media.media, io.BytesIO) or ( @@ -98,7 +104,7 @@ async def edit_message_media( ): uploaded_media = await self.invoke( raw.functions.messages.UploadMedia( - peer=await self.resolve_peer(chat_id), + peer=peer, media=raw.types.InputMediaUploadedPhoto( file=await self.save_file(media.media), spoiler=media.has_spoiler, @@ -106,7 +112,7 @@ async def edit_message_media( ), ) - media = raw.types.InputMediaPhoto( + raw_media = raw.types.InputMediaPhoto( id=raw.types.InputPhoto( id=uploaded_media.photo.id, access_hash=uploaded_media.photo.access_hash, @@ -114,13 +120,15 @@ async def edit_message_media( ), spoiler=media.has_spoiler, ) - elif re.match("^https?://", media.media): - media = raw.types.InputMediaPhotoExternal( + elif isinstance(media.media, str) and re.match( + "^https?://", media.media + ): + raw_media = raw.types.InputMediaPhotoExternal( url=media.media, spoiler=media.has_spoiler, ) - else: - media = utils.get_input_media_from_file_id( + elif isinstance(media.media, str): + raw_media = utils.get_input_media_from_file_id( media.media, FileType.PHOTO, ) @@ -131,11 +139,20 @@ async def edit_message_media( ): uploaded_media = await self.invoke( raw.functions.messages.UploadMedia( - peer=await self.resolve_peer(chat_id), + peer=peer, media=raw.types.InputMediaUploadedDocument( - mime_type=self.guess_mime_type(media.media) + mime_type=( + self.guess_mime_type(media.media) + if isinstance(media.media, str) + else None + ) or "video/mp4", - thumb=await self.save_file(media.thumb), + thumb=cast( + "raw.base.InputFile", + await self.save_file(media.thumb), + ) + if media.thumb + else None, spoiler=media.has_spoiler, file=await self.save_file(media.media), attributes=[ @@ -147,14 +164,19 @@ async def edit_message_media( h=media.height, ), raw.types.DocumentAttributeFilename( - file_name=file_name or Path(media.media).name, + file_name=file_name + or ( + Path(media.media).name + if isinstance(media.media, str) + else "video.mp4" + ), ), ], ), ), ) - media = raw.types.InputMediaDocument( + raw_media = raw.types.InputMediaDocument( id=raw.types.InputDocument( id=uploaded_media.document.id, access_hash=uploaded_media.document.access_hash, @@ -162,13 +184,15 @@ async def edit_message_media( ), spoiler=media.has_spoiler, ) - elif re.match("^https?://", media.media): - media = raw.types.InputMediaDocumentExternal( + elif isinstance(media.media, str) and re.match( + "^https?://", media.media + ): + raw_media = raw.types.InputMediaDocumentExternal( url=media.media, spoiler=media.has_spoiler, ) - else: - media = utils.get_input_media_from_file_id( + elif isinstance(media.media, str): + raw_media = utils.get_input_media_from_file_id( media.media, FileType.VIDEO, ) @@ -177,13 +201,22 @@ async def edit_message_media( isinstance(media.media, str) and await AsyncPath(media.media).is_file() ): - media = await self.invoke( + uploaded_media = await self.invoke( raw.functions.messages.UploadMedia( - peer=await self.resolve_peer(chat_id), + peer=peer, media=raw.types.InputMediaUploadedDocument( - mime_type=self.guess_mime_type(media.media) + mime_type=( + self.guess_mime_type(media.media) + if isinstance(media.media, str) + else None + ) or "audio/mpeg", - thumb=await self.save_file(media.thumb), + thumb=cast( + "raw.base.InputFile", + await self.save_file(media.thumb), + ) + if media.thumb + else None, file=await self.save_file(media.media), attributes=[ raw.types.DocumentAttributeAudio( @@ -192,24 +225,31 @@ async def edit_message_media( title=media.title, ), raw.types.DocumentAttributeFilename( - file_name=file_name or Path(media.media).name, + file_name=file_name + or ( + Path(media.media).name + if isinstance(media.media, str) + else "audio.mp3" + ), ), ], ), ), ) - media = raw.types.InputMediaDocument( + raw_media = raw.types.InputMediaDocument( id=raw.types.InputDocument( - id=media.document.id, - access_hash=media.document.access_hash, - file_reference=media.document.file_reference, + id=uploaded_media.document.id, + access_hash=uploaded_media.document.access_hash, + file_reference=uploaded_media.document.file_reference, ), ) - elif re.match("^https?://", media.media): - media = raw.types.InputMediaDocumentExternal(url=media.media) - else: - media = utils.get_input_media_from_file_id( + elif isinstance(media.media, str) and re.match( + "^https?://", media.media + ): + raw_media = raw.types.InputMediaDocumentExternal(url=media.media) + elif isinstance(media.media, str): + raw_media = utils.get_input_media_from_file_id( media.media, FileType.AUDIO, ) @@ -220,11 +260,20 @@ async def edit_message_media( ): uploaded_media = await self.invoke( raw.functions.messages.UploadMedia( - peer=await self.resolve_peer(chat_id), + peer=peer, media=raw.types.InputMediaUploadedDocument( - mime_type=self.guess_mime_type(media.media) + mime_type=( + self.guess_mime_type(media.media) + if isinstance(media.media, str) + else None + ) or "video/mp4", - thumb=await self.save_file(media.thumb), + thumb=cast( + "raw.base.InputFile", + await self.save_file(media.thumb), + ) + if media.thumb + else None, spoiler=media.has_spoiler, file=await self.save_file(media.media), attributes=[ @@ -235,7 +284,12 @@ async def edit_message_media( h=media.height, ), raw.types.DocumentAttributeFilename( - file_name=file_name or Path(media.media).name, + file_name=file_name + or ( + Path(media.media).name + if isinstance(media.media, str) + else "animation.mp4" + ), ), raw.types.DocumentAttributeAnimated(), ], @@ -243,7 +297,7 @@ async def edit_message_media( ), ) - media = raw.types.InputMediaDocument( + raw_media = raw.types.InputMediaDocument( id=raw.types.InputDocument( id=uploaded_media.document.id, access_hash=uploaded_media.document.access_hash, @@ -251,13 +305,15 @@ async def edit_message_media( ), spoiler=media.has_spoiler, ) - elif re.match("^https?://", media.media): - media = raw.types.InputMediaDocumentExternal( + elif isinstance(media.media, str) and re.match( + "^https?://", media.media + ): + raw_media = raw.types.InputMediaDocumentExternal( url=media.media, spoiler=media.has_spoiler, ) - else: - media = utils.get_input_media_from_file_id( + elif isinstance(media.media, str): + raw_media = utils.get_input_media_from_file_id( media.media, FileType.ANIMATION, ) @@ -266,42 +322,62 @@ async def edit_message_media( isinstance(media.media, str) and await AsyncPath(media.media).is_file() ): - media = await self.invoke( + uploaded_media = await self.invoke( raw.functions.messages.UploadMedia( - peer=await self.resolve_peer(chat_id), + peer=peer, media=raw.types.InputMediaUploadedDocument( - mime_type=self.guess_mime_type(media.media) + mime_type=( + self.guess_mime_type(media.media) + if isinstance(media.media, str) + else None + ) or "application/zip", - thumb=await self.save_file(media.thumb), + thumb=cast( + "raw.base.InputFile", + await self.save_file(media.thumb), + ) + if media.thumb + else None, file=await self.save_file(media.media), attributes=[ raw.types.DocumentAttributeFilename( - file_name=file_name or Path(media.media).name, + file_name=file_name + or ( + Path(media.media).name + if isinstance(media.media, str) + else "document.zip" + ), ), ], ), ), ) - media = raw.types.InputMediaDocument( + raw_media = raw.types.InputMediaDocument( id=raw.types.InputDocument( - id=media.document.id, - access_hash=media.document.access_hash, - file_reference=media.document.file_reference, + id=uploaded_media.document.id, + access_hash=uploaded_media.document.access_hash, + file_reference=uploaded_media.document.file_reference, ), ) - elif re.match("^https?://", media.media): - media = raw.types.InputMediaDocumentExternal(url=media.media) - else: - media = utils.get_input_media_from_file_id( + elif isinstance(media.media, str) and re.match( + "^https?://", media.media + ): + raw_media = raw.types.InputMediaDocumentExternal(url=media.media) + elif isinstance(media.media, str): + raw_media = utils.get_input_media_from_file_id( media.media, FileType.DOCUMENT, ) + if not isinstance(peer, raw.base.InputPeer): + # Fallback to satisfy type checker, peer should always be InputPeer here + return None + rpc = raw.functions.messages.EditMessage( - peer=await self.resolve_peer(chat_id), + peer=peer, id=message_id, - media=media, + media=raw_media, reply_markup=await reply_markup.write(self) if reply_markup else None, message=message, entities=entities, diff --git a/pyrogram/methods/messages/edit_message_reply_markup.py b/pyrogram/methods/messages/edit_message_reply_markup.py index 40be9259..b8a065d2 100644 --- a/pyrogram/methods/messages/edit_message_reply_markup.py +++ b/pyrogram/methods/messages/edit_message_reply_markup.py @@ -9,7 +9,7 @@ async def edit_message_reply_markup( self: pyrogram.Client, chat_id: int | str, message_id: int, - reply_markup: types.InlineKeyboardMarkup = None, + reply_markup: types.InlineKeyboardMarkup | None = None, business_connection_id: str | None = None, ) -> types.Message: """Edit only the reply markup of messages sent by the bot. diff --git a/pyrogram/methods/messages/edit_message_text.py b/pyrogram/methods/messages/edit_message_text.py index 24d8f2f8..d6fe9ac7 100644 --- a/pyrogram/methods/messages/edit_message_text.py +++ b/pyrogram/methods/messages/edit_message_text.py @@ -14,7 +14,7 @@ async def edit_message_text( entities: list[types.MessageEntity] | None = None, disable_web_page_preview: bool | None = None, invert_media: bool | None = None, - reply_markup: types.InlineKeyboardMarkup = None, + reply_markup: types.InlineKeyboardMarkup | None = None, business_connection_id: str | None = None, ) -> types.Message: """Edit the text of messages. diff --git a/pyrogram/methods/messages/send_animation.py b/pyrogram/methods/messages/send_animation.py index b4956ef9..48e15dbe 100644 --- a/pyrogram/methods/messages/send_animation.py +++ b/pyrogram/methods/messages/send_animation.py @@ -53,6 +53,7 @@ async def send_animation( update_stickersets_order: bool | None = None, suggested_post: types.SuggestedPost | None = None, reply_markup: types.InlineKeyboardMarkup + | None | types.ReplyKeyboardMarkup | types.ReplyKeyboardRemove | types.ForceReply = None, diff --git a/pyrogram/methods/messages/send_audio.py b/pyrogram/methods/messages/send_audio.py index 16cb7c2e..51358521 100644 --- a/pyrogram/methods/messages/send_audio.py +++ b/pyrogram/methods/messages/send_audio.py @@ -42,6 +42,7 @@ async def send_audio( protect_content: bool | None = None, allow_paid_broadcast: bool | None = None, reply_markup: types.InlineKeyboardMarkup + | None | types.ReplyKeyboardMarkup | types.ReplyKeyboardRemove | types.ForceReply = None, diff --git a/pyrogram/methods/messages/send_cached_media.py b/pyrogram/methods/messages/send_cached_media.py index 13a071a4..60ba998b 100644 --- a/pyrogram/methods/messages/send_cached_media.py +++ b/pyrogram/methods/messages/send_cached_media.py @@ -30,6 +30,7 @@ async def send_cached_media( allow_paid_broadcast: bool | None = None, invert_media: bool = False, reply_markup: types.InlineKeyboardMarkup + | None | types.ReplyKeyboardMarkup | types.ReplyKeyboardRemove | types.ForceReply = None, diff --git a/pyrogram/methods/messages/send_chat_action.py b/pyrogram/methods/messages/send_chat_action.py index ceb7ebad..3e39ab0d 100644 --- a/pyrogram/methods/messages/send_chat_action.py +++ b/pyrogram/methods/messages/send_chat_action.py @@ -16,7 +16,7 @@ async def send_chat_action( business_connection_id: str | None = None, emoji: str | None = None, emoji_message_id: int | None = None, - emoji_message_interaction: raw.types.DataJSON = None, + emoji_message_interaction: raw.types.DataJSON | None = None, ) -> bool: """Tell the other party that something is happening on your side. diff --git a/pyrogram/methods/messages/send_contact.py b/pyrogram/methods/messages/send_contact.py index 8c71f143..0e397eab 100644 --- a/pyrogram/methods/messages/send_contact.py +++ b/pyrogram/methods/messages/send_contact.py @@ -30,6 +30,7 @@ async def send_contact( allow_paid_broadcast: bool | None = None, message_effect_id: int | None = None, reply_markup: types.InlineKeyboardMarkup + | None | types.ReplyKeyboardMarkup | types.ReplyKeyboardRemove | types.ForceReply = None, diff --git a/pyrogram/methods/messages/send_dice.py b/pyrogram/methods/messages/send_dice.py index 75297f08..0958631a 100644 --- a/pyrogram/methods/messages/send_dice.py +++ b/pyrogram/methods/messages/send_dice.py @@ -28,6 +28,7 @@ async def send_dice( allow_paid_broadcast: bool | None = None, message_effect_id: int | None = None, reply_markup: types.InlineKeyboardMarkup + | None | types.ReplyKeyboardMarkup | types.ReplyKeyboardRemove | types.ForceReply = None, diff --git a/pyrogram/methods/messages/send_document.py b/pyrogram/methods/messages/send_document.py index a9f7de44..54e25941 100644 --- a/pyrogram/methods/messages/send_document.py +++ b/pyrogram/methods/messages/send_document.py @@ -40,6 +40,7 @@ async def send_document( protect_content: bool | None = None, allow_paid_broadcast: bool | None = None, reply_markup: types.InlineKeyboardMarkup + | None | types.ReplyKeyboardMarkup | types.ReplyKeyboardRemove | types.ForceReply = None, diff --git a/pyrogram/methods/messages/send_location.py b/pyrogram/methods/messages/send_location.py index 0626d6fe..b218a119 100644 --- a/pyrogram/methods/messages/send_location.py +++ b/pyrogram/methods/messages/send_location.py @@ -30,6 +30,7 @@ async def send_location( allow_paid_broadcast: bool | None = None, message_effect_id: int | None = None, reply_markup: types.InlineKeyboardMarkup + | None | types.ReplyKeyboardMarkup | types.ReplyKeyboardRemove | types.ForceReply = None, diff --git a/pyrogram/methods/messages/send_message.py b/pyrogram/methods/messages/send_message.py index a96880a7..d4f0ae43 100644 --- a/pyrogram/methods/messages/send_message.py +++ b/pyrogram/methods/messages/send_message.py @@ -39,6 +39,7 @@ async def send_message( update_stickersets_order: bool | None = None, suggested_post: types.SuggestedPost | None = None, reply_markup: types.InlineKeyboardMarkup + | None | types.ReplyKeyboardMarkup | types.ReplyKeyboardRemove | types.ForceReply = None, diff --git a/pyrogram/methods/messages/send_photo.py b/pyrogram/methods/messages/send_photo.py index ec6aac47..fff22d36 100644 --- a/pyrogram/methods/messages/send_photo.py +++ b/pyrogram/methods/messages/send_photo.py @@ -48,6 +48,7 @@ async def send_photo( update_stickersets_order: bool | None = None, suggested_post: types.SuggestedPost | None = None, reply_markup: types.InlineKeyboardMarkup + | None | types.ReplyKeyboardMarkup | types.ReplyKeyboardRemove | types.ForceReply = None, diff --git a/pyrogram/methods/messages/send_poll.py b/pyrogram/methods/messages/send_poll.py index 6624471f..ca47c540 100644 --- a/pyrogram/methods/messages/send_poll.py +++ b/pyrogram/methods/messages/send_poll.py @@ -21,7 +21,7 @@ async def send_poll( allows_multiple_answers: bool | None = None, correct_option_id: int | None = None, explanation: str | None = None, - explanation_parse_mode: enums.ParseMode = None, + explanation_parse_mode: enums.ParseMode | None = None, explanation_entities: list[types.MessageEntity] | None = None, open_period: int | None = None, close_date: datetime | None = None, @@ -39,6 +39,7 @@ async def send_poll( schedule_date: datetime | None = None, message_effect_id: int | None = None, reply_markup: types.InlineKeyboardMarkup + | None | types.ReplyKeyboardMarkup | types.ReplyKeyboardRemove | types.ForceReply = None, diff --git a/pyrogram/methods/messages/send_sticker.py b/pyrogram/methods/messages/send_sticker.py index f98e357c..2fab4734 100644 --- a/pyrogram/methods/messages/send_sticker.py +++ b/pyrogram/methods/messages/send_sticker.py @@ -36,6 +36,7 @@ async def send_sticker( allow_paid_broadcast: bool | None = None, message_effect_id: int | None = None, reply_markup: types.InlineKeyboardMarkup + | None | types.ReplyKeyboardMarkup | types.ReplyKeyboardRemove | types.ForceReply = None, diff --git a/pyrogram/methods/messages/send_venue.py b/pyrogram/methods/messages/send_venue.py index ebce7477..415cd07b 100644 --- a/pyrogram/methods/messages/send_venue.py +++ b/pyrogram/methods/messages/send_venue.py @@ -32,6 +32,7 @@ async def send_venue( allow_paid_broadcast: bool | None = None, message_effect_id: int | None = None, reply_markup: types.InlineKeyboardMarkup + | None | types.ReplyKeyboardMarkup | types.ReplyKeyboardRemove | types.ForceReply = None, diff --git a/pyrogram/methods/messages/send_video.py b/pyrogram/methods/messages/send_video.py index 2a61e410..432b7dcc 100644 --- a/pyrogram/methods/messages/send_video.py +++ b/pyrogram/methods/messages/send_video.py @@ -54,6 +54,7 @@ async def send_video( update_stickersets_order: bool | None = None, suggested_post: types.SuggestedPost | None = None, reply_markup: types.InlineKeyboardMarkup + | None | types.ReplyKeyboardMarkup | types.ReplyKeyboardRemove | types.ForceReply = None, diff --git a/pyrogram/methods/messages/send_video_note.py b/pyrogram/methods/messages/send_video_note.py index 72fb1ab0..65755811 100644 --- a/pyrogram/methods/messages/send_video_note.py +++ b/pyrogram/methods/messages/send_video_note.py @@ -37,6 +37,7 @@ async def send_video_note( ttl_seconds: int | None = None, message_effect_id: int | None = None, reply_markup: types.InlineKeyboardMarkup + | None | types.ReplyKeyboardMarkup | types.ReplyKeyboardRemove | types.ForceReply = None, diff --git a/pyrogram/methods/messages/send_voice.py b/pyrogram/methods/messages/send_voice.py index 4e262b84..19eaa4e1 100644 --- a/pyrogram/methods/messages/send_voice.py +++ b/pyrogram/methods/messages/send_voice.py @@ -37,6 +37,7 @@ async def send_voice( allow_paid_broadcast: bool | None = None, message_effect_id: int | None = None, reply_markup: types.InlineKeyboardMarkup + | None | types.ReplyKeyboardMarkup | types.ReplyKeyboardRemove | types.ForceReply = None, diff --git a/pyrogram/methods/messages/send_web_page.py b/pyrogram/methods/messages/send_web_page.py index 10223d27..8371a997 100644 --- a/pyrogram/methods/messages/send_web_page.py +++ b/pyrogram/methods/messages/send_web_page.py @@ -32,6 +32,7 @@ async def send_web_page( allow_paid_broadcast: bool | None = None, message_effect_id: int | None = None, reply_markup: types.InlineKeyboardMarkup + | None | types.ReplyKeyboardMarkup | types.ReplyKeyboardRemove | types.ForceReply = None, diff --git a/pyrogram/methods/messages/stop_poll.py b/pyrogram/methods/messages/stop_poll.py index 70d8e26a..0a00e77d 100644 --- a/pyrogram/methods/messages/stop_poll.py +++ b/pyrogram/methods/messages/stop_poll.py @@ -9,7 +9,7 @@ async def stop_poll( self: pyrogram.Client, chat_id: int | str, message_id: int, - reply_markup: types.InlineKeyboardMarkup = None, + reply_markup: types.InlineKeyboardMarkup | None = None, business_connection_id: str | None = None, ) -> types.Poll: """Stop a poll which was sent by you. diff --git a/pyrogram/methods/stories/edit_story.py b/pyrogram/methods/stories/edit_story.py index a5a5d47f..50c1eaa5 100644 --- a/pyrogram/methods/stories/edit_story.py +++ b/pyrogram/methods/stories/edit_story.py @@ -18,7 +18,7 @@ async def edit_story( self: pyrogram.Client, story_id: int, chat_id: int | None = None, - privacy: enums.StoriesPrivacyRules = None, + privacy: enums.StoriesPrivacyRules | None = None, allowed_users: list[int] | None = None, denied_users: list[int] | None = None, # allowed_chats: list[int] = None, @@ -27,7 +27,7 @@ async def edit_story( photo: str | None = None, video: str | None = None, caption: str | None = None, - parse_mode: enums.ParseMode = None, + parse_mode: enums.ParseMode | None = None, caption_entities: list[types.MessageEntity] | None = None, media_areas: list[types.InputMediaArea] | None = None, ) -> types.Story: diff --git a/pyrogram/methods/stories/forward_story.py b/pyrogram/methods/stories/forward_story.py index d664af32..c52f37b6 100644 --- a/pyrogram/methods/stories/forward_story.py +++ b/pyrogram/methods/stories/forward_story.py @@ -17,7 +17,7 @@ async def forward_story( from_chat_id: int | str, from_story_id: int, chat_id: int | str | None = None, - privacy: enums.StoriesPrivacyRules = None, + privacy: enums.StoriesPrivacyRules | None = None, allowed_users: list[int] | None = None, denied_users: list[int] | None = None, # allowed_chats: list[int] = None, @@ -25,7 +25,7 @@ async def forward_story( pinned: bool | None = None, protect_content: bool | None = None, caption: str | None = None, - parse_mode: enums.ParseMode = None, + parse_mode: enums.ParseMode | None = None, caption_entities: list[types.MessageEntity] | None = None, period: int | None = None, ) -> types.Story: diff --git a/pyrogram/methods/stories/send_story.py b/pyrogram/methods/stories/send_story.py index 7d619326..7c7869c4 100644 --- a/pyrogram/methods/stories/send_story.py +++ b/pyrogram/methods/stories/send_story.py @@ -37,7 +37,7 @@ async def _upload_video( async def send_story( self: pyrogram.Client, chat_id: int | str | None = None, - privacy: enums.StoriesPrivacyRules = None, + privacy: enums.StoriesPrivacyRules | None = None, allowed_users: list[int] | None = None, denied_users: list[int] | None = None, # allowed_chats: list[int] = None, @@ -48,7 +48,7 @@ async def send_story( pinned: bool | None = None, protect_content: bool | None = None, caption: str | None = None, - parse_mode: enums.ParseMode = None, + parse_mode: enums.ParseMode | None = None, caption_entities: list[types.MessageEntity] | None = None, period: int | None = None, forward_from_chat_id: int | str | None = None, diff --git a/pyrogram/methods/utilities/__init__.py b/pyrogram/methods/utilities/__init__.py index 6ec41bb2..d425a018 100644 --- a/pyrogram/methods/utilities/__init__.py +++ b/pyrogram/methods/utilities/__init__.py @@ -2,6 +2,7 @@ from .add_handler import AddHandler from .export_session_string import ExportSessionString +from .listening import Listening from .remove_handler import RemoveHandler from .restart import Restart from .run import Run @@ -14,6 +15,7 @@ class Utilities( AddHandler, ExportSessionString, RemoveHandler, + Listening, Restart, Run, Start, diff --git a/pyrogram/methods/utilities/listening.py b/pyrogram/methods/utilities/listening.py new file mode 100644 index 00000000..120984e5 --- /dev/null +++ b/pyrogram/methods/utilities/listening.py @@ -0,0 +1,53 @@ +from __future__ import annotations + +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + import pyrogram + from pyrogram import filters + + +class Listening: + async def listen( + self: pyrogram.Client, + chat_id: int | str, + filters: filters.Filter | None = None, + timeout: int | None = None, + *args, + **kwargs, + ): + """Wait for a new message in a chat.""" + return await self.wait_for_message(chat_id, filters, timeout) + + async def wait_for_message( + self: pyrogram.Client, + chat_id: int | str, + filters: filters.Filter | None = None, + timeout: int | None = None, + ): + """Wait for a new message in a chat.""" + # This is a stub to satisfy type checker and provide missing functionality + # In a real implementation, this would interact with self.dispatcher + raise NotImplementedError("Listening is not implemented in this fork yet.") + + async def ask( + self: pyrogram.Client, + chat_id: int | str, + text: str, + filters: filters.Filter | None = None, + timeout: int | None = None, + *args, + **kwargs, + ): + """Send a message and wait for a reply.""" + await self.send_message(chat_id, text, *args, **kwargs) + return await self.listen(chat_id, filters, timeout) + + async def stop_listening( + self: pyrogram.Client, + chat_id: int | str, + *args, + **kwargs, + ): + """Stop listening for messages in a chat.""" + raise NotImplementedError("Listening is not implemented in this fork yet.") diff --git a/pyrogram/parser/parser.py b/pyrogram/parser/parser.py index 2ca0bbc2..0ed5bdc5 100644 --- a/pyrogram/parser/parser.py +++ b/pyrogram/parser/parser.py @@ -13,7 +13,11 @@ def __init__(self, client: pyrogram.Client | None) -> None: self.html = HTML(client) self.markdown = Markdown(client) - async def parse(self, text: str, mode: enums.ParseMode | None = None): + async def parse( + self, + text: str, + mode: enums.ParseMode | None = None, + ) -> dict[str, str | list[pyrogram.raw.base.MessageEntity] | None]: text = str(text or "").strip() if mode is None: diff --git a/pyrogram/raw/core/tl_object.py b/pyrogram/raw/core/tl_object.py index 4f28fc3d..bb88849b 100644 --- a/pyrogram/raw/core/tl_object.py +++ b/pyrogram/raw/core/tl_object.py @@ -14,8 +14,8 @@ class TLObject: QUALNAME = "Base" - @classmethod - def read(cls, b: BytesIO, *args: Any) -> Any: + @staticmethod + def read(b: BytesIO, *args: Any) -> Any: return cast("TLObject", objects[int.from_bytes(b.read(4), "little")]).read( b, *args, diff --git a/pyrogram/storage/sqlite_storage.py b/pyrogram/storage/sqlite_storage.py index 0eb46f36..1928807e 100644 --- a/pyrogram/storage/sqlite_storage.py +++ b/pyrogram/storage/sqlite_storage.py @@ -153,7 +153,7 @@ async def update_usernames(self, usernames: list[tuple[int, str]]) -> None: usernames, ) - async def update_state(self, value: tuple[int, int, int, int, int] = object): + async def update_state(self, value: Any = object): if value is object: return await ( await self.conn.execute( @@ -247,28 +247,28 @@ async def _set(self, value: Any) -> None: async def _accessor(self, value: Any = object): return await self._get() if value is object else await self._set(value) - async def dc_id(self, value: int = object): + async def dc_id(self, value: Any = object): return await self._accessor(value) - async def api_id(self, value: int = object): + async def api_id(self, value: Any = object): return await self._accessor(value) - async def test_mode(self, value: bool = object): + async def test_mode(self, value: Any = object): return await self._accessor(value) - async def auth_key(self, value: bytes = object): + async def auth_key(self, value: Any = object): return await self._accessor(value) - async def date(self, value: int = object): + async def date(self, value: Any = object): return await self._accessor(value) - async def user_id(self, value: int = object): + async def user_id(self, value: Any = object): return await self._accessor(value) - async def is_bot(self, value: bool = object): + async def is_bot(self, value: Any = object): return await self._accessor(value) - async def version(self, value: int = object): + async def version(self, value: Any = object): if value is object: q = await self.conn.execute("SELECT number FROM version") row = await q.fetchone() diff --git a/pyrogram/storage/storage.py b/pyrogram/storage/storage.py index 2957c9ff..68ff40f8 100644 --- a/pyrogram/storage/storage.py +++ b/pyrogram/storage/storage.py @@ -3,7 +3,7 @@ import base64 import struct from abc import ABC, abstractmethod -from typing import NoReturn +from typing import Any, NoReturn class Storage(ABC): @@ -41,54 +41,61 @@ async def delete(self) -> NoReturn: async def update_peers( self, peers: list[tuple[int, int, str, list[str], str]], - ) -> NoReturn: + ) -> Any: + raise NotImplementedError + + @abstractmethod + async def update_usernames( + self, + usernames: list[tuple[int, str]], + ) -> Any: raise NotImplementedError @abstractmethod async def update_state( self, - update_state: tuple[int, int, int, int, int] = object, - ) -> NoReturn: + update_state: Any = object, + ) -> Any: raise NotImplementedError @abstractmethod - async def get_peer_by_id(self, peer_id: int) -> NoReturn: + async def get_peer_by_id(self, peer_id: int | str) -> Any: raise NotImplementedError @abstractmethod - async def get_peer_by_username(self, username: str) -> NoReturn: + async def get_peer_by_username(self, username: str) -> Any: raise NotImplementedError @abstractmethod - async def get_peer_by_phone_number(self, phone_number: str) -> NoReturn: + async def get_peer_by_phone_number(self, phone_number: str) -> Any: raise NotImplementedError @abstractmethod - async def dc_id(self, value: int = object) -> NoReturn: + async def dc_id(self, value: Any = object) -> Any: raise NotImplementedError @abstractmethod - async def api_id(self, value: int = object) -> NoReturn: + async def api_id(self, value: Any = object) -> Any: raise NotImplementedError @abstractmethod - async def test_mode(self, value: bool = object) -> NoReturn: + async def test_mode(self, value: Any = object) -> Any: raise NotImplementedError @abstractmethod - async def auth_key(self, value: bytes = object) -> NoReturn: + async def auth_key(self, value: Any = object) -> Any: raise NotImplementedError @abstractmethod - async def date(self, value: int = object) -> NoReturn: + async def date(self, value: Any = object) -> Any: raise NotImplementedError @abstractmethod - async def user_id(self, value: int = object) -> NoReturn: + async def user_id(self, value: Any = object) -> Any: raise NotImplementedError @abstractmethod - async def is_bot(self, value: bool = object) -> NoReturn: + async def is_bot(self, value: Any = object) -> Any: raise NotImplementedError async def export_session_string(self): diff --git a/pyrogram/types/__init__.py b/pyrogram/types/__init__.py index 39bbda2f..2c17bf83 100644 --- a/pyrogram/types/__init__.py +++ b/pyrogram/types/__init__.py @@ -140,6 +140,7 @@ GiveawayLaunched, GiveawayResult, LabeledPrice, + LinkPreviewOptions, Location, Message, MessageEntity, @@ -370,6 +371,7 @@ "KeyboardButtonStyle", "LabeledPrice", "Link", + "LinkPreviewOptions", "List", "Location", "LoginUrl", diff --git a/pyrogram/types/authorization/sent_code.py b/pyrogram/types/authorization/sent_code.py index 47d945e5..e966a0c3 100644 --- a/pyrogram/types/authorization/sent_code.py +++ b/pyrogram/types/authorization/sent_code.py @@ -27,7 +27,7 @@ def __init__( *, type: enums.SentCodeType, phone_code_hash: str, - next_type: enums.NextCodeType = None, + next_type: enums.NextCodeType | None = None, timeout: int | None = None, ) -> None: super().__init__() diff --git a/pyrogram/types/bots/bot_business_connection.py b/pyrogram/types/bots/bot_business_connection.py index 0bc26b87..7133bbd8 100644 --- a/pyrogram/types/bots/bot_business_connection.py +++ b/pyrogram/types/bots/bot_business_connection.py @@ -36,7 +36,7 @@ class BotBusinessConnection(Object): def __init__( self, *, - client: pyrogram.Client = None, + client: pyrogram.Client | None = None, bot_connection_id: str, user: pyrogram.types.User, dc_id: int, diff --git a/pyrogram/types/bots_and_keyboards/callback_query.py b/pyrogram/types/bots_and_keyboards/callback_query.py index a90e3a8d..8b566f7c 100644 --- a/pyrogram/types/bots_and_keyboards/callback_query.py +++ b/pyrogram/types/bots_and_keyboards/callback_query.py @@ -51,11 +51,11 @@ class CallbackQuery(Object, Update): def __init__( self, *, - client: pyrogram.Client = None, + client: pyrogram.Client | None = None, id: str, from_user: types.User, chat_instance: str, - message: types.Message = None, + message: types.Message | None = None, inline_message_id: str | None = None, data: str | bytes | None = None, game_short_name: str | None = None, @@ -174,7 +174,7 @@ async def edit_message_text( text: str, parse_mode: enums.ParseMode | None = None, disable_web_page_preview: bool | None = None, - reply_markup: types.InlineKeyboardMarkup = None, + reply_markup: types.InlineKeyboardMarkup | None = None, ) -> types.Message | bool: """Edit the text of messages attached to callback queries. @@ -227,7 +227,7 @@ async def edit_message_caption( self, caption: str, parse_mode: enums.ParseMode | None = None, - reply_markup: types.InlineKeyboardMarkup = None, + reply_markup: types.InlineKeyboardMarkup | None = None, business_connection_id: str | None = None, ) -> types.Message | bool: """Edit the caption of media messages attached to callback queries. @@ -272,7 +272,7 @@ async def edit_message_caption( async def edit_message_media( self, media: types.InputMedia, - reply_markup: types.InlineKeyboardMarkup = None, + reply_markup: types.InlineKeyboardMarkup | None = None, business_connection_id: str | None = None, ) -> types.Message | bool: """Edit animation, audio, document, photo or video messages attached to callback queries. @@ -319,7 +319,7 @@ async def edit_message_media( async def edit_message_reply_markup( self, - reply_markup: types.InlineKeyboardMarkup = None, + reply_markup: types.InlineKeyboardMarkup | None = None, business_connection_id: str | None = None, ) -> types.Message | bool: """Edit only the reply markup of messages attached to callback queries. diff --git a/pyrogram/types/bots_and_keyboards/game_high_score.py b/pyrogram/types/bots_and_keyboards/game_high_score.py index 4d0e62f7..d2049748 100644 --- a/pyrogram/types/bots_and_keyboards/game_high_score.py +++ b/pyrogram/types/bots_and_keyboards/game_high_score.py @@ -22,7 +22,7 @@ class GameHighScore(Object): def __init__( self, *, - client: pyrogram.Client = None, + client: pyrogram.Client | None = None, user: types.User, score: int, position: int | None = None, diff --git a/pyrogram/types/bots_and_keyboards/keyboard_button.py b/pyrogram/types/bots_and_keyboards/keyboard_button.py index b6d36e06..f062636e 100644 --- a/pyrogram/types/bots_and_keyboards/keyboard_button.py +++ b/pyrogram/types/bots_and_keyboards/keyboard_button.py @@ -49,9 +49,9 @@ def __init__( request_location: bool | None = None, request_chat: types.RequestPeerTypeChat | types.RequestPeerTypeChannel = None, - request_user: types.RequestPeerTypeUser = None, - web_app: types.WebAppInfo = None, - style: types.KeyboardButtonStyle | enums.ButtonStyle = None, + request_user: types.RequestPeerTypeUser | None = None, + web_app: types.WebAppInfo | None = None, + style: types.KeyboardButtonStyle | enums.ButtonStyle | None = None, icon: int | None = None, ) -> None: super().__init__() diff --git a/pyrogram/types/bots_and_keyboards/requested_chat.py b/pyrogram/types/bots_and_keyboards/requested_chat.py index 1f12f7e1..d031ad64 100644 --- a/pyrogram/types/bots_and_keyboards/requested_chat.py +++ b/pyrogram/types/bots_and_keyboards/requested_chat.py @@ -30,7 +30,7 @@ def __init__( chat_type: enums.ChatType, name: str | None = None, username: str | None = None, - photo: types.ChatPhoto = None, + photo: types.ChatPhoto | None = None, ) -> None: super().__init__() diff --git a/pyrogram/types/bots_and_keyboards/requested_user.py b/pyrogram/types/bots_and_keyboards/requested_user.py index 65cd0e00..f2b50712 100644 --- a/pyrogram/types/bots_and_keyboards/requested_user.py +++ b/pyrogram/types/bots_and_keyboards/requested_user.py @@ -33,7 +33,7 @@ def __init__( first_name: str | None = None, last_name: str | None = None, username: str | None = None, - photo: types.ChatPhoto = None, + photo: types.ChatPhoto | None = None, ) -> None: super().__init__() diff --git a/pyrogram/types/business/extended_media_preview.py b/pyrogram/types/business/extended_media_preview.py index fb109667..f00af72e 100644 --- a/pyrogram/types/business/extended_media_preview.py +++ b/pyrogram/types/business/extended_media_preview.py @@ -26,7 +26,7 @@ def __init__( *, width: int | None = None, height: int | None = None, - thumb: types.Thumbnail = None, + thumb: types.Thumbnail | None = None, video_duration: int | None = None, ) -> None: super().__init__() diff --git a/pyrogram/types/business/invoice.py b/pyrogram/types/business/invoice.py index 024ebef8..51aa93bf 100644 --- a/pyrogram/types/business/invoice.py +++ b/pyrogram/types/business/invoice.py @@ -74,7 +74,7 @@ class Invoice(Object): def __init__( self, *, - client: pyrogram.Client = None, + client: pyrogram.Client | None = None, currency: str, is_test: bool, title: str | None = None, @@ -93,7 +93,7 @@ def __init__( max_tip_amount: int | None = None, suggested_tip_amounts: list[int] | None = None, terms_url: str | None = None, - raw: raw.types.MessageMediaInvoice | raw.types.Invoice = None, + raw: raw.types.MessageMediaInvoice | raw.types.Invoice | None = None, ) -> None: super().__init__(client) diff --git a/pyrogram/types/business/paid_media_preview.py b/pyrogram/types/business/paid_media_preview.py index f1a63043..30aa50fe 100644 --- a/pyrogram/types/business/paid_media_preview.py +++ b/pyrogram/types/business/paid_media_preview.py @@ -28,7 +28,7 @@ def __init__( width: int | None = None, height: int | None = None, duration: int | None = None, - thumbnail: types.StrippedThumbnail = None, + thumbnail: types.StrippedThumbnail | None = None, ) -> None: super().__init__() diff --git a/pyrogram/types/business/payment_info.py b/pyrogram/types/business/payment_info.py index bb5fc297..f5d46aca 100644 --- a/pyrogram/types/business/payment_info.py +++ b/pyrogram/types/business/payment_info.py @@ -31,7 +31,7 @@ def __init__( name: str | None = None, phone_number: str | None = None, email: str | None = None, - shipping_address: types.ShippingAddress = None, + shipping_address: types.ShippingAddress | None = None, ) -> None: super().__init__() diff --git a/pyrogram/types/business/pre_checkout_query.py b/pyrogram/types/business/pre_checkout_query.py index 19945ddb..d16c1f01 100644 --- a/pyrogram/types/business/pre_checkout_query.py +++ b/pyrogram/types/business/pre_checkout_query.py @@ -35,14 +35,14 @@ class PreCheckoutQuery(Object, Update): def __init__( self, *, - client: pyrogram.Client = None, + client: pyrogram.Client | None = None, id: str, from_user: types.User, currency: str, total_amount: int, payload: str, shipping_option_id: str | None = None, - payment_info: types.PaymentInfo = None, + payment_info: types.PaymentInfo | None = None, ) -> None: super().__init__(client) diff --git a/pyrogram/types/business/shipping_query.py b/pyrogram/types/business/shipping_query.py index 63bb8bcb..3f0580da 100644 --- a/pyrogram/types/business/shipping_query.py +++ b/pyrogram/types/business/shipping_query.py @@ -27,11 +27,11 @@ class ShippingQuery(Object, Update): def __init__( self, *, - client: pyrogram.Client = None, + client: pyrogram.Client | None = None, id: str, from_user: types.User, invoice_payload: str, - shipping_address: types.ShippingAddress = None, + shipping_address: types.ShippingAddress | None = None, ) -> None: super().__init__(client) diff --git a/pyrogram/types/business/successful_payment.py b/pyrogram/types/business/successful_payment.py index 90962bc4..ed22b893 100644 --- a/pyrogram/types/business/successful_payment.py +++ b/pyrogram/types/business/successful_payment.py @@ -40,7 +40,7 @@ def __init__( telegram_payment_charge_id: str, provider_payment_charge_id: str, shipping_option_id: str | None = None, - payment_info: types.PaymentInfo = None, + payment_info: types.PaymentInfo | None = None, ) -> None: super().__init__() diff --git a/pyrogram/types/business/suggested_post.py b/pyrogram/types/business/suggested_post.py index fe8372ac..e29ed14b 100644 --- a/pyrogram/types/business/suggested_post.py +++ b/pyrogram/types/business/suggested_post.py @@ -50,7 +50,9 @@ async def write(self) -> raw.types.SuggestedPost: ) @staticmethod - def _parse(suggested_post: raw.types.SuggestedPost) -> SuggestedPost | None: + def _parse( + suggested_post: raw.types.SuggestedPost | None, + ) -> SuggestedPost | None: if not suggested_post: return None diff --git a/pyrogram/types/inline_mode/chosen_inline_result.py b/pyrogram/types/inline_mode/chosen_inline_result.py index ac08be11..aa1df238 100644 --- a/pyrogram/types/inline_mode/chosen_inline_result.py +++ b/pyrogram/types/inline_mode/chosen_inline_result.py @@ -39,11 +39,11 @@ class ChosenInlineResult(Object, Update): def __init__( self, *, - client: pyrogram.Client = None, + client: pyrogram.Client | None = None, result_id: str, from_user: types.User, query: str, - location: types.Location = None, + location: types.Location | None = None, inline_message_id: str | None = None, ) -> None: super().__init__(client) diff --git a/pyrogram/types/inline_mode/inline_query.py b/pyrogram/types/inline_mode/inline_query.py index 861091e8..58ad5ce4 100644 --- a/pyrogram/types/inline_mode/inline_query.py +++ b/pyrogram/types/inline_mode/inline_query.py @@ -43,13 +43,13 @@ class InlineQuery(Object, Update): def __init__( self, *, - client: pyrogram.Client = None, + client: pyrogram.Client | None = None, id: str, from_user: types.User, query: str, offset: str, chat_type: enums.ChatType, - location: types.Location = None, + location: types.Location | None = None, matches: list[Match] | None = None, ) -> None: super().__init__(client) diff --git a/pyrogram/types/inline_mode/inline_query_result_animation.py b/pyrogram/types/inline_mode/inline_query_result_animation.py index 38f116a3..42445774 100644 --- a/pyrogram/types/inline_mode/inline_query_result_animation.py +++ b/pyrogram/types/inline_mode/inline_query_result_animation.py @@ -73,8 +73,8 @@ def __init__( caption: str = "", parse_mode: enums.ParseMode | None = None, caption_entities: list[types.MessageEntity] | None = None, - reply_markup: types.InlineKeyboardMarkup = None, - input_message_content: types.InputMessageContent = None, + reply_markup: types.InlineKeyboardMarkup | None = None, + input_message_content: types.InputMessageContent | None = None, ) -> None: super().__init__("gif", id, input_message_content, reply_markup) diff --git a/pyrogram/types/inline_mode/inline_query_result_article.py b/pyrogram/types/inline_mode/inline_query_result_article.py index 437cd95f..4ec3b6c5 100644 --- a/pyrogram/types/inline_mode/inline_query_result_article.py +++ b/pyrogram/types/inline_mode/inline_query_result_article.py @@ -46,7 +46,7 @@ def __init__( id: str | None = None, url: str | None = None, description: str | None = None, - reply_markup: types.InlineKeyboardMarkup = None, + reply_markup: types.InlineKeyboardMarkup | None = None, thumb_url: str | None = None, thumb_width: int = 0, thumb_height: int = 0, diff --git a/pyrogram/types/inline_mode/inline_query_result_audio.py b/pyrogram/types/inline_mode/inline_query_result_audio.py index bbff89ab..e9f9e853 100644 --- a/pyrogram/types/inline_mode/inline_query_result_audio.py +++ b/pyrogram/types/inline_mode/inline_query_result_audio.py @@ -64,8 +64,8 @@ def __init__( parse_mode: enums.ParseMode | None = None, caption_entities: list[types.MessageEntity] | None = None, description: str | None = None, - reply_markup: types.InlineKeyboardMarkup = None, - input_message_content: types.InputMessageContent = None, + reply_markup: types.InlineKeyboardMarkup | None = None, + input_message_content: types.InputMessageContent | None = None, thumb_url: str | None = None, ) -> None: super().__init__("audio", id, input_message_content, reply_markup) diff --git a/pyrogram/types/inline_mode/inline_query_result_cached_animation.py b/pyrogram/types/inline_mode/inline_query_result_cached_animation.py index eb5e9d2f..57e4ac75 100644 --- a/pyrogram/types/inline_mode/inline_query_result_cached_animation.py +++ b/pyrogram/types/inline_mode/inline_query_result_cached_animation.py @@ -50,8 +50,8 @@ def __init__( caption: str = "", parse_mode: enums.ParseMode | None = None, caption_entities: list[types.MessageEntity] | None = None, - reply_markup: types.InlineKeyboardMarkup = None, - input_message_content: types.InputMessageContent = None, + reply_markup: types.InlineKeyboardMarkup | None = None, + input_message_content: types.InputMessageContent | None = None, ) -> None: super().__init__("gif", id, input_message_content, reply_markup) diff --git a/pyrogram/types/inline_mode/inline_query_result_cached_audio.py b/pyrogram/types/inline_mode/inline_query_result_cached_audio.py index 9e0118a7..2a7c6053 100644 --- a/pyrogram/types/inline_mode/inline_query_result_cached_audio.py +++ b/pyrogram/types/inline_mode/inline_query_result_cached_audio.py @@ -45,8 +45,8 @@ def __init__( caption: str = "", parse_mode: enums.ParseMode | None = None, caption_entities: list[types.MessageEntity] | None = None, - reply_markup: types.InlineKeyboardMarkup = None, - input_message_content: types.InputMessageContent = None, + reply_markup: types.InlineKeyboardMarkup | None = None, + input_message_content: types.InputMessageContent | None = None, ) -> None: super().__init__("audio", id, input_message_content, reply_markup) diff --git a/pyrogram/types/inline_mode/inline_query_result_cached_document.py b/pyrogram/types/inline_mode/inline_query_result_cached_document.py index 1597d2bd..db407a5d 100644 --- a/pyrogram/types/inline_mode/inline_query_result_cached_document.py +++ b/pyrogram/types/inline_mode/inline_query_result_cached_document.py @@ -53,8 +53,8 @@ def __init__( caption: str = "", parse_mode: enums.ParseMode | None = None, caption_entities: list[types.MessageEntity] | None = None, - reply_markup: types.InlineKeyboardMarkup = None, - input_message_content: types.InputMessageContent = None, + reply_markup: types.InlineKeyboardMarkup | None = None, + input_message_content: types.InputMessageContent | None = None, ) -> None: super().__init__("file", id, input_message_content, reply_markup) diff --git a/pyrogram/types/inline_mode/inline_query_result_cached_photo.py b/pyrogram/types/inline_mode/inline_query_result_cached_photo.py index fe1f77fb..25ec0ca7 100644 --- a/pyrogram/types/inline_mode/inline_query_result_cached_photo.py +++ b/pyrogram/types/inline_mode/inline_query_result_cached_photo.py @@ -53,8 +53,8 @@ def __init__( caption: str = "", parse_mode: enums.ParseMode | None = None, caption_entities: list[types.MessageEntity] | None = None, - reply_markup: types.InlineKeyboardMarkup = None, - input_message_content: types.InputMessageContent = None, + reply_markup: types.InlineKeyboardMarkup | None = None, + input_message_content: types.InputMessageContent | None = None, ) -> None: super().__init__("photo", id, input_message_content, reply_markup) diff --git a/pyrogram/types/inline_mode/inline_query_result_cached_sticker.py b/pyrogram/types/inline_mode/inline_query_result_cached_sticker.py index fda6e14a..9d6170f6 100644 --- a/pyrogram/types/inline_mode/inline_query_result_cached_sticker.py +++ b/pyrogram/types/inline_mode/inline_query_result_cached_sticker.py @@ -32,8 +32,8 @@ def __init__( self, sticker_file_id: str, id: str | None = None, - reply_markup: types.InlineKeyboardMarkup = None, - input_message_content: types.InputMessageContent = None, + reply_markup: types.InlineKeyboardMarkup | None = None, + input_message_content: types.InputMessageContent | None = None, ) -> None: super().__init__("sticker", id, input_message_content, reply_markup) diff --git a/pyrogram/types/inline_mode/inline_query_result_cached_video.py b/pyrogram/types/inline_mode/inline_query_result_cached_video.py index 7c40b9a4..666de583 100644 --- a/pyrogram/types/inline_mode/inline_query_result_cached_video.py +++ b/pyrogram/types/inline_mode/inline_query_result_cached_video.py @@ -54,8 +54,8 @@ def __init__( caption: str = "", parse_mode: enums.ParseMode | None = None, caption_entities: list[types.MessageEntity] | None = None, - reply_markup: types.InlineKeyboardMarkup = None, - input_message_content: types.InputMessageContent = None, + reply_markup: types.InlineKeyboardMarkup | None = None, + input_message_content: types.InputMessageContent | None = None, ) -> None: super().__init__("video", id, input_message_content, reply_markup) diff --git a/pyrogram/types/inline_mode/inline_query_result_cached_voice.py b/pyrogram/types/inline_mode/inline_query_result_cached_voice.py index 26420dd4..7247700b 100644 --- a/pyrogram/types/inline_mode/inline_query_result_cached_voice.py +++ b/pyrogram/types/inline_mode/inline_query_result_cached_voice.py @@ -50,8 +50,8 @@ def __init__( caption: str = "", parse_mode: enums.ParseMode | None = None, caption_entities: list[types.MessageEntity] | None = None, - reply_markup: types.InlineKeyboardMarkup = None, - input_message_content: types.InputMessageContent = None, + reply_markup: types.InlineKeyboardMarkup | None = None, + input_message_content: types.InputMessageContent | None = None, ) -> None: super().__init__("voice", id, input_message_content, reply_markup) diff --git a/pyrogram/types/inline_mode/inline_query_result_contact.py b/pyrogram/types/inline_mode/inline_query_result_contact.py index 7ba67baa..e6ee0ee6 100644 --- a/pyrogram/types/inline_mode/inline_query_result_contact.py +++ b/pyrogram/types/inline_mode/inline_query_result_contact.py @@ -53,8 +53,8 @@ def __init__( last_name: str = "", vcard: str = "", id: str | None = None, - reply_markup: types.InlineKeyboardMarkup = None, - input_message_content: types.InputMessageContent = None, + reply_markup: types.InlineKeyboardMarkup | None = None, + input_message_content: types.InputMessageContent | None = None, thumb_url: str | None = None, thumb_width: int = 0, thumb_height: int = 0, diff --git a/pyrogram/types/inline_mode/inline_query_result_document.py b/pyrogram/types/inline_mode/inline_query_result_document.py index 5fdde2fa..c611e10c 100644 --- a/pyrogram/types/inline_mode/inline_query_result_document.py +++ b/pyrogram/types/inline_mode/inline_query_result_document.py @@ -66,8 +66,8 @@ def __init__( parse_mode: enums.ParseMode | None = None, caption_entities: list[types.MessageEntity] | None = None, description: str = "", - reply_markup: types.InlineKeyboardMarkup = None, - input_message_content: types.InputMessageContent = None, + reply_markup: types.InlineKeyboardMarkup | None = None, + input_message_content: types.InputMessageContent | None = None, thumb_url: str | None = None, thumb_width: int = 0, thumb_height: int = 0, diff --git a/pyrogram/types/inline_mode/inline_query_result_location.py b/pyrogram/types/inline_mode/inline_query_result_location.py index a52ee11b..f3bfdf7b 100644 --- a/pyrogram/types/inline_mode/inline_query_result_location.py +++ b/pyrogram/types/inline_mode/inline_query_result_location.py @@ -66,8 +66,8 @@ def __init__( heading: int | None = None, proximity_alert_radius: int | None = None, id: str | None = None, - reply_markup: types.InlineKeyboardMarkup = None, - input_message_content: types.InputMessageContent = None, + reply_markup: types.InlineKeyboardMarkup | None = None, + input_message_content: types.InputMessageContent | None = None, thumb_url: str | None = None, thumb_width: int = 0, thumb_height: int = 0, diff --git a/pyrogram/types/inline_mode/inline_query_result_photo.py b/pyrogram/types/inline_mode/inline_query_result_photo.py index c2c7cb25..b8950e8b 100644 --- a/pyrogram/types/inline_mode/inline_query_result_photo.py +++ b/pyrogram/types/inline_mode/inline_query_result_photo.py @@ -67,8 +67,8 @@ def __init__( caption: str = "", parse_mode: enums.ParseMode | None = None, caption_entities: list[types.MessageEntity] | None = None, - reply_markup: types.InlineKeyboardMarkup = None, - input_message_content: types.InputMessageContent = None, + reply_markup: types.InlineKeyboardMarkup | None = None, + input_message_content: types.InputMessageContent | None = None, ) -> None: super().__init__("photo", id, input_message_content, reply_markup) diff --git a/pyrogram/types/inline_mode/inline_query_result_venue.py b/pyrogram/types/inline_mode/inline_query_result_venue.py index 9fae040c..6e20d605 100644 --- a/pyrogram/types/inline_mode/inline_query_result_venue.py +++ b/pyrogram/types/inline_mode/inline_query_result_venue.py @@ -68,8 +68,8 @@ def __init__( foursquare_type: str | None = None, google_place_id: str | None = None, google_place_type: str | None = None, - reply_markup: types.InlineKeyboardMarkup = None, - input_message_content: types.InputMessageContent = None, + reply_markup: types.InlineKeyboardMarkup | None = None, + input_message_content: types.InputMessageContent | None = None, thumb_url: str | None = None, thumb_width: int = 0, thumb_height: int = 0, diff --git a/pyrogram/types/inline_mode/inline_query_result_video.py b/pyrogram/types/inline_mode/inline_query_result_video.py index a7ec713a..0ac23cbe 100644 --- a/pyrogram/types/inline_mode/inline_query_result_video.py +++ b/pyrogram/types/inline_mode/inline_query_result_video.py @@ -75,8 +75,8 @@ def __init__( caption: str = "", parse_mode: enums.ParseMode | None = None, caption_entities: list[types.MessageEntity] | None = None, - reply_markup: types.InlineKeyboardMarkup = None, - input_message_content: types.InputMessageContent = None, + reply_markup: types.InlineKeyboardMarkup | None = None, + input_message_content: types.InputMessageContent | None = None, ) -> None: super().__init__("video", id, input_message_content, reply_markup) diff --git a/pyrogram/types/inline_mode/inline_query_result_voice.py b/pyrogram/types/inline_mode/inline_query_result_voice.py index 3475e15f..6fabe831 100644 --- a/pyrogram/types/inline_mode/inline_query_result_voice.py +++ b/pyrogram/types/inline_mode/inline_query_result_voice.py @@ -53,8 +53,8 @@ def __init__( caption: str = "", parse_mode: enums.ParseMode | None = None, caption_entities: list[types.MessageEntity] | None = None, - reply_markup: types.InlineKeyboardMarkup = None, - input_message_content: types.InputMessageContent = None, + reply_markup: types.InlineKeyboardMarkup | None = None, + input_message_content: types.InputMessageContent | None = None, ) -> None: super().__init__("voice", id, input_message_content, reply_markup) diff --git a/pyrogram/types/input_message_content/input_reply_to_message.py b/pyrogram/types/input_message_content/input_reply_to_message.py index 689b9d9a..92fba855 100644 --- a/pyrogram/types/input_message_content/input_reply_to_message.py +++ b/pyrogram/types/input_message_content/input_reply_to_message.py @@ -34,7 +34,7 @@ def __init__( *, reply_to_message_id: int | None = None, message_thread_id: int | None = None, - reply_to_chat: raw.types.InputPeerChannel | raw.types.InputPeerUser = None, + reply_to_chat: raw.base.InputPeer | None = None, quote_text: str | None = None, quote_entities: list[raw.base.MessageEntity] | None = None, ) -> None: diff --git a/pyrogram/types/messages_and_media/__init__.py b/pyrogram/types/messages_and_media/__init__.py index be4b6193..1cfe8c63 100644 --- a/pyrogram/types/messages_and_media/__init__.py +++ b/pyrogram/types/messages_and_media/__init__.py @@ -27,6 +27,7 @@ from .giveaway_launched import GiveawayLaunched from .giveaway_result import GiveawayResult from .labeled_price import LabeledPrice +from .link_preview_options import LinkPreviewOptions from .location import Location from .message import Message, Str from .message_entity import MessageEntity @@ -82,6 +83,7 @@ "GiveawayLaunched", "GiveawayResult", "LabeledPrice", + "LinkPreviewOptions", "Location", "MediaArea", "MediaAreaChannelPost", diff --git a/pyrogram/types/messages_and_media/alternative_video.py b/pyrogram/types/messages_and_media/alternative_video.py index 932d25f4..39e7d0c1 100644 --- a/pyrogram/types/messages_and_media/alternative_video.py +++ b/pyrogram/types/messages_and_media/alternative_video.py @@ -62,7 +62,7 @@ class AlternativeVideo(Object): def __init__( self, *, - client: pyrogram.Client = None, + client: pyrogram.Client | None = None, file_id: str, file_unique_id: str, width: int, diff --git a/pyrogram/types/messages_and_media/animation.py b/pyrogram/types/messages_and_media/animation.py index 7994cf49..17a599c4 100644 --- a/pyrogram/types/messages_and_media/animation.py +++ b/pyrogram/types/messages_and_media/animation.py @@ -56,7 +56,7 @@ class Animation(Object): def __init__( self, *, - client: pyrogram.Client = None, + client: pyrogram.Client | None = None, file_id: str, file_unique_id: str, width: int, diff --git a/pyrogram/types/messages_and_media/audio.py b/pyrogram/types/messages_and_media/audio.py index 12dc4bb6..ff800376 100644 --- a/pyrogram/types/messages_and_media/audio.py +++ b/pyrogram/types/messages_and_media/audio.py @@ -55,7 +55,7 @@ class Audio(Object): def __init__( self, *, - client: pyrogram.Client = None, + client: pyrogram.Client | None = None, file_id: str, file_unique_id: str, duration: int, diff --git a/pyrogram/types/messages_and_media/available_effect.py b/pyrogram/types/messages_and_media/available_effect.py index 8bdc4363..ff30d764 100644 --- a/pyrogram/types/messages_and_media/available_effect.py +++ b/pyrogram/types/messages_and_media/available_effect.py @@ -55,7 +55,7 @@ def __init__( async def _parse( client, effect: raw.types.AvailableEffect, - document: raw.types.Document = None, + document: raw.types.Document | None = None, ) -> AvailableEffect: sticker = None diff --git a/pyrogram/types/messages_and_media/contact.py b/pyrogram/types/messages_and_media/contact.py index c4a26250..d4b1d8a1 100644 --- a/pyrogram/types/messages_and_media/contact.py +++ b/pyrogram/types/messages_and_media/contact.py @@ -32,7 +32,7 @@ class Contact(Object): def __init__( self, *, - client: pyrogram.Client = None, + client: pyrogram.Client | None = None, phone_number: str, first_name: str, last_name: str | None = None, diff --git a/pyrogram/types/messages_and_media/dice.py b/pyrogram/types/messages_and_media/dice.py index 2fbdafcc..7196fee4 100644 --- a/pyrogram/types/messages_and_media/dice.py +++ b/pyrogram/types/messages_and_media/dice.py @@ -23,7 +23,7 @@ class Dice(Object): def __init__( self, *, - client: pyrogram.Client = None, + client: pyrogram.Client | None = None, emoji: str, value: int, ) -> None: diff --git a/pyrogram/types/messages_and_media/document.py b/pyrogram/types/messages_and_media/document.py index 1bb8a300..72f23c41 100644 --- a/pyrogram/types/messages_and_media/document.py +++ b/pyrogram/types/messages_and_media/document.py @@ -46,7 +46,7 @@ class Document(Object): def __init__( self, *, - client: pyrogram.Client = None, + client: pyrogram.Client | None = None, file_id: str, file_unique_id: str, file_name: str | None = None, diff --git a/pyrogram/types/messages_and_media/draft_message.py b/pyrogram/types/messages_and_media/draft_message.py index fca676fb..af096e64 100644 --- a/pyrogram/types/messages_and_media/draft_message.py +++ b/pyrogram/types/messages_and_media/draft_message.py @@ -66,19 +66,19 @@ def __init__( self, *, reply_to_message_id: int | None = None, - reply_to_message: types.Message = None, + reply_to_message: types.Message | None = None, date: datetime | None = None, - text: Str = None, + text: Str | None = None, entities: list[types.MessageEntity] | None = None, link_preview_options: types.LinkPreviewOptions = None, effect_id: str | None = None, - video_note: types.VideoNote = None, - voice: types.Voice = None, + video_note: types.VideoNote | None = None, + voice: types.Voice | None = None, show_caption_above_media: bool | None = None, - media: enums.MessageMediaType = None, + media: enums.MessageMediaType | None = None, empty: bool | None = None, - chat: types.Chat = None, - _raw: raw.types.DraftMessage = None, + chat: types.Chat | None = None, + _raw: raw.types.DraftMessage | None = None, ) -> None: super().__init__() diff --git a/pyrogram/types/messages_and_media/fact_check.py b/pyrogram/types/messages_and_media/fact_check.py index ce00976d..8625e01d 100644 --- a/pyrogram/types/messages_and_media/fact_check.py +++ b/pyrogram/types/messages_and_media/fact_check.py @@ -37,7 +37,7 @@ def __init__( self.hash = hash @staticmethod - def _parse(client, fact_check: raw.types.FactCheck) -> FactCheck | None: + def _parse(client, fact_check: raw.types.FactCheck | None) -> FactCheck | None: if not fact_check: return None diff --git a/pyrogram/types/messages_and_media/game.py b/pyrogram/types/messages_and_media/game.py index bb667e70..0e8e6d0e 100644 --- a/pyrogram/types/messages_and_media/game.py +++ b/pyrogram/types/messages_and_media/game.py @@ -33,13 +33,13 @@ class Game(Object): def __init__( self, *, - client: pyrogram.Client = None, + client: pyrogram.Client | None = None, id: int, title: str, short_name: str, description: str, photo: types.Photo, - animation: types.Animation = None, + animation: types.Animation | None = None, ) -> None: super().__init__(client) diff --git a/pyrogram/types/messages_and_media/giveaway.py b/pyrogram/types/messages_and_media/giveaway.py index 4663ff8e..efab7336 100644 --- a/pyrogram/types/messages_and_media/giveaway.py +++ b/pyrogram/types/messages_and_media/giveaway.py @@ -41,7 +41,7 @@ class Giveaway(Object): def __init__( self, *, - client: pyrogram.Client = None, + client: pyrogram.Client | None = None, chats: list[types.Chat], quantity: int, months: int, diff --git a/pyrogram/types/messages_and_media/giveaway_result.py b/pyrogram/types/messages_and_media/giveaway_result.py index 5154abfa..c690eb4a 100644 --- a/pyrogram/types/messages_and_media/giveaway_result.py +++ b/pyrogram/types/messages_and_media/giveaway_result.py @@ -48,9 +48,9 @@ class GiveawayResult(Object): def __init__( self, *, - client: pyrogram.Client = None, - chat: types.Chat = None, - giveaway_message: types.Message = None, + client: pyrogram.Client | None = None, + chat: types.Chat | None = None, + giveaway_message: types.Message | None = None, quantity: int, unclaimed_quantity: int, winners: list[types.User] | None = None, diff --git a/pyrogram/types/messages_and_media/link_preview_options.py b/pyrogram/types/messages_and_media/link_preview_options.py new file mode 100644 index 00000000..1128df1a --- /dev/null +++ b/pyrogram/types/messages_and_media/link_preview_options.py @@ -0,0 +1,64 @@ +from __future__ import annotations + +from typing import TYPE_CHECKING + +from pyrogram.types.object import Object + +if TYPE_CHECKING: + import pyrogram + from pyrogram import raw + + +class LinkPreviewOptions(Object): + """Link preview options. + + Parameters: + is_disabled (``bool``, *optional*): + True, if the link preview is disabled. + + url (``str``, *optional*): + URL to use for the link preview. + + prefer_small_media (``bool``, *optional*): + True, if the small media is preferred. + + prefer_large_media (``bool``, *optional*): + True, if the large media is preferred. + + show_above_text (``bool``, *optional*): + True, if the link preview should be shown above the message text. + """ + + def __init__( + self, + *, + client: pyrogram.Client | None = None, + is_disabled: bool | None = None, + url: str | None = None, + prefer_small_media: bool | None = None, + prefer_large_media: bool | None = None, + show_above_text: bool | None = None, + ) -> None: + super().__init__(client) + + self.is_disabled = is_disabled + self.url = url + self.prefer_small_media = prefer_small_media + self.prefer_large_media = prefer_large_media + self.show_above_text = show_above_text + + @staticmethod + def _parse( + client: pyrogram.Client, + media: raw.base.MessageMedia | raw.base.InputMedia | None = None, + url: str | None = None, + show_above_text: bool | None = None, + ) -> LinkPreviewOptions: + return LinkPreviewOptions( + client=client, + is_disabled=media is None and url is None, + url=url, + prefer_small_media=getattr(media, "force_small_media", None), + prefer_large_media=getattr(media, "force_large_media", None), + show_above_text=show_above_text, + ) diff --git a/pyrogram/types/messages_and_media/location.py b/pyrogram/types/messages_and_media/location.py index 60f4a424..8789b0f1 100644 --- a/pyrogram/types/messages_and_media/location.py +++ b/pyrogram/types/messages_and_media/location.py @@ -19,7 +19,7 @@ class Location(Object): def __init__( self, *, - client: pyrogram.Client = None, + client: pyrogram.Client | None = None, longitude: float, latitude: float, ) -> None: diff --git a/pyrogram/types/messages_and_media/message_entity.py b/pyrogram/types/messages_and_media/message_entity.py index 16c84510..6ea1db59 100644 --- a/pyrogram/types/messages_and_media/message_entity.py +++ b/pyrogram/types/messages_and_media/message_entity.py @@ -40,12 +40,12 @@ class MessageEntity(Object): def __init__( self, *, - client: pyrogram.Client = None, + client: pyrogram.Client | None = None, type: enums.MessageEntityType, offset: int, length: int, url: str | None = None, - user: types.User = None, + user: types.User | None = None, language: str | None = None, custom_emoji_id: int | None = None, collapsed: bool | None = None, diff --git a/pyrogram/types/messages_and_media/message_reaction_count_updated.py b/pyrogram/types/messages_and_media/message_reaction_count_updated.py index c8761e6e..9c9b8088 100644 --- a/pyrogram/types/messages_and_media/message_reaction_count_updated.py +++ b/pyrogram/types/messages_and_media/message_reaction_count_updated.py @@ -33,7 +33,7 @@ class MessageReactionCountUpdated(Object, Update): def __init__( self, *, - client: pyrogram.Client = None, + client: pyrogram.Client | None = None, chat: types.Chat, message_id: int, date: datetime, diff --git a/pyrogram/types/messages_and_media/message_reaction_updated.py b/pyrogram/types/messages_and_media/message_reaction_updated.py index 9b00f68b..5ee0dffe 100644 --- a/pyrogram/types/messages_and_media/message_reaction_updated.py +++ b/pyrogram/types/messages_and_media/message_reaction_updated.py @@ -45,7 +45,7 @@ class MessageReactionUpdated(Object, Update): def __init__( self, *, - client: pyrogram.Client = None, + client: pyrogram.Client | None = None, id: int, from_user: types.User, actor_chat: types.Chat, diff --git a/pyrogram/types/messages_and_media/message_reactions.py b/pyrogram/types/messages_and_media/message_reactions.py index 8e9ccb8d..b58ee945 100644 --- a/pyrogram/types/messages_and_media/message_reactions.py +++ b/pyrogram/types/messages_and_media/message_reactions.py @@ -19,7 +19,7 @@ class MessageReactions(Object): def __init__( self, *, - client: pyrogram.Client = None, + client: pyrogram.Client | None = None, reactions: list[types.Reaction] | None = None, top_reactors: list[types.MessageReactor] | None = None, ) -> None: diff --git a/pyrogram/types/messages_and_media/message_reactor.py b/pyrogram/types/messages_and_media/message_reactor.py index 7ce9830d..582139dd 100644 --- a/pyrogram/types/messages_and_media/message_reactor.py +++ b/pyrogram/types/messages_and_media/message_reactor.py @@ -28,12 +28,12 @@ class MessageReactor(Object): def __init__( self, *, - client: pyrogram.Client = None, + client: pyrogram.Client | None = None, amount: int, is_top: bool | None = None, is_my: bool | None = None, is_anonymous: bool | None = None, - from_user: types.User = None, + from_user: types.User | None = None, ) -> None: super().__init__(client) diff --git a/pyrogram/types/messages_and_media/message_story.py b/pyrogram/types/messages_and_media/message_story.py index eefb0c4f..cb3b62b3 100644 --- a/pyrogram/types/messages_and_media/message_story.py +++ b/pyrogram/types/messages_and_media/message_story.py @@ -22,8 +22,8 @@ class MessageStory(Object): def __init__( self, *, - from_user: types.User = None, - sender_chat: types.Chat = None, + from_user: types.User | None = None, + sender_chat: types.Chat | None = None, story_id: int, ) -> None: super().__init__() diff --git a/pyrogram/types/messages_and_media/payment_form.py b/pyrogram/types/messages_and_media/payment_form.py index 4fcb6f76..a2b795fe 100644 --- a/pyrogram/types/messages_and_media/payment_form.py +++ b/pyrogram/types/messages_and_media/payment_form.py @@ -48,7 +48,7 @@ class PaymentForm(Object): def __init__( self, *, - client: pyrogram.Client = None, + client: pyrogram.Client | None = None, id: int, bot: types.User, title: str, @@ -59,7 +59,7 @@ def __init__( can_save_credentials: bool | None = None, is_password_missing: bool | None = None, native_provider: str | None = None, - raw: raw.base.payments.PaymentForm = None, + raw: raw.base.payments.PaymentForm | None = None, # TODO: Add support for other params: # native_params # additional_params diff --git a/pyrogram/types/messages_and_media/photo.py b/pyrogram/types/messages_and_media/photo.py index e7944381..f9f35a67 100644 --- a/pyrogram/types/messages_and_media/photo.py +++ b/pyrogram/types/messages_and_media/photo.py @@ -50,7 +50,7 @@ class Photo(Object): def __init__( self, *, - client: pyrogram.Client = None, + client: pyrogram.Client | None = None, file_id: str, file_unique_id: str, width: int, diff --git a/pyrogram/types/messages_and_media/poll.py b/pyrogram/types/messages_and_media/poll.py index 6b285806..cad57e40 100644 --- a/pyrogram/types/messages_and_media/poll.py +++ b/pyrogram/types/messages_and_media/poll.py @@ -1,6 +1,6 @@ from __future__ import annotations -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, cast import pyrogram from pyrogram import enums, raw, types, utils @@ -70,7 +70,7 @@ class Poll(Object, Update): def __init__( self, *, - client: pyrogram.Client = None, + client: pyrogram.Client | None = None, id: str, question: str, options: list[types.PollOption], @@ -78,7 +78,7 @@ def __init__( total_voter_count: int, is_closed: bool, is_anonymous: bool | None = None, - type: enums.PollType = None, + type: enums.PollType | None = None, allows_multiple_answers: bool | None = None, chosen_option_id: int | None = None, correct_option_id: int | None = None, @@ -107,15 +107,19 @@ def __init__( self.close_date = close_date self.recent_voters = recent_voters + self.chat: types.Chat | None = None + self.message_id: int | None = None + self.business_connection_id: str | None = None + @staticmethod async def _parse( client, media_poll: raw.types.MessageMediaPoll | raw.types.UpdateMessagePoll, - users: list[raw.base.User], # noqa: ARG004 + users: dict, ) -> Poll: - poll: raw.types.Poll = media_poll.poll - poll_results: raw.types.PollResults = media_poll.results - results: list[raw.types.PollAnswerVoters] = poll_results.results + poll = cast("raw.types.Poll", media_poll.poll) + poll_results = cast("raw.types.PollResults", media_poll.results) + results = cast("list[raw.types.PollAnswerVoters]", poll_results.results) chosen_option_id = None correct_option_id = None @@ -134,19 +138,23 @@ async def _parse( if result.correct: correct_option_id = i + answer_text = cast("raw.types.TextWithEntities", answer.text) o_entities = ( [ types.MessageEntity._parse(client, entity, {}) - for entity in answer.text.entities + for entity in answer_text.entities ] - if answer.text.entities + if answer_text.entities else [] ) - option_entities = types.List(filter(lambda x: x is not None, o_entities)) + option_entities = cast( + "list[types.MessageEntity]", + types.List([i for i in o_entities if i is not None]), + ) options.append( types.PollOption( - text=answer.text.text, + text=answer_text.text, voter_count=voter_count, data=answer.option, entities=option_entities, @@ -154,39 +162,46 @@ async def _parse( ), ) + poll_question = cast("raw.types.TextWithEntities", poll.question) q_entities = ( [ types.MessageEntity._parse(client, entity, {}) - for entity in poll.question.entities + for entity in poll_question.entities ] - if poll.question.entities + if poll_question.entities else [] ) - question_entities = types.List(filter(lambda x: x is not None, q_entities)) + question_entities = cast( + "list[types.MessageEntity]", + types.List([i for i in q_entities if i is not None]), + ) return Poll( id=str(poll.id), - question=poll.question.text, + question=poll_question.text, options=options, question_entities=question_entities, - total_voter_count=media_poll.results.total_voters, - is_closed=poll.closed, + total_voter_count=poll_results.total_voters or 0, + is_closed=bool(poll.closed), is_anonymous=not poll.public_voters, type=enums.PollType.QUIZ if poll.quiz else enums.PollType.REGULAR, - allows_multiple_answers=poll.multiple_choice, + allows_multiple_answers=bool(poll.multiple_choice), chosen_option_id=chosen_option_id, correct_option_id=correct_option_id, explanation=poll_results.solution, - explanation_entities=[ - types.MessageEntity._parse(client, i, {}) - for i in poll_results.solution_entities - ] + explanation_entities=cast( + "list[types.MessageEntity]", + [ + types.MessageEntity._parse(client, i, {}) + for i in poll_results.solution_entities + ], + ) if poll_results.solution_entities else None, open_period=poll.close_period, close_date=utils.timestamp_to_datetime(poll.close_date), recent_voters=[ - await client.get_users(user.user_id) + await client.get_users(utils.get_raw_peer_id(user)) for user in poll_results.recent_voters ] if poll_results.recent_voters @@ -198,12 +213,13 @@ async def _parse( async def _parse_update( client, update: raw.types.UpdateMessagePoll, - users: list[raw.base.User], + users: list[raw.base.User] | dict, ) -> Poll: if update.poll is not None: - return await Poll._parse(client, update, users) + return await Poll._parse(client, update, cast("dict", users)) - results = update.results.results + poll_results = cast("raw.types.PollResults", update.results) + results = cast("list[raw.types.PollAnswerVoters]", poll_results.results) chosen_option_id = None correct_option_id = None options = [] @@ -224,26 +240,43 @@ async def _parse_update( ), ) - return Poll( + users_dict = ( + users + if isinstance(users, dict) + else {cast("raw.types.User", i).id: i for i in users} + ) + + parsed_poll = Poll( id=str(update.poll_id), question="", options=options, - total_voter_count=update.results.total_voters, + total_voter_count=poll_results.total_voters or 0, is_closed=False, chosen_option_id=chosen_option_id, correct_option_id=correct_option_id, - recent_voters=[ - types.User._parse(client, users.get(user.user_id, None)) - for user in update.results.recent_voters - ] - if update.results.recent_voters + recent_voters=cast( + "list[types.User]", + [ + types.User._parse( + client, + users_dict.get(utils.get_raw_peer_id(user) or 0), + ) + for user in poll_results.recent_voters + ], + ) + if poll_results.recent_voters else None, client=client, ) + parsed_poll.chat = types.Chat._parse( + client, cast("Any", update), {}, {}, is_chat=True + ) + return parsed_poll + async def stop( self, - reply_markup: types.InlineKeyboardMarkup = None, + reply_markup: types.InlineKeyboardMarkup | None = None, business_connection_id: str | None = None, ) -> types.Poll: """Bound method *stop* of :obj:`~pyrogram.types.Poll`. @@ -277,8 +310,8 @@ async def stop( """ return await self._client.stop_poll( - chat_id=self.chat.id, - message_id=self.id, + chat_id=cast("types.Chat", self.chat).id, + message_id=cast("int", self.message_id), reply_markup=reply_markup, business_connection_id=self.business_connection_id if business_connection_id is None diff --git a/pyrogram/types/messages_and_media/poll_option.py b/pyrogram/types/messages_and_media/poll_option.py index 66befec5..82c2082d 100644 --- a/pyrogram/types/messages_and_media/poll_option.py +++ b/pyrogram/types/messages_and_media/poll_option.py @@ -25,7 +25,7 @@ class PollOption(Object): def __init__( self, *, - client: pyrogram.Client = None, + client: pyrogram.Client | None = None, text: str, voter_count: int = 0, data: bytes | None = None, diff --git a/pyrogram/types/messages_and_media/reaction.py b/pyrogram/types/messages_and_media/reaction.py index eb053803..59285239 100644 --- a/pyrogram/types/messages_and_media/reaction.py +++ b/pyrogram/types/messages_and_media/reaction.py @@ -32,8 +32,8 @@ class Reaction(Object): def __init__( self, *, - client: pyrogram.Client = None, - type: types.ReactionType = None, + client: pyrogram.Client | None = None, + type: types.ReactionType | None = None, count: int | None = None, chosen_order: int | None = None, is_paid: bool | None = None, diff --git a/pyrogram/types/messages_and_media/sticker.py b/pyrogram/types/messages_and_media/sticker.py index d686fbdf..b5b2d859 100644 --- a/pyrogram/types/messages_and_media/sticker.py +++ b/pyrogram/types/messages_and_media/sticker.py @@ -74,7 +74,7 @@ class Sticker(Object): def __init__( self, *, - client: pyrogram.Client = None, + client: pyrogram.Client | None = None, file_id: str, file_unique_id: str, width: int, diff --git a/pyrogram/types/messages_and_media/stripped_thumbnail.py b/pyrogram/types/messages_and_media/stripped_thumbnail.py index 4731fbc3..0b3ac552 100644 --- a/pyrogram/types/messages_and_media/stripped_thumbnail.py +++ b/pyrogram/types/messages_and_media/stripped_thumbnail.py @@ -17,7 +17,9 @@ class StrippedThumbnail(Object): Thumbnail data """ - def __init__(self, *, client: pyrogram.Client = None, data: bytes) -> None: + def __init__( + self, *, client: pyrogram.Client | None = None, data: bytes + ) -> None: super().__init__(client) self.data = data diff --git a/pyrogram/types/messages_and_media/thumbnail.py b/pyrogram/types/messages_and_media/thumbnail.py index 6fc9662f..d0cc2836 100644 --- a/pyrogram/types/messages_and_media/thumbnail.py +++ b/pyrogram/types/messages_and_media/thumbnail.py @@ -36,7 +36,7 @@ class Thumbnail(Object): def __init__( self, *, - client: pyrogram.Client = None, + client: pyrogram.Client | None = None, file_id: str, file_unique_id: str, width: int, diff --git a/pyrogram/types/messages_and_media/venue.py b/pyrogram/types/messages_and_media/venue.py index c4a4ae81..6a00e364 100644 --- a/pyrogram/types/messages_and_media/venue.py +++ b/pyrogram/types/messages_and_media/venue.py @@ -30,7 +30,7 @@ class Venue(Object): def __init__( self, *, - client: pyrogram.Client = None, + client: pyrogram.Client | None = None, location: types.Location, title: str, address: str, diff --git a/pyrogram/types/messages_and_media/video.py b/pyrogram/types/messages_and_media/video.py index 55f6a84f..8e52da5a 100644 --- a/pyrogram/types/messages_and_media/video.py +++ b/pyrogram/types/messages_and_media/video.py @@ -61,7 +61,7 @@ class Video(Object): def __init__( self, *, - client: pyrogram.Client = None, + client: pyrogram.Client | None = None, file_id: str, file_unique_id: str, width: int, diff --git a/pyrogram/types/messages_and_media/video_note.py b/pyrogram/types/messages_and_media/video_note.py index 6c945038..78d57664 100644 --- a/pyrogram/types/messages_and_media/video_note.py +++ b/pyrogram/types/messages_and_media/video_note.py @@ -49,7 +49,7 @@ class VideoNote(Object): def __init__( self, *, - client: pyrogram.Client = None, + client: pyrogram.Client | None = None, file_id: str, file_unique_id: str, length: int, diff --git a/pyrogram/types/messages_and_media/voice.py b/pyrogram/types/messages_and_media/voice.py index bca271d0..6609d0f7 100644 --- a/pyrogram/types/messages_and_media/voice.py +++ b/pyrogram/types/messages_and_media/voice.py @@ -46,7 +46,7 @@ class Voice(Object): def __init__( self, *, - client: pyrogram.Client = None, + client: pyrogram.Client | None = None, file_id: str, file_unique_id: str, duration: int, diff --git a/pyrogram/types/messages_and_media/web_page.py b/pyrogram/types/messages_and_media/web_page.py index b3b43106..f1d0a3b7 100644 --- a/pyrogram/types/messages_and_media/web_page.py +++ b/pyrogram/types/messages_and_media/web_page.py @@ -70,7 +70,7 @@ class WebPage(Object): def __init__( self, *, - client: pyrogram.Client = None, + client: pyrogram.Client | None = None, id: str, url: str, display_url: str, @@ -78,11 +78,11 @@ def __init__( site_name: str | None = None, title: str | None = None, description: str | None = None, - audio: types.Audio = None, - document: types.Document = None, - photo: types.Photo = None, - animation: types.Animation = None, - video: types.Video = None, + audio: types.Audio | None = None, + document: types.Document | None = None, + photo: types.Photo | None = None, + animation: types.Animation | None = None, + video: types.Video | None = None, embed_url: str | None = None, embed_type: str | None = None, embed_width: int | None = None, diff --git a/pyrogram/types/messages_and_media/web_page_preview.py b/pyrogram/types/messages_and_media/web_page_preview.py index ffc65140..0c2dfad0 100644 --- a/pyrogram/types/messages_and_media/web_page_preview.py +++ b/pyrogram/types/messages_and_media/web_page_preview.py @@ -41,7 +41,7 @@ def __init__( @staticmethod def _parse( client, - web_page_preview: raw.types.WebPage | raw.types.WebPageEmpty, + web_page_preview: raw.types.MessageMediaWebPage, invert_media: bool | None = None, ): if isinstance(web_page_preview.webpage, raw.types.WebPage): diff --git a/pyrogram/types/object.py b/pyrogram/types/object.py index 2af7d620..12ec8573 100644 --- a/pyrogram/types/object.py +++ b/pyrogram/types/object.py @@ -10,8 +10,8 @@ class Object: - def __init__(self, client: pyrogram.Client = None) -> None: - self._client = client + def __init__(self, client: pyrogram.Client | None = None) -> None: + self._client: pyrogram.Client = client # type: ignore def bind(self, client: pyrogram.Client) -> None: """Bind a Client instance to this and to all nested Pyrogram objects. diff --git a/pyrogram/types/payments/gift.py b/pyrogram/types/payments/gift.py index 60802851..af849bc9 100644 --- a/pyrogram/types/payments/gift.py +++ b/pyrogram/types/payments/gift.py @@ -138,9 +138,9 @@ class Gift(Object): def __init__( self, *, - client: pyrogram.Client = None, + client: pyrogram.Client | None = None, id: int, - sticker: types.Sticker = None, + sticker: types.Sticker | None = None, star_count: int | None = None, default_sell_star_count: int | None = None, remaining_count: int | None = None, diff --git a/pyrogram/types/payments/user_gift.py b/pyrogram/types/payments/user_gift.py index fea2fb30..43fb5bcf 100644 --- a/pyrogram/types/payments/user_gift.py +++ b/pyrogram/types/payments/user_gift.py @@ -1,177 +1,177 @@ -from __future__ import annotations - -from typing import TYPE_CHECKING - -import pyrogram -from pyrogram import raw, types, utils -from pyrogram.types.messages_and_media.message import Str -from pyrogram.types.object import Object - -if TYPE_CHECKING: - from datetime import datetime - - -class UserGift(Object): - """Represents a gift received by a user. - - Parameters: - sender_user (:obj:`~pyrogram.types.User`, *optional*): - Identifier of the user that sent the gift; None if unknown. - - text (``str``, *optional*): - Message added to the gift. - - entities (List of :obj:`~pyrogram.types.MessageEntity`, *optional*): - For text messages, special entities like usernames, URLs, bot commands, etc. that appear in the text. - - is_private (``bool``, *optional*): - True, if the sender and gift text are shown only to the gift receiver; otherwise, everyone are able to see them. - - is_saved (``bool``, *optional*): - True, if the gift is displayed on the user's profile page; may be False only for the receiver of the gift. - - date (``datetime``): - Date when the gift was sent. - - gift (:obj:`~pyrogram.types.Gift`, *optional*): - Information about the gift. - - message_id (``int``, *optional*): - Identifier of the message with the gift in the chat with the sender of the gift; can be None or an identifier of a deleted message; only for the gift receiver. - - sell_star_count (``int``, *optional*): - Number of Telegram Stars that can be claimed by the receiver instead of the gift; only for the gift receiver. - - """ - - def __init__( - self, - *, - client: pyrogram.Client = None, - sender_user: types.User | None = None, - text: str | None = None, - entities: list[types.MessageEntity] | None = None, - date: datetime, - is_private: bool | None = None, - is_saved: bool | None = None, - gift: types.Gift | None = None, - message_id: int | None = None, - sell_star_count: int | None = None, - ) -> None: - super().__init__(client) - - self.date = date - self.gift = gift - self.is_private = is_private - self.is_saved = is_saved - self.sender_user = sender_user - self.text = text - self.entities = entities - self.message_id = message_id - self.sell_star_count = sell_star_count - - @staticmethod - async def _parse( - client, - user_star_gift: raw.types.UserStarGift, - users: dict, - ) -> UserGift: - text, entities = None, None - if getattr(user_star_gift, "message", None): - text = user_star_gift.message.text or None - entities = [ - types.MessageEntity._parse(client, entity, users) - for entity in user_star_gift.message.entities - ] - entities = types.List(filter(lambda x: x is not None, entities)) - - return UserGift( - date=utils.timestamp_to_datetime(user_star_gift.date), - gift=await types.Gift._parse(client, user_star_gift.gift), - is_private=getattr(user_star_gift, "name_hidden", None), - is_saved=not user_star_gift.unsaved - if getattr(user_star_gift, "unsaved", None) - else None, - sender_user=types.User._parse(client, users.get(user_star_gift.from_id)) - if getattr(user_star_gift, "from_id", None) - else None, - message_id=getattr(user_star_gift, "msg_id", None), - sell_star_count=getattr(user_star_gift, "convert_stars", None), - text=Str(text).init(entities) if text else None, - entities=entities, - client=client, - ) - - @staticmethod - async def _parse_action( - client, - message: raw.base.Message, - users: dict, - ) -> UserGift: - action = message.action - - doc = action.gift.sticker - attributes = {type(i): i for i in doc.attributes} - - text, entities = None, None - if getattr(action, "message", None): - text = action.message.text or None - entities = [ - types.MessageEntity._parse(client, entity, users) - for entity in action.message.entities - ] - entities = types.List(filter(lambda x: x is not None, entities)) - - return UserGift( - gift=types.Gift( - id=action.gift.id, - sticker=await types.Sticker._parse(client, doc, attributes), - star_count=action.gift.stars, - default_sell_star_count=action.gift.convert_stars, - remaining_count=getattr(action.gift, "availability_remains", None), - total_count=getattr(action.gift, "availability_total", None), - is_limited=getattr(action.gift, "limited", None), - ), - date=utils.timestamp_to_datetime(message.date), - is_private=getattr(action, "name_hidden", None), - is_saved=getattr(action, "saved", None), - sender_user=types.User._parse( - client, - users.get(utils.get_raw_peer_id(message.peer_id)), - ), - message_id=message.id, - text=Str(text).init(entities) if text else None, - entities=entities, - client=client, - ) - - async def toggle(self, is_saved: bool) -> bool: - """Bound method *toggle* of :obj:`~pyrogram.types.UserGift`. - - Use as a shortcut for: - - .. code-block:: python - - await client.toggle_gift_is_saved( - sender_user_id=user_id, - message_id=message_id - ) - - Parameters: - is_saved (``bool``): - Pass True to display the gift on the user's profile page; pass False to remove it from the profile page. - - Example: - .. code-block:: python - - await user_gift.toggle(is_saved=False) - - Returns: - ``bool``: On success, True is returned. - - """ - return await self._client.toggle_gift_is_saved( - sender_user_id=self.sender_user.id, - message_id=self.message_id, - is_saved=is_saved, - ) +from __future__ import annotations + +from typing import TYPE_CHECKING + +import pyrogram +from pyrogram import raw, types, utils +from pyrogram.types.messages_and_media.message import Str +from pyrogram.types.object import Object + +if TYPE_CHECKING: + from datetime import datetime + + +class UserGift(Object): + """Represents a gift received by a user. + + Parameters: + sender_user (:obj:`~pyrogram.types.User`, *optional*): + Identifier of the user that sent the gift; None if unknown. + + text (``str``, *optional*): + Message added to the gift. + + entities (List of :obj:`~pyrogram.types.MessageEntity`, *optional*): + For text messages, special entities like usernames, URLs, bot commands, etc. that appear in the text. + + is_private (``bool``, *optional*): + True, if the sender and gift text are shown only to the gift receiver; otherwise, everyone are able to see them. + + is_saved (``bool``, *optional*): + True, if the gift is displayed on the user's profile page; may be False only for the receiver of the gift. + + date (``datetime``): + Date when the gift was sent. + + gift (:obj:`~pyrogram.types.Gift`, *optional*): + Information about the gift. + + message_id (``int``, *optional*): + Identifier of the message with the gift in the chat with the sender of the gift; can be None or an identifier of a deleted message; only for the gift receiver. + + sell_star_count (``int``, *optional*): + Number of Telegram Stars that can be claimed by the receiver instead of the gift; only for the gift receiver. + + """ + + def __init__( + self, + *, + client: pyrogram.Client | None = None, + sender_user: types.User | None = None, + text: str | None = None, + entities: list[types.MessageEntity] | None = None, + date: datetime, + is_private: bool | None = None, + is_saved: bool | None = None, + gift: types.Gift | None = None, + message_id: int | None = None, + sell_star_count: int | None = None, + ) -> None: + super().__init__(client) + + self.date = date + self.gift = gift + self.is_private = is_private + self.is_saved = is_saved + self.sender_user = sender_user + self.text = text + self.entities = entities + self.message_id = message_id + self.sell_star_count = sell_star_count + + @staticmethod + async def _parse( + client, + user_star_gift: raw.types.UserStarGift, + users: dict, + ) -> UserGift: + text, entities = None, None + if getattr(user_star_gift, "message", None): + text = user_star_gift.message.text or None + entities = [ + types.MessageEntity._parse(client, entity, users) + for entity in user_star_gift.message.entities + ] + entities = types.List(filter(lambda x: x is not None, entities)) + + return UserGift( + date=utils.timestamp_to_datetime(user_star_gift.date), + gift=await types.Gift._parse(client, user_star_gift.gift), + is_private=getattr(user_star_gift, "name_hidden", None), + is_saved=not user_star_gift.unsaved + if getattr(user_star_gift, "unsaved", None) + else None, + sender_user=types.User._parse(client, users.get(user_star_gift.from_id)) + if getattr(user_star_gift, "from_id", None) + else None, + message_id=getattr(user_star_gift, "msg_id", None), + sell_star_count=getattr(user_star_gift, "convert_stars", None), + text=Str(text).init(entities) if text else None, + entities=entities, + client=client, + ) + + @staticmethod + async def _parse_action( + client, + message: raw.base.Message, + users: dict, + ) -> UserGift: + action = message.action + + doc = action.gift.sticker + attributes = {type(i): i for i in doc.attributes} + + text, entities = None, None + if getattr(action, "message", None): + text = action.message.text or None + entities = [ + types.MessageEntity._parse(client, entity, users) + for entity in action.message.entities + ] + entities = types.List(filter(lambda x: x is not None, entities)) + + return UserGift( + gift=types.Gift( + id=action.gift.id, + sticker=await types.Sticker._parse(client, doc, attributes), + star_count=action.gift.stars, + default_sell_star_count=action.gift.convert_stars, + remaining_count=getattr(action.gift, "availability_remains", None), + total_count=getattr(action.gift, "availability_total", None), + is_limited=getattr(action.gift, "limited", None), + ), + date=utils.timestamp_to_datetime(message.date), + is_private=getattr(action, "name_hidden", None), + is_saved=getattr(action, "saved", None), + sender_user=types.User._parse( + client, + users.get(utils.get_raw_peer_id(message.peer_id)), + ), + message_id=message.id, + text=Str(text).init(entities) if text else None, + entities=entities, + client=client, + ) + + async def toggle(self, is_saved: bool) -> bool: + """Bound method *toggle* of :obj:`~pyrogram.types.UserGift`. + + Use as a shortcut for: + + .. code-block:: python + + await client.toggle_gift_is_saved( + sender_user_id=user_id, + message_id=message_id + ) + + Parameters: + is_saved (``bool``): + Pass True to display the gift on the user's profile page; pass False to remove it from the profile page. + + Example: + .. code-block:: python + + await user_gift.toggle(is_saved=False) + + Returns: + ``bool``: On success, True is returned. + + """ + return await self._client.toggle_gift_is_saved( + sender_user_id=self.sender_user.id, + message_id=self.message_id, + is_saved=is_saved, + ) diff --git a/pyrogram/types/stories/story.py b/pyrogram/types/stories/story.py index 4dbcc6e4..9dacac89 100644 --- a/pyrogram/types/stories/story.py +++ b/pyrogram/types/stories/story.py @@ -101,18 +101,18 @@ class Story(Object, Update): def __init__( self, *, - client: pyrogram.Client = None, + client: pyrogram.Client | None = None, id: int, - chat: types.Chat = None, - from_user: types.User = None, - sender_chat: types.Chat = None, + chat: types.Chat | None = None, + from_user: types.User | None = None, + sender_chat: types.Chat | None = None, date: datetime, expire_date: datetime, media: enums.MessageMediaType, has_protected_content: bool | None = None, - animation: types.Animation = None, - photo: types.Photo = None, - video: types.Video = None, + animation: types.Animation | None = None, + photo: types.Photo | None = None, + video: types.Video | None = None, edited: bool | None = None, pinned: bool | None = None, public: bool | None = None, @@ -121,13 +121,13 @@ def __init__( selected_contacts: bool | None = None, caption: str | None = None, caption_entities: list[types.MessageEntity] | None = None, - views: types.StoryViews = None, - privacy: enums.StoryPrivacy = None, - forward_from: types.StoryForwardHeader = None, + views: types.StoryViews | None = None, + privacy: enums.StoryPrivacy | None = None, + forward_from: types.StoryForwardHeader | None = None, allowed_users: list[int] | None = None, denied_users: list[int] | None = None, media_areas: list[types.MediaArea] | None = None, - raw: raw.types.StoryItem = None, + raw: raw.types.StoryItem | None = None, ) -> None: super().__init__(client) @@ -1546,14 +1546,14 @@ async def edit_animation(self, animation: str | BinaryIO) -> types.Story: async def edit( self, - privacy: enums.StoriesPrivacyRules = None, + privacy: enums.StoriesPrivacyRules | None = None, allowed_users: list[int] | None = None, denied_users: list[int] | None = None, animation: str | None = None, photo: str | None = None, video: str | None = None, caption: str | None = None, - parse_mode: enums.ParseMode = None, + parse_mode: enums.ParseMode | None = None, caption_entities: list[types.MessageEntity] | None = None, media_areas: list[types.InputMediaArea] | None = None, ) -> types.Story: @@ -1723,7 +1723,7 @@ async def edit_photo(self, photo: str | BinaryIO) -> types.Story: async def edit_privacy( self, - privacy: enums.StoriesPrivacyRules = None, + privacy: enums.StoriesPrivacyRules | None = None, allowed_users: list[int] | None = None, denied_users: list[int] | None = None, ) -> types.Story: @@ -1831,13 +1831,13 @@ async def export_link(self) -> types.ExportedStoryLink: async def forward( self, chat_id: int | None = None, - privacy: enums.StoriesPrivacyRules = None, + privacy: enums.StoriesPrivacyRules | None = None, allowed_users: list[int] | None = None, denied_users: list[int] | None = None, pinned: bool | None = None, protect_content: bool | None = None, caption: str | None = None, - parse_mode: enums.ParseMode = None, + parse_mode: enums.ParseMode | None = None, caption_entities: list[types.MessageEntity] | None = None, period: int | None = None, ): diff --git a/pyrogram/types/stories/story_deleted.py b/pyrogram/types/stories/story_deleted.py index 858b4822..bfd5326b 100644 --- a/pyrogram/types/stories/story_deleted.py +++ b/pyrogram/types/stories/story_deleted.py @@ -23,10 +23,10 @@ class StoryDeleted(Object, Update): def __init__( self, *, - client: pyrogram.Client = None, + client: pyrogram.Client | None = None, id: int, - from_user: types.User = None, - sender_chat: types.Chat = None, + from_user: types.User | None = None, + sender_chat: types.Chat | None = None, ) -> None: super().__init__(client) diff --git a/pyrogram/types/stories/story_forward_header.py b/pyrogram/types/stories/story_forward_header.py index 9897e670..2bcdb75f 100644 --- a/pyrogram/types/stories/story_forward_header.py +++ b/pyrogram/types/stories/story_forward_header.py @@ -29,9 +29,9 @@ class StoryForwardHeader(Object): def __init__( self, *, - user: types.User = None, + user: types.User | None = None, sender_name: str | None = None, - chat: types.Chat = None, + chat: types.Chat | None = None, story_id: int | None = None, is_modified: bool | None = None, ) -> None: diff --git a/pyrogram/types/stories/story_skipped.py b/pyrogram/types/stories/story_skipped.py index c83fe23e..a29728c8 100644 --- a/pyrogram/types/stories/story_skipped.py +++ b/pyrogram/types/stories/story_skipped.py @@ -37,10 +37,10 @@ class StorySkipped(Object, Update): def __init__( self, *, - client: pyrogram.Client = None, + client: pyrogram.Client | None = None, id: int, - from_user: types.User = None, - sender_chat: types.Chat = None, + from_user: types.User | None = None, + sender_chat: types.Chat | None = None, date: datetime, expire_date: datetime, close_friends: bool | None = None, diff --git a/pyrogram/types/user_and_chats/birthday.py b/pyrogram/types/user_and_chats/birthday.py index 268251cc..35c37ece 100644 --- a/pyrogram/types/user_and_chats/birthday.py +++ b/pyrogram/types/user_and_chats/birthday.py @@ -24,7 +24,7 @@ def __init__(self, *, day: int, month: int, year: int) -> None: self.year = year @staticmethod - def _parse(birthday: raw.types.Birthday = None) -> Birthday: + def _parse(birthday: raw.types.Birthday | None = None) -> Birthday: return Birthday(day=birthday.day, month=birthday.month, year=birthday.year) async def write(self) -> raw.types.Birthday: diff --git a/pyrogram/types/user_and_chats/business_info.py b/pyrogram/types/user_and_chats/business_info.py index 956a3bd5..559bf57c 100644 --- a/pyrogram/types/user_and_chats/business_info.py +++ b/pyrogram/types/user_and_chats/business_info.py @@ -28,10 +28,10 @@ def __init__( self, *, address: str | None = None, - location: types.Location = None, - greeting_message: types.BusinessMessage = None, - away_message: types.BusinessMessage = None, - working_hours: types.BusinessWorkingHours = None, + location: types.Location | None = None, + greeting_message: types.BusinessMessage | None = None, + away_message: types.BusinessMessage | None = None, + working_hours: types.BusinessWorkingHours | None = None, ) -> None: self.address = address self.location = location @@ -42,7 +42,7 @@ def __init__( @staticmethod def _parse( client, - user: raw.types.UserFull = None, + user: raw.types.UserFull | None = None, users: dict | None = None, ) -> BusinessInfo | None: working_hours = getattr(user, "business_work_hours", None) diff --git a/pyrogram/types/user_and_chats/business_message.py b/pyrogram/types/user_and_chats/business_message.py index eba8193b..3eb5ec5a 100644 --- a/pyrogram/types/user_and_chats/business_message.py +++ b/pyrogram/types/user_and_chats/business_message.py @@ -50,7 +50,7 @@ def __init__( no_activity_days: int | None = None, offline_only: bool | None = None, recipients: list[types.User] | None = None, - schedule: enums.BusinessSchedule = None, + schedule: enums.BusinessSchedule | None = None, start_date: datetime | None = None, end_date: datetime | None = None, ) -> None: diff --git a/pyrogram/types/user_and_chats/business_weekly_open.py b/pyrogram/types/user_and_chats/business_weekly_open.py index bed104cb..9c0c53fb 100644 --- a/pyrogram/types/user_and_chats/business_weekly_open.py +++ b/pyrogram/types/user_and_chats/business_weekly_open.py @@ -30,7 +30,7 @@ def __init__( @staticmethod def _parse( - weekly_open: raw.types.BusinessWeeklyOpen = None, + weekly_open: raw.types.BusinessWeeklyOpen | None = None, ) -> BusinessWeeklyOpen: return BusinessWeeklyOpen( start_minute=weekly_open.start_minute, diff --git a/pyrogram/types/user_and_chats/business_working_hours.py b/pyrogram/types/user_and_chats/business_working_hours.py index ff5532ae..cf7639da 100644 --- a/pyrogram/types/user_and_chats/business_working_hours.py +++ b/pyrogram/types/user_and_chats/business_working_hours.py @@ -31,7 +31,7 @@ def __init__( @staticmethod def _parse( - work_hours: raw.types.BusinessWorkHours = None, + work_hours: raw.types.BusinessWorkHours | None = None, ) -> BusinessWorkingHours | None: if not work_hours: return None diff --git a/pyrogram/types/user_and_chats/chat.py b/pyrogram/types/user_and_chats/chat.py index 01c5aa03..b22a703a 100644 --- a/pyrogram/types/user_and_chats/chat.py +++ b/pyrogram/types/user_and_chats/chat.py @@ -229,7 +229,7 @@ class Chat(Object): def __init__( self, *, - client: pyrogram.Client = None, + client: pyrogram.Client | None = None, id: int, type: enums.ChatType, is_verified: bool | None = None, @@ -257,9 +257,9 @@ def __init__( username: str | None = None, first_name: str | None = None, last_name: str | None = None, - photo: types.ChatPhoto = None, + photo: types.ChatPhoto | None = None, stories: list[types.Story] | None = None, - wallpaper: types.Document = None, + wallpaper: types.Document | None = None, bio: str | None = None, description: str | None = None, dc_id: int | None = None, @@ -273,17 +273,17 @@ def __init__( slow_mode_delay: int | None = None, join_requests_count: int | None = None, restrictions: list[types.Restriction] | None = None, - permissions: types.ChatPermissions = None, + permissions: types.ChatPermissions | None = None, distance: int | None = None, - linked_chat: types.Chat = None, - send_as_chat: types.Chat = None, + linked_chat: types.Chat | None = None, + send_as_chat: types.Chat | None = None, available_reactions: types.ChatReactions | None = None, usernames: list[types.Username] | None = None, - reply_color: types.ChatColor = None, - profile_color: types.ChatColor = None, - business_info: types.BusinessInfo = None, - birthday: types.Birthday = None, - personal_chat: types.Chat = None, + reply_color: types.ChatColor | None = None, + profile_color: types.ChatColor | None = None, + business_info: types.BusinessInfo | None = None, + birthday: types.Birthday | None = None, + personal_chat: types.Chat | None = None, subscription_until_date: datetime | None = None, can_enable_paid_reaction: bool | None = None, max_reaction_count: int | None = None, @@ -359,7 +359,7 @@ def full_name(self) -> str: return ( " ".join(filter(None, [self.first_name, self.last_name])) or self.title - or None + or "" ) @staticmethod @@ -381,10 +381,17 @@ def _parse_user_chat(client, user: raw.types.User) -> Chat: client, user.photo, peer_id, - user.access_hash, - ), + user.access_hash or 0, + ) + if isinstance( + user.photo, (raw.types.UserProfilePhoto, raw.types.ChatPhoto) + ) + else None, restrictions=types.List( - [types.Restriction._parse(r) for r in user.restriction_reason], + [ + types.Restriction._parse(r) + for r in (user.restriction_reason or []) + ], ) or None, dc_id=getattr(getattr(user, "photo", None), "dc_id", None), @@ -396,7 +403,9 @@ def _parse_user_chat(client, user: raw.types.User) -> Chat: ) @staticmethod - def _parse_chat_chat(client, chat: raw.types.Chat) -> Chat: + def _parse_chat_chat( + client, chat: raw.types.Chat | raw.types.ChatForbidden + ) -> Chat: peer_id = -chat.id active_usernames = getattr(chat, "usernames", []) usernames = None @@ -428,7 +437,9 @@ def _parse_chat_chat(client, chat: raw.types.Chat) -> Chat: ) @staticmethod - def _parse_channel_chat(client, channel: raw.types.Channel) -> Chat: + def _parse_channel_chat( + client, channel: raw.types.Channel | raw.types.ChannelForbidden + ) -> Chat: peer_id = utils.get_channel_id(channel.id) restriction_reason = getattr(channel, "restriction_reason", []) user_name = getattr(channel, "username", None) @@ -536,15 +547,21 @@ def _parse_dialog(client, peer, users: dict, chats: dict): async def _parse_full( client, chat_full: raw.types.messages.ChatFull | raw.types.users.UserFull, - ) -> Chat: - users = {u.id: u for u in chat_full.users} - chats = {c.id: c for c in chat_full.chats} + ) -> Chat | None: + users = {getattr(u, "id", 0): u for u in chat_full.users} + chats = {getattr(c, "id", 0): c for c in chat_full.chats} if isinstance(chat_full, raw.types.users.UserFull): full_user = chat_full.full_user + if not isinstance(full_user, raw.types.UserFull): + return None + + user_raw = users.get(full_user.id) + if not isinstance(user_raw, raw.types.User): + return None - parsed_chat = Chat._parse_user_chat(client, users[full_user.id]) - parsed_chat.bio = full_user.about + parsed_chat = Chat._parse_user_chat(client, user_raw) + parsed_chat.bio = getattr(full_user, "about", None) parsed_chat.folder_id = getattr(full_user, "folder_id", None) parsed_chat.business_info = types.BusinessInfo._parse( client, @@ -571,14 +588,16 @@ async def _parse_full( personal_chat.chats[0], ) - if full_user.pinned_msg_id: + full_user_pinned_msg_id = getattr(full_user, "pinned_msg_id", None) + if full_user_pinned_msg_id: parsed_chat.pinned_message = await client.get_messages( parsed_chat.id, - message_ids=full_user.pinned_msg_id, + message_ids=full_user_pinned_msg_id, ) - if full_user.stories: - peer_stories: raw.types.PeerStories = full_user.stories + full_user_stories = getattr(full_user, "stories", None) + if full_user_stories: + peer_stories: raw.types.PeerStories = full_user_stories parsed_chat.stories = ( types.List( [ @@ -593,20 +612,25 @@ async def _parse_full( or None ) - if full_user.wallpaper and isinstance( - full_user.wallpaper, + full_user_wallpaper = getattr(full_user, "wallpaper", None) + if full_user_wallpaper and isinstance( + full_user_wallpaper, raw.types.WallPaper, ): parsed_chat.wallpaper = types.Document._parse( client, - full_user.wallpaper.document, + full_user_wallpaper.document, "wallpaper.jpg", ) else: full_chat = chat_full.full_chat - chat_raw = chats[full_chat.id] + chat_raw = chats.get(getattr(full_chat, "id", 0)) if isinstance(full_chat, raw.types.ChatFull): + if not isinstance( + chat_raw, (raw.types.Chat, raw.types.ChatForbidden) + ): + return None parsed_chat = Chat._parse_chat_chat(client, chat_raw) parsed_chat.description = full_chat.about or None @@ -615,8 +639,12 @@ async def _parse_full( full_chat.participants.participants, ) else: + if not isinstance(chat_raw, raw.types.Channel): + return None parsed_chat = Chat._parse_channel_chat(client, chat_raw) - parsed_chat.members_count = full_chat.participants_count + parsed_chat.members_count = getattr( + full_chat, "participants_count", None + ) parsed_chat.slow_mode_delay = getattr( full_chat, "slowmode_seconds", @@ -627,40 +655,60 @@ async def _parse_full( "paid_reactions_available", None, ) - parsed_chat.description = full_chat.about or None - parsed_chat.can_set_sticker_set = full_chat.can_set_stickers + parsed_chat.description = getattr(full_chat, "about", None) or None + parsed_chat.can_set_sticker_set = getattr( + full_chat, "can_set_stickers", None + ) parsed_chat.sticker_set_name = getattr( - full_chat.stickerset, + getattr(full_chat, "stickerset", None), "short_name", None, ) - parsed_chat.is_participants_hidden = full_chat.participants_hidden - parsed_chat.is_antispam = full_chat.antispam + parsed_chat.is_participants_hidden = getattr( + full_chat, "participants_hidden", None + ) + parsed_chat.is_antispam = getattr(full_chat, "antispam", None) parsed_chat.folder_id = getattr(full_chat, "folder_id", None) - parsed_chat.can_enable_paid_reaction = ( - full_chat.paid_reactions_available + parsed_chat.can_enable_paid_reaction = getattr( + full_chat, + "paid_reactions_available", + None, ) - linked_chat_raw = chats.get(full_chat.linked_chat_id) + linked_chat_id = getattr(full_chat, "linked_chat_id", None) + linked_chat_raw = ( + chats.get(linked_chat_id) if linked_chat_id else None + ) - if linked_chat_raw: + if isinstance( + linked_chat_raw, (raw.types.Channel, raw.types.ChannelForbidden) + ): parsed_chat.linked_chat = Chat._parse_channel_chat( client, linked_chat_raw, ) - default_send_as = full_chat.default_send_as + default_send_as = getattr(full_chat, "default_send_as", None) if default_send_as: if isinstance(default_send_as, raw.types.PeerUser): - send_as_raw = users[default_send_as.user_id] + send_as_raw = users.get(default_send_as.user_id) else: - send_as_raw = chats[default_send_as.channel_id] + send_as_raw = chats.get( + getattr(default_send_as, "channel_id", 0) + ) - parsed_chat.send_as_chat = Chat._parse_chat(client, send_as_raw) + if isinstance( + send_as_raw, + (raw.types.Chat, raw.types.User, raw.types.Channel), + ): + parsed_chat.send_as_chat = Chat._parse_chat( + client, send_as_raw + ) - if full_chat.stories: - peer_stories: raw.types.PeerStories = full_chat.stories + full_chat_stories = getattr(full_chat, "stories", None) + if full_chat_stories: + peer_stories: raw.types.PeerStories = full_chat_stories parsed_chat.stories = ( types.List( [ @@ -675,31 +723,34 @@ async def _parse_full( or None ) - if full_chat.wallpaper and isinstance( - full_chat.wallpaper, + full_chat_wallpaper = getattr(full_chat, "wallpaper", None) + if full_chat_wallpaper and isinstance( + full_chat_wallpaper, raw.types.WallPaper, ): parsed_chat.wallpaper = types.Document._parse( client, - full_chat.wallpaper.document, + full_chat_wallpaper.document, "wallpaper.jpg", ) - if full_chat.pinned_msg_id: + pinned_msg_id = getattr(full_chat, "pinned_msg_id", None) + if pinned_msg_id: parsed_chat.pinned_message = await client.get_messages( parsed_chat.id, - message_ids=full_chat.pinned_msg_id, + message_ids=pinned_msg_id, ) + exported_invite = getattr(full_chat, "exported_invite", None) if isinstance( - full_chat.exported_invite, + exported_invite, raw.types.ChatInviteExported, ): - parsed_chat.invite_link = full_chat.exported_invite.link + parsed_chat.invite_link = exported_invite.link parsed_chat.available_reactions = types.ChatReactions._parse( client, - full_chat.available_reactions, + getattr(full_chat, "available_reactions", None), ) parsed_chat.join_requests_count = getattr( full_chat, @@ -752,7 +803,7 @@ def listen(self, *args, **kwargs): RPCError: In case of a Telegram RPC error. asyncio.TimeoutError: In case reply not received within the timeout. """ - return self._client.listen(*args, chat_id=self.id, **kwargs) + return self._client.listen(self.id, *args, **kwargs) def ask(self, text, *args, **kwargs): """Bound method *ask* of :obj:`~pyrogram.types.Chat`. @@ -810,7 +861,7 @@ def stop_listening(self, *args, **kwargs): chat.stop_listen() """ - return self._client.stop_listening(*args, chat_id=self.id, **kwargs) + return self._client.stop_listening(self.id, *args, **kwargs) async def archive(self): """Bound method *archive* of :obj:`~pyrogram.types.Chat`. @@ -1137,7 +1188,7 @@ async def restrict_member( async def promote_member( self, user_id: int | str, - privileges: types.ChatPrivileges = None, + privileges: types.ChatPrivileges | None = None, title: str | None = "", ) -> bool: """Bound method *promote_member* of :obj:`~pyrogram.types.Chat`. diff --git a/pyrogram/types/user_and_chats/chat_color.py b/pyrogram/types/user_and_chats/chat_color.py index 54ffe661..054c658d 100644 --- a/pyrogram/types/user_and_chats/chat_color.py +++ b/pyrogram/types/user_and_chats/chat_color.py @@ -18,7 +18,7 @@ class ChatColor(Object): def __init__( self, *, - color: enums.ReplyColor | enums.ProfileColor = None, + color: enums.ReplyColor | enums.ProfileColor | None = None, background_emoji_id: int | None = None, ) -> None: self.color = color @@ -26,7 +26,7 @@ def __init__( @staticmethod def _parse( - color: raw.types.PeerColor = None, + color: raw.types.PeerColor | None = None, ) -> ChatColor | None: if not color: return None @@ -40,7 +40,7 @@ def _parse( @staticmethod def _parse_profile_color( - color: raw.types.PeerColor = None, + color: raw.types.PeerColor | None = None, ) -> ChatColor | None: if not color: return None diff --git a/pyrogram/types/user_and_chats/chat_event.py b/pyrogram/types/user_and_chats/chat_event.py index d79d66da..4fec5f2c 100644 --- a/pyrogram/types/user_and_chats/chat_event.py +++ b/pyrogram/types/user_and_chats/chat_event.py @@ -177,51 +177,51 @@ def __init__( new_description: str | None = None, old_history_ttl: int | None = None, new_history_ttl: int | None = None, - old_linked_chat: types.Chat = None, - new_linked_chat: types.Chat = None, - old_photo: types.Photo = None, - new_photo: types.Photo = None, + old_linked_chat: types.Chat | None = None, + new_linked_chat: types.Chat | None = None, + old_photo: types.Photo | None = None, + new_photo: types.Photo | None = None, old_title: str | None = None, new_title: str | None = None, old_username: str | None = None, new_username: str | None = None, old_usernames: list[types.Username] | None = None, new_usernames: list[types.Username] | None = None, - old_chat_permissions: types.ChatPermissions = None, - new_chat_permissions: types.ChatPermissions = None, - deleted_message: types.Message = None, - old_message: types.Message = None, - new_message: types.Message = None, - invited_member: types.ChatMember = None, - invite_link: types.ChatInviteLink = None, + old_chat_permissions: types.ChatPermissions | None = None, + new_chat_permissions: types.ChatPermissions | None = None, + deleted_message: types.Message | None = None, + old_message: types.Message | None = None, + new_message: types.Message | None = None, + invited_member: types.ChatMember | None = None, + invite_link: types.ChatInviteLink | None = None, via_chat_folder_invite_link: bool | None = None, - approver_user: types.User = None, - old_administrator_privileges: types.ChatMember = None, - new_administrator_privileges: types.ChatMember = None, - old_member_permissions: types.ChatMember = None, - new_member_permissions: types.ChatMember = None, - stopped_poll: types.Message = None, - invites_enabled: types.ChatMember = None, + approver_user: types.User | None = None, + old_administrator_privileges: types.ChatMember | None = None, + new_administrator_privileges: types.ChatMember | None = None, + old_member_permissions: types.ChatMember | None = None, + new_member_permissions: types.ChatMember | None = None, + stopped_poll: types.Message | None = None, + invites_enabled: types.ChatMember | None = None, history_hidden: bool | None = None, signatures_enabled: bool | None = None, old_slow_mode: int | None = None, new_slow_mode: int | None = None, - pinned_message: types.Message = None, - unpinned_message: types.Message = None, - old_invite_link: types.ChatInviteLink = None, - new_invite_link: types.ChatInviteLink = None, - revoked_invite_link: types.ChatInviteLink = None, - deleted_invite_link: types.ChatInviteLink = None, - old_chat_member: types.ChatMember = None, - new_chat_member: types.ChatMember = None, + pinned_message: types.Message | None = None, + unpinned_message: types.Message | None = None, + old_invite_link: types.ChatInviteLink | None = None, + new_invite_link: types.ChatInviteLink | None = None, + revoked_invite_link: types.ChatInviteLink | None = None, + deleted_invite_link: types.ChatInviteLink | None = None, + old_chat_member: types.ChatMember | None = None, + new_chat_member: types.ChatMember | None = None, show_message_sender_enabled: bool | None = None, has_aggressive_anti_spam_enabled: bool | None = None, has_protected_content: bool | None = None, is_forum: bool | None = None, - created_forum_topic: types.ForumTopic = None, - old_forum_topic: types.ForumTopic = None, - new_forum_topic: types.ForumTopic = None, - deleted_forum_topic: types.ForumTopic = None, + created_forum_topic: types.ForumTopic | None = None, + old_forum_topic: types.ForumTopic | None = None, + new_forum_topic: types.ForumTopic | None = None, + deleted_forum_topic: types.ForumTopic | None = None, ) -> None: super().__init__() diff --git a/pyrogram/types/user_and_chats/chat_invite_link.py b/pyrogram/types/user_and_chats/chat_invite_link.py index d66998d9..0fa3f410 100644 --- a/pyrogram/types/user_and_chats/chat_invite_link.py +++ b/pyrogram/types/user_and_chats/chat_invite_link.py @@ -65,11 +65,11 @@ class ChatInviteLink(Object): def __init__( self, *, - invite_link: str, - date: datetime, + invite_link: str | None = None, + date: datetime | None = None, is_primary: bool | None = None, is_revoked: bool | None = None, - creator: types.User = None, + creator: types.User | None = None, name: str | None = None, creates_join_request: bool | None = None, start_date: datetime | None = None, @@ -116,10 +116,10 @@ def _parse( subscription_pricing = getattr(invite, "subscription_pricing", None) return ChatInviteLink( - invite_link=invite.link, - date=utils.timestamp_to_datetime(invite.date), - is_primary=invite.permanent, - is_revoked=invite.revoked, + invite_link=getattr(invite, "link", None), + date=utils.timestamp_to_datetime(getattr(invite, "date", None)), + is_primary=getattr(invite, "permanent", None), + is_revoked=getattr(invite, "revoked", None), creator=creator, name=invite.title, creates_join_request=invite.request_needed, diff --git a/pyrogram/types/user_and_chats/chat_join_request.py b/pyrogram/types/user_and_chats/chat_join_request.py index 88ac484a..8c739c8e 100644 --- a/pyrogram/types/user_and_chats/chat_join_request.py +++ b/pyrogram/types/user_and_chats/chat_join_request.py @@ -34,12 +34,12 @@ class ChatJoinRequest(Object, Update): def __init__( self, *, - client: pyrogram.Client = None, - chat: types.Chat, - from_user: types.User, - date: datetime, + client: pyrogram.Client | None = None, + chat: types.Chat | None = None, + from_user: types.User | None = None, + date: datetime | None = None, bio: str | None = None, - invite_link: types.ChatInviteLink = None, + invite_link: types.ChatInviteLink | None = None, ) -> None: super().__init__(client) @@ -59,11 +59,13 @@ def _parse( chat_id = utils.get_raw_peer_id(update.peer) return ChatJoinRequest( - chat=types.Chat._parse_chat(client, chats[chat_id]), - from_user=types.User._parse(client, users[update.user_id]), - date=utils.timestamp_to_datetime(update.date), - bio=update.about, - invite_link=types.ChatInviteLink._parse(client, update.invite, users), + chat=types.Chat._parse_chat(client, chats.get(chat_id)), + from_user=types.User._parse(client, users.get(update.user_id)), + date=utils.timestamp_to_datetime(getattr(update, "date", None)), + bio=getattr(update, "about", None), + invite_link=types.ChatInviteLink._parse( + client, getattr(update, "invite", None), users + ), client=client, ) diff --git a/pyrogram/types/user_and_chats/chat_joiner.py b/pyrogram/types/user_and_chats/chat_joiner.py index d25343fd..0841946f 100644 --- a/pyrogram/types/user_and_chats/chat_joiner.py +++ b/pyrogram/types/user_and_chats/chat_joiner.py @@ -33,12 +33,12 @@ class ChatJoiner(Object): def __init__( self, *, - client: pyrogram.Client, - user: types.User, + client: pyrogram.Client | None = None, + user: types.User | None = None, date: datetime | None = None, bio: str | None = None, pending: bool | None = None, - approved_by: types.User = None, + approved_by: types.User | None = None, ) -> None: super().__init__(client) @@ -51,17 +51,20 @@ def __init__( @staticmethod def _parse( client: pyrogram.Client, - joiner: raw.base.ChatInviteImporter, + joiner: raw.base.ChatInviteImporter | None, users: dict[int, raw.base.User], - ) -> ChatJoiner: + ) -> ChatJoiner | None: + if not isinstance(joiner, raw.types.ChatInviteImporter): + return None + return ChatJoiner( - user=types.User._parse(client, users[joiner.user_id]), - date=utils.timestamp_to_datetime(joiner.date), - pending=joiner.requested, - bio=joiner.about, + user=types.User._parse(client, users.get(joiner.user_id)), + date=utils.timestamp_to_datetime(getattr(joiner, "date", None)), + pending=getattr(joiner, "requested", None), + bio=getattr(joiner, "about", None), approved_by=( - types.User._parse(client, users[joiner.approved_by]) - if joiner.approved_by + types.User._parse(client, users.get(joiner.approved_by)) + if getattr(joiner, "approved_by", None) else None ), client=client, diff --git a/pyrogram/types/user_and_chats/chat_member.py b/pyrogram/types/user_and_chats/chat_member.py index dd72f956..2434a4e7 100644 --- a/pyrogram/types/user_and_chats/chat_member.py +++ b/pyrogram/types/user_and_chats/chat_member.py @@ -1,6 +1,6 @@ from __future__ import annotations -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, Any import pyrogram from pyrogram import enums, raw, types, utils @@ -62,20 +62,20 @@ class ChatMember(Object): def __init__( self, *, - client: pyrogram.Client = None, + client: pyrogram.Client | None = None, status: enums.ChatMemberStatus, - user: types.User = None, - chat: types.Chat = None, + user: types.User | None = None, + chat: types.Chat | None = None, custom_title: str | None = None, until_date: datetime | None = None, joined_date: datetime | None = None, - invited_by: types.User = None, - promoted_by: types.User = None, - restricted_by: types.User = None, + invited_by: types.User | None = None, + promoted_by: types.User | None = None, + restricted_by: types.User | None = None, is_member: bool | None = None, can_be_edited: bool | None = None, - permissions: types.ChatPermissions = None, - privileges: types.ChatPrivileges = None, + permissions: types.ChatPermissions | None = None, + privileges: types.ChatPrivileges | None = None, ) -> None: super().__init__(client) @@ -96,37 +96,39 @@ def __init__( @staticmethod def _parse( client: pyrogram.Client, - member: raw.base.ChatParticipant | raw.base.ChannelParticipant, - users: dict[int, raw.base.User], - chats: dict[int, raw.base.Chat], - ) -> ChatMember: + member: raw.base.ChatParticipant | raw.base.ChannelParticipant | None, + users: dict[int, Any], + chats: dict[int, Any], + ) -> ChatMember | None: + if member is None: + return None if isinstance(member, raw.types.ChatParticipant): return ChatMember( status=enums.ChatMemberStatus.MEMBER, - user=types.User._parse(client, users[member.user_id]), + user=types.User._parse(client, users.get(member.user_id)), joined_date=utils.timestamp_to_datetime(member.date), - invited_by=types.User._parse(client, users[member.inviter_id]), + invited_by=types.User._parse(client, users.get(member.inviter_id)), client=client, ) if isinstance(member, raw.types.ChatParticipantAdmin): return ChatMember( status=enums.ChatMemberStatus.ADMINISTRATOR, - user=types.User._parse(client, users[member.user_id]), + user=types.User._parse(client, users.get(member.user_id)), joined_date=utils.timestamp_to_datetime(member.date), - invited_by=types.User._parse(client, users[member.inviter_id]), + invited_by=types.User._parse(client, users.get(member.inviter_id)), client=client, ) if isinstance(member, raw.types.ChatParticipantCreator): return ChatMember( status=enums.ChatMemberStatus.OWNER, - user=types.User._parse(client, users[member.user_id]), + user=types.User._parse(client, users.get(member.user_id)), client=client, ) if isinstance(member, raw.types.ChannelParticipant): return ChatMember( status=enums.ChatMemberStatus.MEMBER, - user=types.User._parse(client, users[member.user_id]), + user=types.User._parse(client, users.get(member.user_id)), joined_date=utils.timestamp_to_datetime(member.date), until_date=utils.timestamp_to_datetime( member.subscription_until_date, @@ -136,11 +138,11 @@ def _parse( if isinstance(member, raw.types.ChannelParticipantAdmin): return ChatMember( status=enums.ChatMemberStatus.ADMINISTRATOR, - user=types.User._parse(client, users[member.user_id]), + user=types.User._parse(client, users.get(member.user_id)), joined_date=utils.timestamp_to_datetime(member.date), promoted_by=types.User._parse(client, users[member.promoted_by]), invited_by=( - types.User._parse(client, users[member.inviter_id]) + types.User._parse(client, users.get(member.inviter_id)) if member.inviter_id else None ), @@ -154,13 +156,13 @@ def _parse( peer_id = utils.get_raw_peer_id(peer) user = ( - types.User._parse(client, users[peer_id]) + types.User._parse(client, users.get(peer_id or 0)) if isinstance(peer, raw.types.PeerUser) else None ) chat = ( - types.Chat._parse_chat(client, chats[peer_id]) + types.Chat._parse_chat(client, chats.get(peer_id or 0)) if not isinstance(peer, raw.types.PeerUser) else None ) @@ -168,24 +170,24 @@ def _parse( return ChatMember( status=( enums.ChatMemberStatus.BANNED - if member.banned_rights.view_messages + if getattr(member.banned_rights, "view_messages", False) else enums.ChatMemberStatus.RESTRICTED ), user=user, chat=chat, until_date=utils.timestamp_to_datetime( - member.banned_rights.until_date, + getattr(member.banned_rights, "until_date", None), ), joined_date=utils.timestamp_to_datetime(member.date), is_member=not member.left, - restricted_by=types.User._parse(client, users[member.kicked_by]), + restricted_by=types.User._parse(client, users.get(member.kicked_by)), permissions=types.ChatPermissions._parse(member.banned_rights), client=client, ) if isinstance(member, raw.types.ChannelParticipantCreator): return ChatMember( status=enums.ChatMemberStatus.OWNER, - user=types.User._parse(client, users[member.user_id]), + user=types.User._parse(client, users.get(member.user_id)), custom_title=member.rank, privileges=types.ChatPrivileges._parse(member.admin_rights), client=client, @@ -195,13 +197,13 @@ def _parse( peer_id = utils.get_raw_peer_id(peer) user = ( - types.User._parse(client, users[peer_id]) + types.User._parse(client, users.get(peer_id or 0)) if isinstance(peer, raw.types.PeerUser) else None ) chat = ( - types.Chat._parse_chat(client, chats[peer_id]) + types.Chat._parse_chat(client, chats.get(peer_id or 0)) if not isinstance(peer, raw.types.PeerUser) else None ) @@ -215,9 +217,9 @@ def _parse( if isinstance(member, raw.types.ChannelParticipantSelf): return ChatMember( status=enums.ChatMemberStatus.MEMBER, - user=types.User._parse(client, users[member.user_id]), + user=types.User._parse(client, users.get(member.user_id)), joined_date=utils.timestamp_to_datetime(member.date), - invited_by=types.User._parse(client, users[member.inviter_id]), + invited_by=types.User._parse(client, users.get(member.inviter_id)), until_date=utils.timestamp_to_datetime( member.subscription_until_date, ), diff --git a/pyrogram/types/user_and_chats/chat_member_updated.py b/pyrogram/types/user_and_chats/chat_member_updated.py index ec8af6c9..6dcc806d 100644 --- a/pyrogram/types/user_and_chats/chat_member_updated.py +++ b/pyrogram/types/user_and_chats/chat_member_updated.py @@ -43,16 +43,16 @@ class ChatMemberUpdated(Object, Update): def __init__( self, *, - client: pyrogram.Client = None, - chat: types.Chat, - from_user: types.User, - date: datetime, - old_chat_member: types.ChatMember, - new_chat_member: types.ChatMember, - invite_link: types.ChatInviteLink = None, + client: pyrogram.Client | None = None, + chat: types.Chat | None = None, + from_user: types.User | None = None, + date: datetime | None = None, + old_chat_member: types.ChatMember | None = None, + new_chat_member: types.ChatMember | None = None, + invite_link: types.ChatInviteLink | None = None, via_join_request: bool | None = None, via_chat_folder_invite_link: bool = False, - _raw: raw.base.Update = None, + _raw: raw.base.Update | None = None, ) -> None: super().__init__(client) @@ -105,7 +105,7 @@ def _parse( client=client, ) - chat_id = getattr(update, "chat_id", None) or update.channel_id + chat_id = getattr(update, "chat_id", 0) or getattr(update, "channel_id", 0) old_chat_member = None new_chat_member = None @@ -134,9 +134,9 @@ def _parse( via_join_request = True return ChatMemberUpdated( - chat=types.Chat._parse_chat(client, chats[chat_id]), - from_user=types.User._parse(client, users[update.actor_id]), - date=utils.timestamp_to_datetime(update.date), + chat=types.Chat._parse_chat(client, chats.get(chat_id)), + from_user=types.User._parse(client, users.get(update.actor_id)), + date=utils.timestamp_to_datetime(getattr(update, "date", None)), old_chat_member=old_chat_member, new_chat_member=new_chat_member, invite_link=invite_link, diff --git a/pyrogram/types/user_and_chats/chat_permissions.py b/pyrogram/types/user_and_chats/chat_permissions.py index 714c005b..48717aa2 100644 --- a/pyrogram/types/user_and_chats/chat_permissions.py +++ b/pyrogram/types/user_and_chats/chat_permissions.py @@ -147,8 +147,8 @@ def __init__( @staticmethod def _parse( - denied_permissions: raw.base.ChatBannedRights, - ) -> ChatPermissions: + denied_permissions: raw.base.ChatBannedRights | None, + ) -> ChatPermissions | None: if isinstance(denied_permissions, raw.types.ChatBannedRights): all_permissions = None all_params = [ diff --git a/pyrogram/types/user_and_chats/chat_photo.py b/pyrogram/types/user_and_chats/chat_photo.py index dd9f8eee..2b0561ad 100644 --- a/pyrogram/types/user_and_chats/chat_photo.py +++ b/pyrogram/types/user_and_chats/chat_photo.py @@ -46,14 +46,14 @@ class ChatPhoto(Object): def __init__( self, *, - client: pyrogram.Client = None, + client: pyrogram.Client | None = None, small_file_id: str, small_photo_unique_id: str, big_file_id: str, big_photo_unique_id: str, has_animation: bool, is_personal: bool, - minithumbnail: types.StrippedThumbnail = None, + minithumbnail: types.StrippedThumbnail | None = None, ) -> None: super().__init__(client) @@ -68,7 +68,7 @@ def __init__( @staticmethod def _parse( client, - chat_photo: raw.types.UserProfilePhoto | raw.types.ChatPhoto, + chat_photo: raw.types.UserProfilePhoto | raw.types.ChatPhoto | None, peer_id: int, peer_access_hash: int, ): @@ -109,7 +109,7 @@ def _parse( file_unique_type=FileUniqueType.DOCUMENT, media_id=chat_photo.photo_id, ).encode(), - has_animation=chat_photo.has_video, + has_animation=bool(getattr(chat_photo, "has_video", False)), is_personal=getattr(chat_photo, "personal", False), minithumbnail=types.StrippedThumbnail(data=chat_photo.stripped_thumb) if chat_photo.stripped_thumb diff --git a/pyrogram/types/user_and_chats/chat_preview.py b/pyrogram/types/user_and_chats/chat_preview.py index cc571ae2..8c50c42a 100644 --- a/pyrogram/types/user_and_chats/chat_preview.py +++ b/pyrogram/types/user_and_chats/chat_preview.py @@ -28,11 +28,11 @@ class ChatPreview(Object): def __init__( self, *, - client: pyrogram.Client = None, + client: pyrogram.Client | None = None, title: str, type: str, members_count: int, - photo: types.Photo = None, + photo: types.Photo | None = None, members: list[types.User] | None = None, ) -> None: super().__init__(client) @@ -55,9 +55,16 @@ def _parse(client, chat_invite: raw.types.ChatInvite) -> ChatPreview: else "supergroup" ), members_count=chat_invite.participants_count, - photo=types.Photo._parse(client, chat_invite.photo), + photo=types.Photo._parse(client, chat_invite.photo) + if isinstance(chat_invite.photo, raw.types.Photo) + else None, members=[ - types.User._parse(client, user) for user in chat_invite.participants + u + for u in [ + types.User._parse(client, user) + for user in (chat_invite.participants or []) + ] + if u ] or None, client=client, diff --git a/pyrogram/types/user_and_chats/chat_privileges.py b/pyrogram/types/user_and_chats/chat_privileges.py index 5d076316..e7b67897 100644 --- a/pyrogram/types/user_and_chats/chat_privileges.py +++ b/pyrogram/types/user_and_chats/chat_privileges.py @@ -1,12 +1,8 @@ from __future__ import annotations -from typing import TYPE_CHECKING - +from pyrogram import raw from pyrogram.types.object import Object -if TYPE_CHECKING: - from pyrogram import raw - class ChatPrivileges(Object): """Describes privileged actions an administrator is able to take in a chat. @@ -114,23 +110,26 @@ def __init__( @staticmethod def _parse( - admin_rights: raw.base.ChatAdminRights, - ) -> ChatPrivileges: + admin_rights: raw.base.ChatAdminRights | None, + ) -> ChatPrivileges | None: + if not isinstance(admin_rights, raw.types.ChatAdminRights): + return None + return ChatPrivileges( - can_manage_chat=admin_rights.other, - can_delete_messages=admin_rights.delete_messages, - can_manage_video_chats=admin_rights.manage_call, - can_restrict_members=admin_rights.ban_users, - can_promote_members=admin_rights.add_admins, - can_change_info=admin_rights.change_info, - can_post_messages=admin_rights.post_messages, - can_edit_messages=admin_rights.edit_messages, - can_invite_users=admin_rights.invite_users, - can_pin_messages=admin_rights.pin_messages, - can_manage_topics=admin_rights.manage_topics, - can_post_stories=admin_rights.post_stories, - can_edit_stories=admin_rights.edit_stories, - can_delete_stories=admin_rights.delete_stories, - can_manage_direct_messages=admin_rights.manage_direct_messages, - is_anonymous=admin_rights.anonymous, + can_manage_chat=bool(admin_rights.other), + can_delete_messages=bool(admin_rights.delete_messages), + can_manage_video_chats=bool(admin_rights.manage_call), + can_restrict_members=bool(admin_rights.ban_users), + can_promote_members=bool(admin_rights.add_admins), + can_change_info=bool(admin_rights.change_info), + can_post_messages=bool(admin_rights.post_messages), + can_edit_messages=bool(admin_rights.edit_messages), + can_invite_users=bool(admin_rights.invite_users), + can_pin_messages=bool(admin_rights.pin_messages), + can_manage_topics=bool(admin_rights.manage_topics), + can_post_stories=bool(admin_rights.post_stories), + can_edit_stories=bool(admin_rights.edit_stories), + can_delete_stories=bool(admin_rights.delete_stories), + can_manage_direct_messages=bool(admin_rights.manage_direct_messages), + is_anonymous=bool(admin_rights.anonymous), ) diff --git a/pyrogram/types/user_and_chats/chat_reactions.py b/pyrogram/types/user_and_chats/chat_reactions.py index 61778be2..da50cf07 100644 --- a/pyrogram/types/user_and_chats/chat_reactions.py +++ b/pyrogram/types/user_and_chats/chat_reactions.py @@ -24,10 +24,10 @@ class ChatReactions(Object): def __init__( self, *, - client: pyrogram.Client = None, + client: pyrogram.Client | None = None, all_are_enabled: bool | None = None, allow_custom_emoji: bool | None = None, - reactions: list[types.Reaction] | None = None, + reactions: list[types.ReactionType] | None = None, max_reaction_count: int = 11, ) -> None: super().__init__(client) @@ -40,7 +40,7 @@ def __init__( @staticmethod def _parse( client, - chat_reactions: raw.base.ChatReactions, + chat_reactions: raw.base.ChatReactions | None, reactions_limit: int = 11, ) -> ChatReactions | None: if isinstance(chat_reactions, raw.types.ChatReactionsAll): @@ -55,8 +55,12 @@ def _parse( return ChatReactions( client=client, reactions=[ - types.ReactionType._parse(client, reaction) - for reaction in chat_reactions.reactions + r + for r in [ + types.ReactionType._parse(client, reaction) + for reaction in chat_reactions.reactions + ] + if r ], max_reaction_count=reactions_limit, ) diff --git a/pyrogram/types/user_and_chats/dialog.py b/pyrogram/types/user_and_chats/dialog.py index a6749e5e..0bf42703 100644 --- a/pyrogram/types/user_and_chats/dialog.py +++ b/pyrogram/types/user_and_chats/dialog.py @@ -49,19 +49,19 @@ class Dialog(Object): def __init__( self, *, - client: pyrogram.Client = None, - chat: types.Chat, - top_message: types.Message, - unread_messages_count: int, - unread_mentions_count: int, - unread_reactions_count: int, - unread_mark: bool, - is_pinned: bool, - chat_list: int, - message_auto_delete_time: int, - view_as_topics: bool, - draft: types.DraftMessage = None, - _raw: raw.types.Dialog = None, + client: pyrogram.Client | None = None, + chat: types.Chat | None = None, + top_message: types.Message | None = None, + unread_messages_count: int | None = None, + unread_mentions_count: int | None = None, + unread_reactions_count: int | None = None, + unread_mark: bool | None = None, + is_pinned: bool | None = None, + chat_list: int | None = None, + message_auto_delete_time: int | None = None, + view_as_topics: bool | None = None, + draft: types.DraftMessage | None = None, + _raw: raw.types.Dialog | None = None, ) -> None: super().__init__(client) @@ -83,15 +83,19 @@ def _parse(client, dialog: raw.types.Dialog, messages, users, chats) -> Dialog: return Dialog( chat=types.Chat._parse_dialog(client, dialog.peer, users, chats), top_message=messages.get(utils.get_peer_id(dialog.peer)), - unread_messages_count=dialog.unread_count, - unread_mentions_count=dialog.unread_mentions_count, - unread_reactions_count=dialog.unread_reactions_count, - unread_mark=dialog.unread_mark, - is_pinned=dialog.pinned, + unread_messages_count=getattr(dialog, "unread_count", None), + unread_mentions_count=getattr(dialog, "unread_mentions_count", None), + unread_reactions_count=getattr(dialog, "unread_reactions_count", None), + unread_mark=getattr(dialog, "unread_mark", None), + is_pinned=getattr(dialog, "pinned", None), chat_list=getattr(dialog, "folder_id", None), message_auto_delete_time=getattr(dialog, "ttl_period", 0), - view_as_topics=not dialog.view_forum_as_messages, + view_as_topics=not getattr(dialog, "view_forum_as_messages", True), client=client, - draft=types.DraftMessage._parse(client, dialog.draft, users, chats), + draft=types.DraftMessage._parse(client, dialog.draft, users) + if isinstance( + dialog.draft, (raw.types.DraftMessage, raw.types.DraftMessageEmpty) + ) + else None, _raw=dialog, ) diff --git a/pyrogram/types/user_and_chats/emoji_status.py b/pyrogram/types/user_and_chats/emoji_status.py index d6bea128..6f7cd721 100644 --- a/pyrogram/types/user_and_chats/emoji_status.py +++ b/pyrogram/types/user_and_chats/emoji_status.py @@ -24,10 +24,10 @@ class EmojiStatus(Object): def __init__( self, *, - client: pyrogram.Client = None, + client: pyrogram.Client | None = None, custom_emoji_id: int, until_date: datetime | None = None, - _raw: raw.base.EmojiStatus = None, + _raw: raw.base.EmojiStatus | None = None, ) -> None: super().__init__(client) @@ -35,7 +35,9 @@ def __init__( self.until_date = until_date @staticmethod - def _parse(client, emoji_status: raw.base.EmojiStatus) -> EmojiStatus | None: + def _parse( + client, emoji_status: raw.base.EmojiStatus | None + ) -> EmojiStatus | None: if isinstance(emoji_status, raw.types.EmojiStatus): return EmojiStatus( client=client, @@ -59,10 +61,9 @@ def _parse(client, emoji_status: raw.base.EmojiStatus) -> EmojiStatus | None: return None def write(self): - if self.until_date: - return raw.types.EmojiStatusUntil( - document_id=self.custom_emoji_id, - until=utils.datetime_to_timestamp(self.until_date), - ) - - return raw.types.EmojiStatus(document_id=self.custom_emoji_id) + return raw.types.EmojiStatus( + document_id=self.custom_emoji_id, + until=utils.datetime_to_timestamp(self.until_date) + if self.until_date + else None, + ) diff --git a/pyrogram/types/user_and_chats/folder.py b/pyrogram/types/user_and_chats/folder.py index ac1fa5d8..0843f98b 100644 --- a/pyrogram/types/user_and_chats/folder.py +++ b/pyrogram/types/user_and_chats/folder.py @@ -60,9 +60,9 @@ class Folder(Object): def __init__( self, *, - client: pyrogram.Client = None, - id: int, - title: str, + client: pyrogram.Client | None = None, + id: int | None = None, + title: str | None = None, included_chats: list[types.Chat] | None = None, excluded_chats: list[types.Chat] | None = None, pinned_chats: list[types.Chat] | None = None, @@ -75,7 +75,7 @@ def __init__( exclude_read: bool | None = None, exclude_archived: bool | None = None, emoji: str | None = None, - color: enums.FolderColor = None, + color: enums.FolderColor | None = None, has_my_invites: bool | None = None, ) -> None: super().__init__(client) @@ -98,7 +98,17 @@ def __init__( self.has_my_invites = has_my_invites @staticmethod - def _parse(client, folder: raw.types.DialogFilter, users, chats) -> Folder: + def _parse( + client, folder: raw.base.DialogFilter | None, users: dict, chats: dict + ) -> Folder | None: + if not isinstance( + folder, (raw.types.DialogFilter, raw.types.DialogFilterDefault) + ): + return None + + if isinstance(folder, raw.types.DialogFilterDefault): + return Folder(id=0, title="All", client=client) + included_chats = [] excluded_chats = [] pinned_chats = [] @@ -124,7 +134,7 @@ def _parse(client, folder: raw.types.DialogFilter, users, chats) -> Folder: return Folder( id=folder.id, - title=folder.title, + title=str(folder.title), included_chats=types.List(included_chats) or None, excluded_chats=types.List(excluded_chats) or None, pinned_chats=types.List(pinned_chats) or None, @@ -160,7 +170,7 @@ async def delete(self): True on success. """ - return await self._client.delete_folder(self.id) + return await self._client.delete_folder(self.id or 0) async def update( self, @@ -177,7 +187,7 @@ async def update( exclude_read: bool | None = None, exclude_archived: bool | None = None, emoji: str | None = None, - color: enums.FolderColor = None, + color: enums.FolderColor | None = None, ): """Bound method *update_peers* of :obj:`~pyrogram.types.Folder`. @@ -257,8 +267,8 @@ async def update( pinned_chats = [i.id for i in self.pinned_chats or []] return await self._client.update_folder( - folder_id=self.id, - title=title or self.title, + folder_id=self.id or 0, + title=title or self.title or "", included_chats=included_chats, excluded_chats=excluded_chats, pinned_chats=pinned_chats, @@ -436,17 +446,33 @@ async def remove_chat(self, chat_id: int | str): Returns: True on success. """ + assert self._client peer = await self._client.resolve_peer(chat_id) - peer_id = utils.get_peer_id(peer) + if isinstance(peer, raw.types.InputPeerUser): + peer_id = peer.user_id + elif isinstance(peer, raw.types.InputPeerChat): + peer_id = -peer.chat_id + elif isinstance(peer, raw.types.InputPeerChannel): + peer_id = utils.get_channel_id(peer.channel_id) + else: + peer_id = 0 return await self.update( included_chats=[ - i.id for i in self.included_chats or [] if peer_id != i.id + getattr(i, "id", 0) + for i in self.included_chats or [] + if peer_id != getattr(i, "id", 0) ], excluded_chats=[ - i.id for i in self.excluded_chats or [] if peer_id != i.id + getattr(i, "id", 0) + for i in self.excluded_chats or [] + if peer_id != getattr(i, "id", 0) + ], + pinned_chats=[ + getattr(i, "id", 0) + for i in self.pinned_chats or [] + if peer_id != getattr(i, "id", 0) ], - pinned_chats=[i.id for i in self.pinned_chats or [] if peer_id != i.id], ) async def export_link(self): @@ -467,4 +493,4 @@ async def export_link(self): ``str``: On success, a link to the folder as string is returned. """ - return await self._client.export_folder_link(folder_id=self.id) + return await self._client.export_folder_link(folder_id=self.id or 0) diff --git a/pyrogram/types/user_and_chats/forum_topic.py b/pyrogram/types/user_and_chats/forum_topic.py index a9c3c0ef..2a095ba6 100644 --- a/pyrogram/types/user_and_chats/forum_topic.py +++ b/pyrogram/types/user_and_chats/forum_topic.py @@ -62,17 +62,17 @@ class ForumTopic(Object): def __init__( self, *, - id: int, - date: int, - title: str, - icon_color: int, - top_message: int, - read_inbox_max_id: int, - read_outbox_max_id: int, - unread_count: int, - unread_mentions_count: int, - unread_reactions_count: int, - from_id: types.PeerChannel | types.PeerUser, + id: int | None = None, + date: int | None = None, + title: str | None = None, + icon_color: int | None = None, + top_message: int | None = None, + read_inbox_max_id: int | None = None, + read_outbox_max_id: int | None = None, + unread_count: int | None = None, + unread_mentions_count: int | None = None, + unread_reactions_count: int | None = None, + from_id: types.PeerChannel | types.PeerUser | None = None, my: bool | None = None, closed: bool | None = None, pinned: bool | None = None, @@ -99,8 +99,12 @@ def __init__( self.icon_emoji_id = icon_emoji_id @staticmethod - def _parse(forum_topic: raw.types.forum_topic) -> ForumTopic: + def _parse(forum_topic: raw.base.ForumTopic | None) -> ForumTopic | None: + if not isinstance(forum_topic, raw.types.ForumTopic): + return None + from_id = forum_topic.from_id + peer = None if isinstance(from_id, raw.types.PeerChannel): peer = types.PeerChannel._parse(from_id) if isinstance(from_id, raw.types.PeerUser): diff --git a/pyrogram/types/user_and_chats/forum_topic_created.py b/pyrogram/types/user_and_chats/forum_topic_created.py index 48cff8be..7c6319e7 100644 --- a/pyrogram/types/user_and_chats/forum_topic_created.py +++ b/pyrogram/types/user_and_chats/forum_topic_created.py @@ -1,12 +1,8 @@ from __future__ import annotations -from typing import TYPE_CHECKING - +from pyrogram import raw from pyrogram.types.object import Object -if TYPE_CHECKING: - from pyrogram import raw - class ForumTopicCreated(Object): """A service message about a new forum topic created in the chat. @@ -29,9 +25,9 @@ class ForumTopicCreated(Object): def __init__( self, *, - id: int, - title: str, - icon_color: int, + id: int | None = None, + title: str | None = None, + icon_color: int | None = None, icon_emoji_id: int | None = None, ) -> None: super().__init__() @@ -42,7 +38,10 @@ def __init__( self.icon_emoji_id = icon_emoji_id @staticmethod - def _parse(message: raw.base.Message) -> ForumTopicCreated: + def _parse(message: raw.base.Message | None) -> ForumTopicCreated | None: + if not isinstance(message, raw.types.MessageService): + return None + return ForumTopicCreated( id=getattr(message, "id", None), title=getattr(message.action, "title", None), diff --git a/pyrogram/types/user_and_chats/found_contacts.py b/pyrogram/types/user_and_chats/found_contacts.py index 4b568acc..d5701f9a 100644 --- a/pyrogram/types/user_and_chats/found_contacts.py +++ b/pyrogram/types/user_and_chats/found_contacts.py @@ -18,9 +18,9 @@ class FoundContacts(Object): def __init__( self, *, - client: pyrogram.Client = None, - my_results: types.Chat | None = None, - global_results: types.Chat | None = None, + client: pyrogram.Client | None = None, + my_results: list[types.Chat] | None = None, + global_results: list[types.Chat] | None = None, ) -> None: super().__init__(client) @@ -29,8 +29,8 @@ def __init__( @staticmethod def _parse(client, found: raw.types.contacts.Found) -> FoundContacts: - users = {u.id: u for u in found.users} - chats = {c.id: c for c in found.chats} + users = {getattr(u, "id", 0): u for u in found.users} + chats = {getattr(c, "id", 0): c for c in found.chats} my_results = [] global_results = [] @@ -39,13 +39,15 @@ def _parse(client, found: raw.types.contacts.Found) -> FoundContacts: peer_id = utils.get_raw_peer_id(result) peer = users.get(peer_id) or chats.get(peer_id) - my_results.append(types.Chat._parse_chat(client, peer)) + if isinstance(peer, (raw.types.Chat, raw.types.User, raw.types.Channel)): + my_results.append(types.Chat._parse_chat(client, peer)) for result in found.results: peer_id = utils.get_raw_peer_id(result) peer = users.get(peer_id) or chats.get(peer_id) - global_results.append(types.Chat._parse_chat(client, peer)) + if isinstance(peer, (raw.types.Chat, raw.types.User, raw.types.Channel)): + global_results.append(types.Chat._parse_chat(client, peer)) return FoundContacts( my_results=types.List(my_results) or None, diff --git a/pyrogram/types/user_and_chats/invite_link_importer.py b/pyrogram/types/user_and_chats/invite_link_importer.py index b8355680..e8515344 100644 --- a/pyrogram/types/user_and_chats/invite_link_importer.py +++ b/pyrogram/types/user_and_chats/invite_link_importer.py @@ -20,7 +20,9 @@ class InviteLinkImporter(Object): The user that has used the given invite link """ - def __init__(self, *, date: datetime, user: types.User) -> None: + def __init__( + self, *, date: datetime | None = None, user: types.User | None = None + ) -> None: super().__init__(None) self.date = date @@ -33,13 +35,15 @@ def _parse( ): importers = types.List() - d = {i.id: i for i in invite_importers.users} + d = {getattr(i, "id", 0): i for i in invite_importers.users} for j in invite_importers.importers: importers.append( InviteLinkImporter( - date=utils.timestamp_to_datetime(j.date), - user=types.User._parse(client=None, user=d[j.user_id]), + date=utils.timestamp_to_datetime(getattr(j, "date", None)), + user=types.User._parse( + client=None, user=d.get(getattr(j, "user_id", 0)) + ), ), ) diff --git a/pyrogram/types/user_and_chats/peer_channel.py b/pyrogram/types/user_and_chats/peer_channel.py index 0a0be83b..07fa02f2 100644 --- a/pyrogram/types/user_and_chats/peer_channel.py +++ b/pyrogram/types/user_and_chats/peer_channel.py @@ -17,11 +17,14 @@ class PeerChannel(Object): Id of the channel. """ - def __init__(self, *, channel_id: int) -> None: + def __init__(self, *, channel_id: int | None = None) -> None: super().__init__() self.channel_id = channel_id @staticmethod - def _parse(action: raw.types.PeerChannel) -> PeerChannel: + def _parse(action: raw.types.PeerChannel | None) -> PeerChannel | None: + if not action: + return None + return PeerChannel(channel_id=getattr(action, "channel_id", None)) diff --git a/pyrogram/types/user_and_chats/peer_user.py b/pyrogram/types/user_and_chats/peer_user.py index 878fc00c..55403459 100644 --- a/pyrogram/types/user_and_chats/peer_user.py +++ b/pyrogram/types/user_and_chats/peer_user.py @@ -17,11 +17,14 @@ class PeerUser(Object): Id of the user. """ - def __init__(self, *, user_id: int) -> None: + def __init__(self, *, user_id: int | None = None) -> None: super().__init__() self.user_id = user_id @staticmethod - def _parse(action: raw.types.PeerUser) -> PeerUser: + def _parse(action: raw.types.PeerUser | None) -> PeerUser | None: + if not action: + return None + return PeerUser(user_id=getattr(action, "user_id", None)) diff --git a/pyrogram/types/user_and_chats/restriction.py b/pyrogram/types/user_and_chats/restriction.py index 18c5f3f2..cf293598 100644 --- a/pyrogram/types/user_and_chats/restriction.py +++ b/pyrogram/types/user_and_chats/restriction.py @@ -1,12 +1,8 @@ from __future__ import annotations -from typing import TYPE_CHECKING - +from pyrogram import raw from pyrogram.types.object import Object -if TYPE_CHECKING: - from pyrogram import raw - class Restriction(Object): """A restriction applied to bots or chats. @@ -31,8 +27,11 @@ def __init__(self, *, platform: str, reason: str, text: str) -> None: @staticmethod def _parse( - restriction: raw.types.RestrictionReason, - ) -> Restriction: + restriction: raw.base.RestrictionReason | None, + ) -> Restriction | None: + if not isinstance(restriction, raw.types.RestrictionReason): + return None + return Restriction( platform=restriction.platform, reason=restriction.reason, diff --git a/pyrogram/types/user_and_chats/user.py b/pyrogram/types/user_and_chats/user.py index 747faac7..cabeb5ae 100644 --- a/pyrogram/types/user_and_chats/user.py +++ b/pyrogram/types/user_and_chats/user.py @@ -24,19 +24,21 @@ def __init__(self, url: str, text: str, style: enums.ParseMode) -> None: self.style = style @staticmethod - def format(url: str, text: str, style: enums.ParseMode): + def _format(url: str, text: str, style: enums.ParseMode): fmt = Link.MARKDOWN if style == enums.ParseMode.MARKDOWN else Link.HTML return fmt.format(url=url, text=html.escape(text)) def __new__(cls, url, text, style): - return str.__new__(cls, Link.format(url, text, style)) + return str.__new__(cls, Link._format(url, text, style)) - def __call__(self, other: str | None = None, *, style: str | None = None): - return Link.format(self.url, other or self.text, style or self.style) + def __call__( + self, other: str | None = None, *, style: enums.ParseMode | None = None + ): + return Link._format(self.url, other or self.text, style or self.style) def __str__(self) -> str: - return Link.format(self.url, self.text, self.style) + return Link._format(self.url, self.text, self.style) class User(Object, Update): @@ -179,7 +181,7 @@ class User(Object, Update): def __init__( self, *, - client: pyrogram.Client = None, + client: pyrogram.Client | None = None, id: int, is_self: bool | None = None, is_contact: bool | None = None, @@ -203,7 +205,7 @@ def __init__( is_bot_forum_can_manage_topics: bool | None = None, first_name: str | None = None, last_name: str | None = None, - status: enums.UserStatus = None, + status: enums.UserStatus | None = None, last_online_date: datetime | None = None, next_offline_date: datetime | None = None, username: str | None = None, @@ -212,10 +214,10 @@ def __init__( emoji_status: types.EmojiStatus | None = None, dc_id: int | None = None, phone_number: str | None = None, - photo: types.ChatPhoto = None, + photo: types.ChatPhoto | None = None, restrictions: list[types.Restriction] | None = None, - reply_color: types.ChatColor = None, - profile_color: types.ChatColor = None, + reply_color: types.ChatColor | None = None, + profile_color: types.ChatColor | None = None, active_users: int | None = None, bot_verification_icon: int | None = None, send_paid_messages_stars: int | None = None, @@ -263,7 +265,7 @@ def __init__( self.send_paid_messages_stars = send_paid_messages_stars @property - def full_name(self) -> str: + def full_name(self) -> str | None: return " ".join(filter(None, [self.first_name, self.last_name])) or None @property @@ -271,12 +273,12 @@ def mention(self): return Link( f"tg://user?id={self.id}", self.first_name or "Deleted Account", - self._client.parse_mode, + self._client.parse_mode or enums.ParseMode.DEFAULT, ) @staticmethod - def _parse(client, user: raw.base.User) -> User | None: - if user is None or isinstance(user, raw.types.UserEmpty): + def _parse(client, user: raw.base.User | None) -> User | None: + if not isinstance(user, raw.types.User): return None user_name = user.username active_usernames = getattr(user, "usernames", []) @@ -321,23 +323,36 @@ def _parse(client, user: raw.base.User) -> User | None: ), first_name=user.first_name, last_name=user.last_name, - **User._parse_status(user.status, user.bot), + **User._parse_status( + getattr(user, "status", None), bool(getattr(user, "bot", None)) + ), username=user_name, usernames=usernames, language_code=user.lang_code, - emoji_status=types.EmojiStatus._parse(client, user.emoji_status), + emoji_status=types.EmojiStatus._parse( + client, getattr(user, "emoji_status", None) + ), dc_id=getattr(user.photo, "dc_id", None), phone_number=user.phone, photo=types.ChatPhoto._parse( client, user.photo, user.id, - user.access_hash, - ), + user.access_hash or 0, + ) + if isinstance( + user.photo, (raw.types.UserProfilePhoto, raw.types.ChatPhoto) + ) + else None, restrictions=types.List( - [types.Restriction._parse(r) for r in user.restriction_reason], + [ + types.Restriction._parse(r) + for r in user.restriction_reason + if isinstance(r, raw.types.RestrictionReason) + ], ) - or None, + if user.restriction_reason + else None, reply_color=types.ChatColor._parse(getattr(user, "color", None)), profile_color=types.ChatColor._parse_profile_color( getattr(user, "profile_color", None), @@ -349,7 +364,7 @@ def _parse(client, user: raw.base.User) -> User | None: ) @staticmethod - def _parse_status(user_status: raw.base.UserStatus, is_bot: bool = False): + def _parse_status(user_status: raw.base.UserStatus | None, is_bot: bool = False): if isinstance(user_status, raw.types.UserStatusOnline): status, date = ( enums.UserStatus.ONLINE, diff --git a/pyrogram/types/user_and_chats/username.py b/pyrogram/types/user_and_chats/username.py index dbc140e1..724aab4e 100644 --- a/pyrogram/types/user_and_chats/username.py +++ b/pyrogram/types/user_and_chats/username.py @@ -39,7 +39,7 @@ def __init__( @staticmethod def _parse(action: raw.types.Username) -> Username: return Username( - username=getattr(action, "username", None), - editable=getattr(action, "editable", None), - active=getattr(action, "active", None), + username=action.username, + editable=action.editable, + active=action.active, ) diff --git a/pyrogram/types/user_and_chats/video_chat_ended.py b/pyrogram/types/user_and_chats/video_chat_ended.py index 54922174..e52aa5c1 100644 --- a/pyrogram/types/user_and_chats/video_chat_ended.py +++ b/pyrogram/types/user_and_chats/video_chat_ended.py @@ -16,7 +16,7 @@ class VideoChatEnded(Object): Voice chat duration; in seconds. """ - def __init__(self, *, duration: int) -> None: + def __init__(self, *, duration: int | None = None) -> None: super().__init__() self.duration = duration diff --git a/pyrogram/types/user_and_chats/video_chat_members_invited.py b/pyrogram/types/user_and_chats/video_chat_members_invited.py index df20d5ea..6e32d3aa 100644 --- a/pyrogram/types/user_and_chats/video_chat_members_invited.py +++ b/pyrogram/types/user_and_chats/video_chat_members_invited.py @@ -13,7 +13,7 @@ class VideoChatMembersInvited(Object): New members that were invited to the voice chat. """ - def __init__(self, *, users: list[types.User]) -> None: + def __init__(self, *, users: list[types.User] | None = None) -> None: super().__init__() self.users = users @@ -24,6 +24,8 @@ def _parse( action: raw.types.MessageActionInviteToGroupCall, users: dict[int, raw.types.User], ) -> VideoChatMembersInvited: - users = [types.User._parse(client, users[i]) for i in action.users] + parsed_users = [ + types.User._parse(client, users.get(i)) for i in action.users + ] - return VideoChatMembersInvited(users=users) + return VideoChatMembersInvited(users=[u for u in parsed_users if u]) diff --git a/pyrogram/types/user_and_chats/video_chat_scheduled.py b/pyrogram/types/user_and_chats/video_chat_scheduled.py index 2301540d..f59f2f98 100644 --- a/pyrogram/types/user_and_chats/video_chat_scheduled.py +++ b/pyrogram/types/user_and_chats/video_chat_scheduled.py @@ -17,7 +17,7 @@ class VideoChatScheduled(Object): Point in time when the voice chat is supposed to be started by a chat administrator. """ - def __init__(self, *, start_date: datetime) -> None: + def __init__(self, *, start_date: datetime | None = None) -> None: super().__init__() self.start_date = start_date diff --git a/uv.lock b/uv.lock index 2cf890a7..ee28d885 100644 --- a/uv.lock +++ b/uv.lock @@ -706,11 +706,11 @@ wheels = [ [[package]] name = "filelock" -version = "3.23.0" +version = "3.24.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/98/f7/5e0dec5165ca52203d9f2c248db0a72dd31d6f15aad0b1e4a874f2187452/filelock-3.23.0.tar.gz", hash = "sha256:f64442f6f4707b9385049bb490be0bc48e3ab8e74ad27d4063435252917f4d4b", size = 32798, upload-time = "2026-02-14T02:53:58.703Z" } +sdist = { url = "https://files.pythonhosted.org/packages/02/a8/dae62680be63cbb3ff87cfa2f51cf766269514ea5488479d42fec5aa6f3a/filelock-3.24.2.tar.gz", hash = "sha256:c22803117490f156e59fafce621f0550a7a853e2bbf4f87f112b11d469b6c81b", size = 37601, upload-time = "2026-02-16T02:50:45.614Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/0b/10/da216e25ef2f3c9dfa75574aa27f5f4c7e5fb5540308f04e4d8c4d834ecb/filelock-3.23.0-py3-none-any.whl", hash = "sha256:4203c3f43983c7c95e4bbb68786f184f6acb7300899bf99d686bb82d526bdf62", size = 22227, upload-time = "2026-02-14T02:53:56.122Z" }, + { url = "https://files.pythonhosted.org/packages/e7/04/a94ebfb4eaaa08db56725a40de2887e95de4e8641b9e902c311bfa00aa39/filelock-3.24.2-py3-none-any.whl", hash = "sha256:667d7dc0b7d1e1064dd5f8f8e80bdac157a6482e8d2e02cd16fd3b6b33bd6556", size = 24152, upload-time = "2026-02-16T02:50:44Z" }, ] [[package]] @@ -1049,35 +1049,36 @@ wheels = [ [[package]] name = "nh3" -version = "0.3.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ca/a5/34c26015d3a434409f4d2a1cd8821a06c05238703f49283ffeb937bef093/nh3-0.3.2.tar.gz", hash = "sha256:f394759a06df8b685a4ebfb1874fb67a9cbfd58c64fc5ed587a663c0e63ec376", size = 19288, upload-time = "2025-10-30T11:17:45.948Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/5b/01/a1eda067c0ba823e5e2bb033864ae4854549e49fb6f3407d2da949106bfb/nh3-0.3.2-cp314-cp314t-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:d18957a90806d943d141cc5e4a0fefa1d77cf0d7a156878bf9a66eed52c9cc7d", size = 1419839, upload-time = "2025-10-30T11:17:09.956Z" }, - { url = "https://files.pythonhosted.org/packages/30/57/07826ff65d59e7e9cc789ef1dc405f660cabd7458a1864ab58aefa17411b/nh3-0.3.2-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45c953e57028c31d473d6b648552d9cab1efe20a42ad139d78e11d8f42a36130", size = 791183, upload-time = "2025-10-30T11:17:11.99Z" }, - { url = "https://files.pythonhosted.org/packages/af/2f/e8a86f861ad83f3bb5455f596d5c802e34fcdb8c53a489083a70fd301333/nh3-0.3.2-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2c9850041b77a9147d6bbd6dbbf13eeec7009eb60b44e83f07fcb2910075bf9b", size = 829127, upload-time = "2025-10-30T11:17:13.192Z" }, - { url = "https://files.pythonhosted.org/packages/d8/97/77aef4daf0479754e8e90c7f8f48f3b7b8725a3b8c0df45f2258017a6895/nh3-0.3.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:403c11563e50b915d0efdb622866d1d9e4506bce590ef7da57789bf71dd148b5", size = 997131, upload-time = "2025-10-30T11:17:14.677Z" }, - { url = "https://files.pythonhosted.org/packages/41/ee/fd8140e4df9d52143e89951dd0d797f5546004c6043285289fbbe3112293/nh3-0.3.2-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:0dca4365db62b2d71ff1620ee4f800c4729849906c5dd504ee1a7b2389558e31", size = 1068783, upload-time = "2025-10-30T11:17:15.861Z" }, - { url = "https://files.pythonhosted.org/packages/87/64/bdd9631779e2d588b08391f7555828f352e7f6427889daf2fa424bfc90c9/nh3-0.3.2-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:0fe7ee035dd7b2290715baf29cb27167dddd2ff70ea7d052c958dbd80d323c99", size = 994732, upload-time = "2025-10-30T11:17:17.155Z" }, - { url = "https://files.pythonhosted.org/packages/79/66/90190033654f1f28ca98e3d76b8be1194505583f9426b0dcde782a3970a2/nh3-0.3.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:a40202fd58e49129764f025bbaae77028e420f1d5b3c8e6f6fd3a6490d513868", size = 975997, upload-time = "2025-10-30T11:17:18.77Z" }, - { url = "https://files.pythonhosted.org/packages/34/30/ebf8e2e8d71fdb5a5d5d8836207177aed1682df819cbde7f42f16898946c/nh3-0.3.2-cp314-cp314t-win32.whl", hash = "sha256:1f9ba555a797dbdcd844b89523f29cdc90973d8bd2e836ea6b962cf567cadd93", size = 583364, upload-time = "2025-10-30T11:17:20.286Z" }, - { url = "https://files.pythonhosted.org/packages/94/ae/95c52b5a75da429f11ca8902c2128f64daafdc77758d370e4cc310ecda55/nh3-0.3.2-cp314-cp314t-win_amd64.whl", hash = "sha256:dce4248edc427c9b79261f3e6e2b3ecbdd9b88c267012168b4a7b3fc6fd41d13", size = 589982, upload-time = "2025-10-30T11:17:21.384Z" }, - { url = "https://files.pythonhosted.org/packages/b4/bd/c7d862a4381b95f2469704de32c0ad419def0f4a84b7a138a79532238114/nh3-0.3.2-cp314-cp314t-win_arm64.whl", hash = "sha256:019ecbd007536b67fdf76fab411b648fb64e2257ca3262ec80c3425c24028c80", size = 577126, upload-time = "2025-10-30T11:17:22.755Z" }, - { url = "https://files.pythonhosted.org/packages/b6/3e/f5a5cc2885c24be13e9b937441bd16a012ac34a657fe05e58927e8af8b7a/nh3-0.3.2-cp38-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:7064ccf5ace75825bd7bf57859daaaf16ed28660c1c6b306b649a9eda4b54b1e", size = 1431980, upload-time = "2025-10-30T11:17:25.457Z" }, - { url = "https://files.pythonhosted.org/packages/7f/f7/529a99324d7ef055de88b690858f4189379708abae92ace799365a797b7f/nh3-0.3.2-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c8745454cdd28bbbc90861b80a0111a195b0e3961b9fa2e672be89eb199fa5d8", size = 820805, upload-time = "2025-10-30T11:17:26.98Z" }, - { url = "https://files.pythonhosted.org/packages/3d/62/19b7c50ccd1fa7d0764822d2cea8f2a320f2fd77474c7a1805cb22cf69b0/nh3-0.3.2-cp38-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:72d67c25a84579f4a432c065e8b4274e53b7cf1df8f792cf846abfe2c3090866", size = 803527, upload-time = "2025-10-30T11:17:28.284Z" }, - { url = "https://files.pythonhosted.org/packages/4a/ca/f022273bab5440abff6302731a49410c5ef66b1a9502ba3fbb2df998d9ff/nh3-0.3.2-cp38-abi3-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:13398e676a14d6233f372c75f52d5ae74f98210172991f7a3142a736bd92b131", size = 1051674, upload-time = "2025-10-30T11:17:29.909Z" }, - { url = "https://files.pythonhosted.org/packages/fa/f7/5728e3b32a11daf5bd21cf71d91c463f74305938bc3eb9e0ac1ce141646e/nh3-0.3.2-cp38-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:03d617e5c8aa7331bd2659c654e021caf9bba704b109e7b2b28b039a00949fe5", size = 1004737, upload-time = "2025-10-30T11:17:31.205Z" }, - { url = "https://files.pythonhosted.org/packages/53/7f/f17e0dba0a99cee29e6cee6d4d52340ef9cb1f8a06946d3a01eb7ec2fb01/nh3-0.3.2-cp38-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f2f55c4d2d5a207e74eefe4d828067bbb01300e06e2a7436142f915c5928de07", size = 911745, upload-time = "2025-10-30T11:17:32.945Z" }, - { url = "https://files.pythonhosted.org/packages/42/0f/c76bf3dba22c73c38e9b1113b017cf163f7696f50e003404ec5ecdb1e8a6/nh3-0.3.2-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7bb18403f02b655a1bbe4e3a4696c2ae1d6ae8f5991f7cacb684b1ae27e6c9f7", size = 797184, upload-time = "2025-10-30T11:17:34.226Z" }, - { url = "https://files.pythonhosted.org/packages/08/a1/73d8250f888fb0ddf1b119b139c382f8903d8bb0c5bd1f64afc7e38dad1d/nh3-0.3.2-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6d66f41672eb4060cf87c037f760bdbc6847852ca9ef8e9c5a5da18f090abf87", size = 838556, upload-time = "2025-10-30T11:17:35.875Z" }, - { url = "https://files.pythonhosted.org/packages/d1/09/deb57f1fb656a7a5192497f4a287b0ade5a2ff6b5d5de4736d13ef6d2c1f/nh3-0.3.2-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:f97f8b25cb2681d25e2338148159447e4d689aafdccfcf19e61ff7db3905768a", size = 1006695, upload-time = "2025-10-30T11:17:37.071Z" }, - { url = "https://files.pythonhosted.org/packages/b6/61/8f4d41c4ccdac30e4b1a4fa7be4b0f9914d8314a5058472f84c8e101a418/nh3-0.3.2-cp38-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:2ab70e8c6c7d2ce953d2a58102eefa90c2d0a5ed7aa40c7e29a487bc5e613131", size = 1075471, upload-time = "2025-10-30T11:17:38.225Z" }, - { url = "https://files.pythonhosted.org/packages/b0/c6/966aec0cb4705e69f6c3580422c239205d5d4d0e50fac380b21e87b6cf1b/nh3-0.3.2-cp38-abi3-musllinux_1_2_i686.whl", hash = "sha256:1710f3901cd6440ca92494ba2eb6dc260f829fa8d9196b659fa10de825610ce0", size = 1002439, upload-time = "2025-10-30T11:17:39.553Z" }, - { url = "https://files.pythonhosted.org/packages/e2/c8/97a2d5f7a314cce2c5c49f30c6f161b7f3617960ade4bfc2fd1ee092cb20/nh3-0.3.2-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:91e9b001101fb4500a2aafe3e7c92928d85242d38bf5ac0aba0b7480da0a4cd6", size = 987439, upload-time = "2025-10-30T11:17:40.81Z" }, - { url = "https://files.pythonhosted.org/packages/0d/95/2d6fc6461687d7a171f087995247dec33e8749a562bfadd85fb5dbf37a11/nh3-0.3.2-cp38-abi3-win32.whl", hash = "sha256:169db03df90da63286e0560ea0efa9b6f3b59844a9735514a1d47e6bb2c8c61b", size = 589826, upload-time = "2025-10-30T11:17:42.239Z" }, - { url = "https://files.pythonhosted.org/packages/64/9a/1a1c154f10a575d20dd634e5697805e589bbdb7673a0ad00e8da90044ba7/nh3-0.3.2-cp38-abi3-win_amd64.whl", hash = "sha256:562da3dca7a17f9077593214a9781a94b8d76de4f158f8c895e62f09573945fe", size = 596406, upload-time = "2025-10-30T11:17:43.773Z" }, - { url = "https://files.pythonhosted.org/packages/9e/7e/a96255f63b7aef032cbee8fc4d6e37def72e3aaedc1f72759235e8f13cb1/nh3-0.3.2-cp38-abi3-win_arm64.whl", hash = "sha256:cf5964d54edd405e68583114a7cba929468bcd7db5e676ae38ee954de1cfc104", size = 584162, upload-time = "2025-10-30T11:17:44.96Z" }, +version = "0.3.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/cc/37/ab55eb2b05e334ff9a1ad52c556ace1f9c20a3f63613a165d384d5387657/nh3-0.3.3.tar.gz", hash = "sha256:185ed41b88c910b9ca8edc89ca3b4be688a12cb9de129d84befa2f74a0039fee", size = 18968, upload-time = "2026-02-14T09:35:15.664Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e7/a4/834f0ebd80844ce67e1bdb011d6f844f61cdb4c1d7cdc56a982bc054cc00/nh3-0.3.3-cp314-cp314t-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:21b058cd20d9f0919421a820a2843fdb5e1749c0bf57a6247ab8f4ba6723c9fc", size = 1428680, upload-time = "2026-02-14T09:34:33.015Z" }, + { url = "https://files.pythonhosted.org/packages/7f/1a/a7d72e750f74c6b71befbeebc4489579fe783466889d41f32e34acde0b6b/nh3-0.3.3-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f4400a73c2a62859e769f9d36d1b5a7a5c65c4179d1dddd2f6f3095b2db0cbfc", size = 799003, upload-time = "2026-02-14T09:34:35.108Z" }, + { url = "https://files.pythonhosted.org/packages/58/d5/089eb6d65da139dc2223b83b2627e00872eccb5e1afdf5b1d76eb6ad3fcc/nh3-0.3.3-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1ef87f8e916321a88b45f2d597f29bd56e560ed4568a50f0f1305afab86b7189", size = 846818, upload-time = "2026-02-14T09:34:37Z" }, + { url = "https://files.pythonhosted.org/packages/9b/c6/44a0b65fc7b213a3a725f041ef986534b100e58cd1a2e00f0fd3c9603893/nh3-0.3.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:a446eae598987f49ee97ac2f18eafcce4e62e7574bd1eb23782e4702e54e217d", size = 1012537, upload-time = "2026-02-14T09:34:38.515Z" }, + { url = "https://files.pythonhosted.org/packages/94/3a/91bcfcc0a61b286b8b25d39e288b9c0ba91c3290d402867d1cd705169844/nh3-0.3.3-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:0d5eb734a78ac364af1797fef718340a373f626a9ff6b4fb0b4badf7927e7b81", size = 1095435, upload-time = "2026-02-14T09:34:40.022Z" }, + { url = "https://files.pythonhosted.org/packages/fd/fd/4617a19d80cf9f958e65724ff5e97bc2f76f2f4c5194c740016606c87bd1/nh3-0.3.3-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:92a958e6f6d0100e025a5686aafd67e3c98eac67495728f8bb64fbeb3e474493", size = 1056344, upload-time = "2026-02-14T09:34:41.469Z" }, + { url = "https://files.pythonhosted.org/packages/bd/7d/5bcbbc56e71b7dda7ef1d6008098da9c5426d6334137ef32bb2b9c496984/nh3-0.3.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:9ed40cf8449a59a03aa465114fedce1ff7ac52561688811d047917cc878b19ca", size = 1034533, upload-time = "2026-02-14T09:34:43.313Z" }, + { url = "https://files.pythonhosted.org/packages/3f/9c/054eff8a59a8b23b37f0f4ac84cdd688ee84cf5251664c0e14e5d30a8a67/nh3-0.3.3-cp314-cp314t-win32.whl", hash = "sha256:b50c3770299fb2a7c1113751501e8878d525d15160a4c05194d7fe62b758aad8", size = 608305, upload-time = "2026-02-14T09:34:44.622Z" }, + { url = "https://files.pythonhosted.org/packages/d7/b0/64667b8d522c7b859717a02b1a66ba03b529ca1df623964e598af8db1ed5/nh3-0.3.3-cp314-cp314t-win_amd64.whl", hash = "sha256:21a63ccb18ddad3f784bb775955839b8b80e347e597726f01e43ca1abcc5c808", size = 620633, upload-time = "2026-02-14T09:34:46.069Z" }, + { url = "https://files.pythonhosted.org/packages/91/b5/ae9909e4ddfd86ee076c4d6d62ba69e9b31061da9d2f722936c52df8d556/nh3-0.3.3-cp314-cp314t-win_arm64.whl", hash = "sha256:f508ddd4e2433fdcb78c790fc2d24e3a349ba775e5fa904af89891321d4844a3", size = 607027, upload-time = "2026-02-14T09:34:47.91Z" }, + { url = "https://files.pythonhosted.org/packages/13/3e/aef8cf8e0419b530c95e96ae93a5078e9b36c1e6613eeb1df03a80d5194e/nh3-0.3.3-cp38-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:e8ee96156f7dfc6e30ecda650e480c5ae0a7d38f0c6fafc3c1c655e2500421d9", size = 1448640, upload-time = "2026-02-14T09:34:49.316Z" }, + { url = "https://files.pythonhosted.org/packages/ca/43/d2011a4f6c0272cb122eeff40062ee06bb2b6e57eabc3a5e057df0d582df/nh3-0.3.3-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45fe0d6a607264910daec30360c8a3b5b1500fd832d21b2da608256287bcb92d", size = 839405, upload-time = "2026-02-14T09:34:50.779Z" }, + { url = "https://files.pythonhosted.org/packages/f8/f3/965048510c1caf2a34ed04411a46a04a06eb05563cd06f1aa57b71eb2bc8/nh3-0.3.3-cp38-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5bc1d4b30ba1ba896669d944b6003630592665974bd11a3dc2f661bde92798a7", size = 825849, upload-time = "2026-02-14T09:34:52.622Z" }, + { url = "https://files.pythonhosted.org/packages/78/99/b4bbc6ad16329d8db2c2c320423f00b549ca3b129c2b2f9136be2606dbb0/nh3-0.3.3-cp38-abi3-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:f433a2dd66545aad4a720ad1b2150edcdca75bfff6f4e6f378ade1ec138d5e77", size = 1068303, upload-time = "2026-02-14T09:34:54.179Z" }, + { url = "https://files.pythonhosted.org/packages/3f/34/3420d97065aab1b35f3e93ce9c96c8ebd423ce86fe84dee3126790421a2a/nh3-0.3.3-cp38-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:52e973cb742e95b9ae1b35822ce23992428750f4b46b619fe86eba4205255b30", size = 1029316, upload-time = "2026-02-14T09:34:56.186Z" }, + { url = "https://files.pythonhosted.org/packages/f1/9a/99eda757b14e596fdb2ca5f599a849d9554181aa899274d0d183faef4493/nh3-0.3.3-cp38-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4c730617bdc15d7092dcc0469dc2826b914c8f874996d105b4bc3842a41c1cd9", size = 919944, upload-time = "2026-02-14T09:34:57.886Z" }, + { url = "https://files.pythonhosted.org/packages/6f/84/c0dc75c7fb596135f999e59a410d9f45bdabb989f1cb911f0016d22b747b/nh3-0.3.3-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e98fa3dbfd54e25487e36ba500bc29bca3a4cab4ffba18cfb1a35a2d02624297", size = 811461, upload-time = "2026-02-14T09:34:59.65Z" }, + { url = "https://files.pythonhosted.org/packages/7e/ec/b1bf57cab6230eec910e4863528dc51dcf21b57aaf7c88ee9190d62c9185/nh3-0.3.3-cp38-abi3-manylinux_2_31_riscv64.whl", hash = "sha256:3a62b8ae7c235481715055222e54c682422d0495a5c73326807d4e44c5d14691", size = 840360, upload-time = "2026-02-14T09:35:01.444Z" }, + { url = "https://files.pythonhosted.org/packages/37/5e/326ae34e904dde09af1de51219a611ae914111f0970f2f111f4f0188f57e/nh3-0.3.3-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fc305a2264868ec8fa16548296f803d8fd9c1fa66cd28b88b605b1bd06667c0b", size = 859872, upload-time = "2026-02-14T09:35:03.348Z" }, + { url = "https://files.pythonhosted.org/packages/09/38/7eba529ce17ab4d3790205da37deabb4cb6edcba15f27b8562e467f2fc97/nh3-0.3.3-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:90126a834c18af03bfd6ff9a027bfa6bbf0e238527bc780a24de6bd7cc1041e2", size = 1023550, upload-time = "2026-02-14T09:35:04.829Z" }, + { url = "https://files.pythonhosted.org/packages/05/a2/556fdecd37c3681b1edee2cf795a6799c6ed0a5551b2822636960d7e7651/nh3-0.3.3-cp38-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:24769a428e9e971e4ccfb24628f83aaa7dc3c8b41b130c8ddc1835fa1c924489", size = 1105212, upload-time = "2026-02-14T09:35:06.821Z" }, + { url = "https://files.pythonhosted.org/packages/dd/e3/5db0b0ad663234967d83702277094687baf7c498831a2d3ad3451c11770f/nh3-0.3.3-cp38-abi3-musllinux_1_2_i686.whl", hash = "sha256:b7a18ee057761e455d58b9d31445c3e4b2594cff4ddb84d2e331c011ef46f462", size = 1069970, upload-time = "2026-02-14T09:35:08.504Z" }, + { url = "https://files.pythonhosted.org/packages/79/b2/2ea21b79c6e869581ce5f51549b6e185c4762233591455bf2a326fb07f3b/nh3-0.3.3-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:5a4b2c1f3e6f3cbe7048e17f4fefad3f8d3e14cc0fd08fb8599e0d5653f6b181", size = 1047588, upload-time = "2026-02-14T09:35:09.911Z" }, + { url = "https://files.pythonhosted.org/packages/e2/92/2e434619e658c806d9c096eed2cdff9a883084299b7b19a3f0824eb8e63d/nh3-0.3.3-cp38-abi3-win32.whl", hash = "sha256:e974850b131fdffa75e7ad8e0d9c7a855b96227b093417fdf1bd61656e530f37", size = 616179, upload-time = "2026-02-14T09:35:11.366Z" }, + { url = "https://files.pythonhosted.org/packages/73/88/1ce287ef8649dc51365b5094bd3713b76454838140a32ab4f8349973883c/nh3-0.3.3-cp38-abi3-win_amd64.whl", hash = "sha256:2efd17c0355d04d39e6d79122b42662277ac10a17ea48831d90b46e5ef7e4fc0", size = 631159, upload-time = "2026-02-14T09:35:12.77Z" }, + { url = "https://files.pythonhosted.org/packages/31/f1/b4835dbde4fb06f29db89db027576d6014081cd278d9b6751facc3e69e43/nh3-0.3.3-cp38-abi3-win_arm64.whl", hash = "sha256:b838e619f483531483d26d889438e53a880510e832d2aafe73f93b7b1ac2bce2", size = 616645, upload-time = "2026-02-14T09:35:14.062Z" }, ] [[package]] @@ -1112,11 +1113,11 @@ wheels = [ [[package]] name = "platformdirs" -version = "4.8.0" +version = "4.9.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/41/9b/20c8288dc591129bf9dd7be2c91aec6ef23e450605c3403716bd6c74833e/platformdirs-4.8.0.tar.gz", hash = "sha256:c1d4a51ab04087041dd602707fbe7ee8b62b64e590f30e336e5c99c2d0c542d2", size = 27607, upload-time = "2026-02-14T01:52:03.451Z" } +sdist = { url = "https://files.pythonhosted.org/packages/1b/04/fea538adf7dbbd6d186f551d595961e564a3b6715bdf276b477460858672/platformdirs-4.9.2.tar.gz", hash = "sha256:9a33809944b9db043ad67ca0db94b14bf452cc6aeaac46a88ea55b26e2e9d291", size = 28394, upload-time = "2026-02-16T03:56:10.574Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e0/f0/227a7d1b8d80ae55c4b47f271c0870dd7a153aa65353bf71921265df2300/platformdirs-4.8.0-py3-none-any.whl", hash = "sha256:1c1328b4d2ea997bbcb904175a9bde14e824a3fa79f751ea3888d63d7d727557", size = 20647, upload-time = "2026-02-14T01:52:01.915Z" }, + { url = "https://files.pythonhosted.org/packages/48/31/05e764397056194206169869b50cf2fee4dbbbc71b344705b9c0d878d4d8/platformdirs-4.9.2-py3-none-any.whl", hash = "sha256:9170634f126f8efdae22fb58ae8a0eaa86f38365bc57897a6c4f781d1f5875bd", size = 21168, upload-time = "2026-02-16T03:56:08.891Z" }, ] [[package]] @@ -1961,27 +1962,27 @@ wheels = [ [[package]] name = "uv" -version = "0.10.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/0d/9a/fe74aa0127cdc26141364e07abf25e5d69b4bf9788758fad9cfecca637aa/uv-0.10.2.tar.gz", hash = "sha256:b5016f038e191cc9ef00e17be802f44363d1b1cc3ef3454d1d76839a4246c10a", size = 3858864, upload-time = "2026-02-10T19:17:51.609Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/ec/b5/aea88f66284d220be56ef748ed5e1bd11d819be14656a38631f4b55bfd48/uv-0.10.2-py3-none-linux_armv6l.whl", hash = "sha256:69e35aa3e91a245b015365e5e6ca383ecf72a07280c6d00c17c9173f2d3b68ab", size = 22215714, upload-time = "2026-02-10T19:17:34.281Z" }, - { url = "https://files.pythonhosted.org/packages/7f/72/947ba7737ae6cd50de61d268781b9e7717caa3b07e18238ffd547f9fc728/uv-0.10.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:0b7eef95c36fe92e7aac399c0dce555474432cbfeaaa23975ed83a63923f78fd", size = 21276485, upload-time = "2026-02-10T19:18:15.415Z" }, - { url = "https://files.pythonhosted.org/packages/d3/38/5c3462b927a93be4ccaaa25138926a5fb6c9e1b72884efd7af77e451d82e/uv-0.10.2-py3-none-macosx_11_0_arm64.whl", hash = "sha256:acc08e420abab21de987151059991e3f04bc7f4044d94ca58b5dd547995b4843", size = 20048620, upload-time = "2026-02-10T19:17:26.481Z" }, - { url = "https://files.pythonhosted.org/packages/03/51/d4509b0f5b7740c1af82202e9c69b700d5848b8bd0faa25229e8edd2c19c/uv-0.10.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:aefbcd749ab2ad48bb533ec028607607f7b03be11c83ea152dbb847226cd6285", size = 21870454, upload-time = "2026-02-10T19:17:21.838Z" }, - { url = "https://files.pythonhosted.org/packages/cd/7e/2bcbafcb424bb885817a7e58e6eec9314c190c55935daaafab1858bb82cd/uv-0.10.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.musllinux_1_1_armv7l.whl", hash = "sha256:fad554c38d9988409ceddfac69a465e6e5f925a8b689e7606a395c20bb4d1d78", size = 21839508, upload-time = "2026-02-10T19:17:59.211Z" }, - { url = "https://files.pythonhosted.org/packages/60/08/16df2c1f8ad121a595316b82f6e381447e8974265b2239c9135eb874f33b/uv-0.10.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6dd2dc41043e92b3316d7124a7bf48c2affe7117c93079419146f083df71933c", size = 21841283, upload-time = "2026-02-10T19:17:41.419Z" }, - { url = "https://files.pythonhosted.org/packages/76/27/a869fec4c03af5e43db700fabe208d8ee8dbd56e0ff568ba792788d505cd/uv-0.10.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:111c05182c5630ac523764e0ec2e58d7b54eb149dbe517b578993a13c2f71aff", size = 23111967, upload-time = "2026-02-10T19:18:11.764Z" }, - { url = "https://files.pythonhosted.org/packages/2a/4a/fb38515d966acfbd80179e626985aab627898ffd02c70205850d6eb44df1/uv-0.10.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:45c3deaba0343fd27ab5385d6b7cde0765df1a15389ee7978b14a51c32895662", size = 23911019, upload-time = "2026-02-10T19:18:26.947Z" }, - { url = "https://files.pythonhosted.org/packages/dd/5f/51bcbb490ddb1dcb06d767f0bde649ad2826686b9e30efa57f8ab2750a1d/uv-0.10.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bb2cac4f3be60b64a23d9f035019c30a004d378b563c94f60525c9591665a56b", size = 23030217, upload-time = "2026-02-10T19:17:37.789Z" }, - { url = "https://files.pythonhosted.org/packages/46/69/144f6db851d49aa6f25b040dc5c8c684b8f92df9e8d452c7abc619c6ec23/uv-0.10.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:937687df0380d636ceafcb728cf6357f0432588e721892128985417b283c3b54", size = 23036452, upload-time = "2026-02-10T19:18:18.97Z" }, - { url = "https://files.pythonhosted.org/packages/66/29/3c7c4559c9310ed478e3d6c585ee0aad2852dc4d5fb14f4d92a2a12d1728/uv-0.10.2-py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:f90bca8703ae66bccfcfb7313b4b697a496c4d3df662f4a1a2696a6320c47598", size = 21941903, upload-time = "2026-02-10T19:17:30.575Z" }, - { url = "https://files.pythonhosted.org/packages/9a/5a/42883b5ef2ef0b1bc5b70a1da12a6854a929ff824aa8eb1a5571fb27a39b/uv-0.10.2-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:cca026c2e584788e1264879a123bf499dd8f169b9cafac4a2065a416e09d3823", size = 22651571, upload-time = "2026-02-10T19:18:22.74Z" }, - { url = "https://files.pythonhosted.org/packages/e8/b8/e4f1dda1b3b0cc6c8ac06952bfe7bc28893ff016fb87651c8fafc6dfca96/uv-0.10.2-py3-none-musllinux_1_1_i686.whl", hash = "sha256:9f878837938103ee1307ed3ed5d9228118e3932816ab0deb451e7e16dc8ce82a", size = 22321279, upload-time = "2026-02-10T19:17:49.402Z" }, - { url = "https://files.pythonhosted.org/packages/2c/4b/baa16d46469e024846fc1a8aa0cfa63f1f89ad0fd3eaa985359a168c3fb0/uv-0.10.2-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:6ec75cfe638b316b329474aa798c3988e5946ead4d9e977fe4dc6fc2ea3e0b8b", size = 23252208, upload-time = "2026-02-10T19:17:54.46Z" }, - { url = "https://files.pythonhosted.org/packages/d6/84/6a74e5ec2ee90e4314905e6d1d1708d473e06405e492ec38868b42645388/uv-0.10.2-py3-none-win32.whl", hash = "sha256:f7f3c7e09bf53b81f55730a67dd86299158f470dffb2bd279b6432feb198d231", size = 21118543, upload-time = "2026-02-10T19:18:07.296Z" }, - { url = "https://files.pythonhosted.org/packages/dd/f9/e5cc6cf3a578b87004e857274df97d3cdecd8e19e965869b9b67c094c20c/uv-0.10.2-py3-none-win_amd64.whl", hash = "sha256:7b3685aa1da15acbe080b4cba8684afbb6baf11c9b04d4d4b347cc18b7b9cfa0", size = 23620790, upload-time = "2026-02-10T19:17:45.204Z" }, - { url = "https://files.pythonhosted.org/packages/df/7a/99979dc08ae6a65f4f7a44c5066699016c6eecdc4e695b7512c2efb53378/uv-0.10.2-py3-none-win_arm64.whl", hash = "sha256:abdd5b3c6b871b17bf852a90346eb7af881345706554fd082346b000a9393afd", size = 22035199, upload-time = "2026-02-10T19:18:03.679Z" }, +version = "0.10.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/60/ad/7e2de47ef90b2807572ca0410e7a2d5694b0afac6d31b559b6e2eff225e4/uv-0.10.3.tar.gz", hash = "sha256:56e15a90bf81a484e501f6ebc890024a47cb808800e18ecbc81f7d7668ff8b55", size = 3875449, upload-time = "2026-02-16T11:23:58.482Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/67/a7/e90f9c2c0a4f80c65102fa444ba71a6fe1233e2c4dd55fb68b9bf5e50607/uv-0.10.3-py3-none-linux_armv6l.whl", hash = "sha256:de599782dfaa8ff818767cd07e6fbdcff41a7451a42c324b8a32862da7283148", size = 22331102, upload-time = "2026-02-16T11:24:17.531Z" }, + { url = "https://files.pythonhosted.org/packages/40/db/c5729ec39ed557ac673ca993abd71e5b18d71a92f95f1845152e639000ff/uv-0.10.3-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:815717d3ed409ca7573d3f95125d6bcec6978d2236bddad7bc123ac12dc6cfbb", size = 21384482, upload-time = "2026-02-16T11:24:22.974Z" }, + { url = "https://files.pythonhosted.org/packages/0b/8c/cce26f6da9f69a9f0df032d642a4cb5603249f145c368e41b0154c463ca9/uv-0.10.3-py3-none-macosx_11_0_arm64.whl", hash = "sha256:52241dbefdc1be57aaa37171d27372252d64f3347a5df9e5b8ee3de49207f6ff", size = 20118525, upload-time = "2026-02-16T11:24:00.258Z" }, + { url = "https://files.pythonhosted.org/packages/e1/b2/bab536c11c24c49674820e8e2ebfa686db810d9776bdc5c47ba65beccc48/uv-0.10.3-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:4c5dbc7071c7f18ddf8e445ca59e2f4e4f34872ddffcb971c0ec2d0aee959b3e", size = 21869406, upload-time = "2026-02-16T11:24:08.153Z" }, + { url = "https://files.pythonhosted.org/packages/ed/0e/3dc97fde6e16c974a9f937fdbdf9af713f2b96873f97cd16c78dc6295116/uv-0.10.3-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.musllinux_1_1_armv7l.whl", hash = "sha256:519d9449bf276395643358322c4199338ddf506d684001b12bd7777385d9f81c", size = 21953236, upload-time = "2026-02-16T11:23:56.348Z" }, + { url = "https://files.pythonhosted.org/packages/be/ea/6195af5b4d189d64f148a69991fa6335bf77d770c5eb763990787f0ebf65/uv-0.10.3-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c8ac385bb93bd1b1d4f74f234a3a6e89033eb50976da5d5a4d15218a84c7247f", size = 21937189, upload-time = "2026-02-16T11:24:28.848Z" }, + { url = "https://files.pythonhosted.org/packages/f6/09/2b61660fd3058b751c591b906fe1e34a8308586bb283beafe9df5487c83d/uv-0.10.3-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:95e2bedd5b618621dc4320f3dc863c8f00e07084d8f4ab77b39ddbe7822ddeda", size = 23285307, upload-time = "2026-02-16T11:24:05.588Z" }, + { url = "https://files.pythonhosted.org/packages/06/02/32b1f98552498c0f390192a3496066e6470544ad8c552ae39ec1aea2b794/uv-0.10.3-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b967705e8126ff33bf35d7531283bc5cf5096b8c2b7235772abfa55e1f174d14", size = 24021235, upload-time = "2026-02-16T11:24:14.91Z" }, + { url = "https://files.pythonhosted.org/packages/2e/77/feead72435bbd66ac12e452b98ac0798bf548135eb333f7597cefb43afe9/uv-0.10.3-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ddd903aec32ac4810857ebdbc526dd9624d70c549d0b0410ea06c617a89af7b6", size = 23124930, upload-time = "2026-02-16T11:23:47.418Z" }, + { url = "https://files.pythonhosted.org/packages/ce/de/0638d8aa83c2038c5f820151006b3bf372d109afbfdb2a8fc59187cc3690/uv-0.10.3-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f8daf6530d6496da799dd53a4bfafe138b412a714ea0bff34472c1267229054c", size = 23085652, upload-time = "2026-02-16T11:24:02.865Z" }, + { url = "https://files.pythonhosted.org/packages/f1/cc/1e83561367d78d3d0c0aa7eca89cd635d1e67865ed07067015a055755de9/uv-0.10.3-py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:d930818bfa78976d68dac888123e6dda8e6fc506f0baf5058d8b4e7f514c8e17", size = 21937422, upload-time = "2026-02-16T11:23:44.725Z" }, + { url = "https://files.pythonhosted.org/packages/fc/f7/4c248d6bc67c99828ef741f8090790f11bd522bded48bb8b6d7f18b7f924/uv-0.10.3-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:9c67056288d0e7a000c926545cf9a7e37fd6f29cae2a0b36f2e8c905165dc99c", size = 22750461, upload-time = "2026-02-16T11:23:50.364Z" }, + { url = "https://files.pythonhosted.org/packages/6e/3a/52f1009c8e035253b94f3f255272e468fb553f1f8a9233b8acf5b3a9891f/uv-0.10.3-py3-none-musllinux_1_1_i686.whl", hash = "sha256:8868ae00305a4c4d0daeb6a2b3a7eef41e11e376176fbd8746288477c75fd674", size = 22461429, upload-time = "2026-02-16T11:23:53.892Z" }, + { url = "https://files.pythonhosted.org/packages/93/a3/980c999480d3f0391f4c8d62c71404b9f096f15c49c644696e9e4d15586c/uv-0.10.3-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:037d93c77acb344ef28eac9ab554e5c237452b90ca4869830104397f2fb798a1", size = 23288496, upload-time = "2026-02-16T11:24:11.676Z" }, + { url = "https://files.pythonhosted.org/packages/bb/d6/5ccb14e919d43389d3746586d26649c45221deaafdddd714559f8f813b5f/uv-0.10.3-py3-none-win32.whl", hash = "sha256:d13307f74ce7b9f04962e12198a6c86b7032435979e1c1fd3845cce9b4b8befa", size = 21359743, upload-time = "2026-02-16T11:24:25.737Z" }, + { url = "https://files.pythonhosted.org/packages/d5/95/89b9caeb4007d950dfa5fa5923c2ea67de541de0e3582598b7b9c7eeac53/uv-0.10.3-py3-none-win_amd64.whl", hash = "sha256:4f2fa16083b6c5277f81c5b3ea4bf12e25e6d16c2a71c3c794506bd080c5afe6", size = 23837765, upload-time = "2026-02-16T11:24:31.465Z" }, + { url = "https://files.pythonhosted.org/packages/50/f6/324e84432441b8c03bf65724fabb11d8c7ccdac98e39bd717e4a72b838de/uv-0.10.3-py3-none-win_arm64.whl", hash = "sha256:f86596b464d6fb7951890708fdb907744cbd326464d6a5326919a6859eaefca2", size = 22178302, upload-time = "2026-02-16T11:24:20.036Z" }, ] [[package]] @@ -2000,7 +2001,7 @@ wheels = [ [[package]] name = "virtualenv" -version = "20.36.1" +version = "20.37.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "distlib" }, @@ -2008,9 +2009,9 @@ dependencies = [ { name = "platformdirs" }, { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/aa/a3/4d310fa5f00863544e1d0f4de93bddec248499ccf97d4791bc3122c9d4f3/virtualenv-20.36.1.tar.gz", hash = "sha256:8befb5c81842c641f8ee658481e42641c68b5eab3521d8e092d18320902466ba", size = 6032239, upload-time = "2026-01-09T18:21:01.296Z" } +sdist = { url = "https://files.pythonhosted.org/packages/c1/ef/d9d4ce633df789bf3430bd81fb0d8b9d9465dfc1d1f0deb3fb62cd80f5c2/virtualenv-20.37.0.tar.gz", hash = "sha256:6f7e2064ed470aa7418874e70b6369d53b66bcd9e9fd5389763e96b6c94ccb7c", size = 5864710, upload-time = "2026-02-16T16:17:59.42Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/6a/2a/dc2228b2888f51192c7dc766106cd475f1b768c10caaf9727659726f7391/virtualenv-20.36.1-py3-none-any.whl", hash = "sha256:575a8d6b124ef88f6f51d56d656132389f961062a9177016a50e4f507bbcc19f", size = 6008258, upload-time = "2026-01-09T18:20:59.425Z" }, + { url = "https://files.pythonhosted.org/packages/42/4b/6cf85b485be7ec29db837ec2a1d8cd68bc1147b1abf23d8636c5bd65b3cc/virtualenv-20.37.0-py3-none-any.whl", hash = "sha256:5d3951c32d57232ae3569d4de4cc256c439e045135ebf43518131175d9be435d", size = 5837480, upload-time = "2026-02-16T16:17:57.341Z" }, ] [[package]]