diff --git a/compiler/api/compiler.py b/compiler/api/compiler.py index 14269fe7..ae2ea999 100644 --- a/compiler/api/compiler.py +++ b/compiler/api/compiler.py @@ -89,32 +89,40 @@ def camel(s: str): def get_type_hint(type: str) -> str: - is_flag = FLAGS_RE.match(type) + is_flag = bool(FLAGS_RE.match(type)) if is_flag: type = type.split("?")[1] - if type in CORE_TYPES: - if type == "long" or "int" in type: - type = "int" - elif type == "double": - type = "float" - elif type == "string": - type = "str" - elif type in {"Bool", "true"}: - type = "bool" - else: # bytes and object - type = "bytes" - elif type in {"Object", "!X"}: - type = "TLObject" - elif re.match("^vector", type, re.IGNORECASE): - sub_type = type.split("<")[1][:-1] - type = f"List[{get_type_hint(sub_type)}]" - else: - ns, name = type.split(".") if "." in type else ("", type) - type = '"raw.base.' + ".".join([ns, name]).strip(".") + '"' + def get_hint(t: str) -> str: + if t in CORE_TYPES: + if t in {"long", "int", "int128", "int256"}: + return "int" + if t == "double": + return "float" + if t == "string": + return "str" + if t in {"Bool", "true"}: + return "bool" + return "bytes" + if t in {"Object", "!X"}: + return "TLObject" + if re.match("^vector", t, re.IGNORECASE): + sub_type = t.split("<", 1)[1][:-1] + return f"list[{get_hint(sub_type)}]" + ns, name = t.split(".") if "." in t else ("", t) + return "raw.base." + ".".join([ns, name]).strip(".") + + hint = get_hint(type) + + if is_flag: + if "raw.base" in hint: + return f'"{hint} | None" = None' + return f"{hint} | None = None" - return f"Optional[{type}] = None" if is_flag else type + if "raw.base" in hint: + return f'"{hint}"' + return hint def sort_args(args: list[tuple[str, str]]): diff --git a/compiler/api/template/combinator.txt b/compiler/api/template/combinator.txt index 9599d321..9e938771 100644 --- a/compiler/api/template/combinator.txt +++ b/compiler/api/template/combinator.txt @@ -1,9 +1,11 @@ +from __future__ import annotations + from io import BytesIO from pyrogram.raw.core.primitives import Int, Long, Int128, Int256, Bool, Bytes, String, Double, Vector from pyrogram.raw.core import TLObject from pyrogram import raw -from typing import List, Optional, Any +from typing import Any {warning} @@ -12,7 +14,7 @@ class {name}({base}): # type: ignore """{docstring} """ - __slots__: List[str] = [{slots}] + __slots__: list[str] = [{slots}] ID = {id} QUALNAME = "{qualname}" diff --git a/compiler/api/template/type.txt b/compiler/api/template/type.txt index 2178b29a..1eb49db3 100644 --- a/compiler/api/template/type.txt +++ b/compiler/api/template/type.txt @@ -1,5 +1,7 @@ {warning} +from __future__ import annotations + from pyrogram.raw.core import TLObject class {name}(TLObject): # type: ignore diff --git a/pyproject.toml b/pyproject.toml index 52cf52e9..f7139851 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -136,3 +136,4 @@ ignore = [ [tool.ty.rules] unresolved-import = "ignore" +invalid-assignment = "ignore" \ No newline at end of file diff --git a/pyrogram/client.py b/pyrogram/client.py index 5e8bcb3b..92154e55 100644 --- a/pyrogram/client.py +++ b/pyrogram/client.py @@ -663,7 +663,7 @@ async def handle_updates(self, updates) -> None: diff = await self.invoke( raw.functions.updates.GetChannelDifference( channel=await self.resolve_peer( - utils.get_channel_id(channel_id), + utils.get_channel_id(channel_id or 0), ), filter=raw.types.ChannelMessagesFilter( ranges=[ diff --git a/pyrogram/methods/advanced/save_file.py b/pyrogram/methods/advanced/save_file.py index b26e84b8..cfa77f7a 100644 --- a/pyrogram/methods/advanced/save_file.py +++ b/pyrogram/methods/advanced/save_file.py @@ -137,7 +137,10 @@ def create_rpc(chunk, file_part, is_big, file_id, file_total_parts): pool_size = 2 if is_big else 1 workers_count = 4 if is_big else 1 is_missing_part = file_id is not None - file_id = file_id or self.rnd_id() + + if file_id is None: + file_id = int(self.rnd_id()) + md5_sum = md5() if not is_big and not is_missing_part else None pool = [ diff --git a/pyrogram/methods/business/get_user_gifts.py b/pyrogram/methods/business/get_user_gifts.py index e658213f..7f082855 100644 --- a/pyrogram/methods/business/get_user_gifts.py +++ b/pyrogram/methods/business/get_user_gifts.py @@ -52,8 +52,8 @@ async def get_user_gifts( while True: r = await self.invoke( - raw.functions.payments.GetUserStarGifts( - user_id=peer, + raw.functions.payments.GetSavedStarGifts( + peer=peer, offset=offset, limit=limit, ), diff --git a/pyrogram/methods/business/sell_gift.py b/pyrogram/methods/business/sell_gift.py index 5f376bd3..41a9bc63 100644 --- a/pyrogram/methods/business/sell_gift.py +++ b/pyrogram/methods/business/sell_gift.py @@ -39,5 +39,7 @@ async def sell_gift( raise ValueError("sender_user_id must belong to a user.") return await self.invoke( - raw.functions.payments.ConvertStarGift(user_id=peer, msg_id=message_id), + raw.functions.payments.ConvertStarGift( + stargift=raw.types.InputSavedStarGiftUser(msg_id=message_id), + ), ) diff --git a/pyrogram/methods/business/send_gift.py b/pyrogram/methods/business/send_gift.py index 1cb97828..2346b6a3 100644 --- a/pyrogram/methods/business/send_gift.py +++ b/pyrogram/methods/business/send_gift.py @@ -64,7 +64,7 @@ async def send_gift( ).values() invoice = raw.types.InputInvoiceStarGift( - user_id=peer, + peer=peer, gift_id=gift_id, hide_name=is_private, message=raw.types.TextWithEntities(text=text, entities=entities or []) diff --git a/pyrogram/methods/business/toggle_gift_is_saved.py b/pyrogram/methods/business/toggle_gift_is_saved.py index c3caa634..e38dd792 100644 --- a/pyrogram/methods/business/toggle_gift_is_saved.py +++ b/pyrogram/methods/business/toggle_gift_is_saved.py @@ -43,8 +43,7 @@ async def toggle_gift_is_saved( return await self.invoke( raw.functions.payments.SaveStarGift( - user_id=peer, - msg_id=message_id, + stargift=raw.types.InputSavedStarGiftUser(msg_id=message_id), unsave=not is_saved, ), ) diff --git a/pyrogram/methods/chats/update_color.py b/pyrogram/methods/chats/update_color.py index aae1983a..ad9488c0 100644 --- a/pyrogram/methods/chats/update_color.py +++ b/pyrogram/methods/chats/update_color.py @@ -41,8 +41,10 @@ async def update_color( r = await self.invoke( raw.functions.account.UpdateColor( for_profile=isinstance(color, enums.ProfileColor), - color=color.value, - background_emoji_id=background_emoji_id, + color=raw.types.PeerColor( + color=color.value, + background_emoji_id=background_emoji_id, + ), ), ) else: diff --git a/pyrogram/methods/messages/copy_message.py b/pyrogram/methods/messages/copy_message.py index 85a1396f..e1db98aa 100644 --- a/pyrogram/methods/messages/copy_message.py +++ b/pyrogram/methods/messages/copy_message.py @@ -116,7 +116,7 @@ async def copy_message( await app.copy_message(to_chat, from_chat, 123) """ - message: types.Message = await self.get_messages(from_chat_id, message_id) + message = await self.get_messages(from_chat_id, message_id) return await message.copy( chat_id=chat_id, diff --git a/pyrogram/methods/messages/delete_scheduled_messages.py b/pyrogram/methods/messages/delete_scheduled_messages.py index 0b336067..ca8f5ba7 100644 --- a/pyrogram/methods/messages/delete_scheduled_messages.py +++ b/pyrogram/methods/messages/delete_scheduled_messages.py @@ -14,7 +14,7 @@ async def delete_scheduled_messages( self: pyrogram.Client, chat_id: int | str, message_ids: int | Iterable[int], - ) -> int: + ) -> int | list[int]: """Delete scheduled messages. .. include:: /_includes/usable-by/users-bots.rst @@ -41,11 +41,19 @@ async def delete_scheduled_messages( await app.delete_scheduled_messages(chat_id, list_of_message_ids) """ peer = await self.resolve_peer(chat_id) - is_iterable = not isinstance(message_ids, int) - message_ids = list(message_ids) if is_iterable else [message_ids] - r = await self.invoke( - raw.functions.channels.DeleteMessages(peer=peer, id=message_ids), + if isinstance(message_ids, int): + is_iterable = False + ids = [message_ids] + else: + is_iterable = True + ids = list(message_ids) + + await self.invoke( + raw.functions.messages.DeleteScheduledMessages( + peer=peer, # type: ignore + id=ids, + ), ) - return r.messages if is_iterable else r.messages[0] + return ids if is_iterable else ids[0] diff --git a/pyrogram/methods/messages/edit_message_caption.py b/pyrogram/methods/messages/edit_message_caption.py index 8928963c..3403e1d3 100644 --- a/pyrogram/methods/messages/edit_message_caption.py +++ b/pyrogram/methods/messages/edit_message_caption.py @@ -15,7 +15,7 @@ async def edit_message_caption( caption: str, parse_mode: enums.ParseMode | None = None, caption_entities: list[types.MessageEntity] | None = None, - invert_media: bool = False, + invert_media: bool | None = None, reply_markup: types.InlineKeyboardMarkup | None = None, business_connection_id: str | None = None, ) -> types.Message | None: diff --git a/pyrogram/methods/messages/edit_message_media.py b/pyrogram/methods/messages/edit_message_media.py index 3cf94bca..8257a801 100644 --- a/pyrogram/methods/messages/edit_message_media.py +++ b/pyrogram/methods/messages/edit_message_media.py @@ -22,7 +22,7 @@ async def edit_message_media( file_name: str | None = None, parse_mode: enums.ParseMode | None = None, business_connection_id: str | None = None, - invert_media: bool = False, + invert_media: bool | None = None, ) -> types.Message | None: """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/get_custom_emoji_stickers.py b/pyrogram/methods/messages/get_custom_emoji_stickers.py index 2d70b321..2171622c 100644 --- a/pyrogram/methods/messages/get_custom_emoji_stickers.py +++ b/pyrogram/methods/messages/get_custom_emoji_stickers.py @@ -23,11 +23,11 @@ async def get_custom_emoji_stickers( a list, a single sticker is returned, otherwise a list of stickers is returned. """ is_list = isinstance(custom_emoji_ids, list) - custom_emoji_ids = [custom_emoji_ids] if not is_list else custom_emoji_ids + ids = [custom_emoji_ids] if not is_list else custom_emoji_ids result = await self.invoke( raw.functions.messages.GetCustomEmojiDocuments( - document_id=custom_emoji_ids, + document_id=ids, ), ) diff --git a/pyrogram/methods/messages/search_global_hashtag_messages.py b/pyrogram/methods/messages/search_global_hashtag_messages.py index 949eb667..c95dd759 100644 --- a/pyrogram/methods/messages/search_global_hashtag_messages.py +++ b/pyrogram/methods/messages/search_global_hashtag_messages.py @@ -56,6 +56,7 @@ async def search_global_hashtag_messages( limit = min(100, total) offset_peer = raw.types.InputPeerEmpty() + offset_rate = utils.datetime_to_timestamp(offset_date) while True: messages = await utils.parse_messages( @@ -63,7 +64,7 @@ async def search_global_hashtag_messages( await self.invoke( raw.functions.channels.SearchPosts( hashtag=hashtag, - offset_rate=utils.datetime_to_timestamp(offset_date), + offset_rate=offset_rate, offset_peer=offset_peer, offset_id=offset_id, limit=limit, @@ -77,7 +78,7 @@ async def search_global_hashtag_messages( last = messages[-1] - offset_date = utils.datetime_to_timestamp(last.date) + offset_rate = utils.datetime_to_timestamp(last.date) offset_peer = await self.resolve_peer(last.chat.id) offset_id = last.id diff --git a/pyrogram/methods/messages/send_media_group.py b/pyrogram/methods/messages/send_media_group.py index 1c743b3e..fd8542b3 100644 --- a/pyrogram/methods/messages/send_media_group.py +++ b/pyrogram/methods/messages/send_media_group.py @@ -548,7 +548,6 @@ async def send_media_group( background=background, clear_draft=clear_draft, update_stickersets_order=update_stickersets_order, - schedule_repeat_period=schedule_repeat_period, send_as=await self.resolve_peer(send_as) if send_as else None, quick_reply_shortcut=await utils.get_input_quick_reply_shortcut( quick_reply_shortcut, diff --git a/pyrogram/methods/messages/send_paid_media.py b/pyrogram/methods/messages/send_paid_media.py index e916a890..691d24cf 100644 --- a/pyrogram/methods/messages/send_paid_media.py +++ b/pyrogram/methods/messages/send_paid_media.py @@ -303,7 +303,6 @@ async def send_paid_media( "connection_id", business_connection_id, ), - raw_reply_to_message=i.reply_to_message, replies=0, ) return None diff --git a/pyrogram/methods/stories/get_stories.py b/pyrogram/methods/stories/get_stories.py index 7b234b86..c1284c62 100644 --- a/pyrogram/methods/stories/get_stories.py +++ b/pyrogram/methods/stories/get_stories.py @@ -17,7 +17,13 @@ async def get_stories( self: pyrogram.Client, chat_id: int | str, story_ids: int | Iterable[int], - ) -> types.Story | list[types.Story] | None: + ) -> ( + types.Story + | types.StorySkipped + | types.StoryDeleted + | list[types.Story | types.StorySkipped | types.StoryDeleted] + | None + ): """Get one or more story from an user by using story identifiers. .. include:: /_includes/usable-by/users.rst diff --git a/pyrogram/session/auth.py b/pyrogram/session/auth.py index 8d819d19..5834cf7d 100644 --- a/pyrogram/session/auth.py +++ b/pyrogram/session/auth.py @@ -46,8 +46,8 @@ def unpack(b: BytesIO): return TLObject.read(b) async def invoke(self, data: TLObject): - data = self.pack(data) - await self.connection.send(data) + packed_data = self.pack(data) + await self.connection.send(packed_data) response = BytesIO(await self.connection.recv()) return self.unpack(response) diff --git a/pyrogram/types/bots_and_keyboards/callback_query.py b/pyrogram/types/bots_and_keyboards/callback_query.py index 0a17abe5..d6d49146 100644 --- a/pyrogram/types/bots_and_keyboards/callback_query.py +++ b/pyrogram/types/bots_and_keyboards/callback_query.py @@ -175,6 +175,7 @@ async def edit_message_text( parse_mode: enums.ParseMode | None = None, disable_web_page_preview: bool | None = None, reply_markup: types.InlineKeyboardMarkup | None = None, + business_connection_id: str | None = None, ) -> types.Message | bool | None: """Edit the text of messages attached to callback queries. @@ -194,6 +195,10 @@ async def edit_message_text( reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup`, *optional*): An InlineKeyboardMarkup object. + business_connection_id (``str``, *optional*): + Unique identifier of the business connection. + for business bots only. + Returns: :obj:`~pyrogram.types.Message` | ``bool``: On success, if the edited message was sent by the bot, the edited message is returned, otherwise True is returned (message sent via the bot, as inline query result). @@ -213,7 +218,9 @@ async def edit_message_text( self.message, "business_connection_id", None, - ), + ) + if business_connection_id is None + else business_connection_id, ) return await self._client.edit_inline_text( inline_message_id=self.inline_message_id, @@ -256,17 +263,26 @@ async def edit_message_caption( Raises: RPCError: In case of a Telegram RPC error. """ - return await self.edit_message_text( - caption, - parse_mode, - reply_markup=reply_markup, - business_connection_id=getattr( - self.message, - "business_connection_id", - None, + if self.inline_message_id is None: + return await self._client.edit_message_caption( + chat_id=self.message.chat.id, + message_id=self.message.id, + caption=caption, + parse_mode=parse_mode, + reply_markup=reply_markup, + business_connection_id=getattr( + self.message, + "business_connection_id", + None, + ) + if business_connection_id is None + else business_connection_id, ) - if business_connection_id is None - else business_connection_id, + return await self._client.edit_inline_caption( + inline_message_id=self.inline_message_id, + caption=caption, + parse_mode=parse_mode, + reply_markup=reply_markup, ) async def edit_message_media( diff --git a/pyrogram/types/messages_and_media/draft_message.py b/pyrogram/types/messages_and_media/draft_message.py index 31af51d7..3d4267e3 100644 --- a/pyrogram/types/messages_and_media/draft_message.py +++ b/pyrogram/types/messages_and_media/draft_message.py @@ -123,7 +123,6 @@ def _parse( video_note = None link_preview_options = None web_page_url = None - file_name = None media = raw_draft_message.media media_type = None @@ -134,12 +133,6 @@ def _parse( if isinstance(doc, raw.types.Document): attributes = {type(i): i for i in doc.attributes} - file_name = getattr( - attributes.get(raw.types.DocumentAttributeFilename), - "file_name", - None, - ) - if raw.types.DocumentAttributeVideo in attributes: video_attributes = attributes[ raw.types.DocumentAttributeVideo @@ -206,7 +199,6 @@ def _parse( "invert_media", False, ), - file_name=file_name, media=media_type, _raw=raw_draft_message, ) diff --git a/pyrogram/types/messages_and_media/giveaway.py b/pyrogram/types/messages_and_media/giveaway.py index efab7336..52e248d3 100644 --- a/pyrogram/types/messages_and_media/giveaway.py +++ b/pyrogram/types/messages_and_media/giveaway.py @@ -61,7 +61,10 @@ def __init__( self.private_channel_ids = private_channel_ids @staticmethod - async def _parse(client, message: raw.types.Message) -> Giveaway: + async def _parse(client, message: raw.types.Message) -> Giveaway | None: + if not isinstance(message.media, raw.types.MessageMediaGiveaway): + return None + giveaway: raw.types.MessageMediaGiveaway = message.media chats = [] private_ids = [] diff --git a/pyrogram/types/messages_and_media/message.py b/pyrogram/types/messages_and_media/message.py index 435054ab..4619fc8e 100644 --- a/pyrogram/types/messages_and_media/message.py +++ b/pyrogram/types/messages_and_media/message.py @@ -33,11 +33,11 @@ def init(self, entities): @property def markdown(self): - return Parser.unparse(self, self.entities, False) + return Parser.unparse(self, self.entities or [], False) @property def html(self): - return Parser.unparse(self, self.entities, True) + return Parser.unparse(self, self.entities or [], True) def __getitem__(self, item): return parser_utils.remove_surrogates( @@ -1130,11 +1130,16 @@ async def _parse( # noqa: C901 if isinstance(message, raw.types.Message): message_thread_id = None - entities = [ - types.MessageEntity._parse(client, entity, users) - for entity in (message.entities or []) - ] - entities = types.List(filter(lambda x: x is not None, entities)) + entities = types.List( + [ + e + for e in [ + types.MessageEntity._parse(client, entity, users) + for entity in (message.entities or []) + ] + if e is not None + ], + ) sender_business_bot = None forward_from = None @@ -1516,12 +1521,15 @@ async def _parse( # noqa: C901 if isinstance(message.reply_to, raw.types.MessageReplyHeader): parsed_message.quote_text = message.reply_to.quote_text if message.reply_to.quote_entities: - quote_entities = [ - types.MessageEntity._parse(client, entity, users) - for entity in message.reply_to.quote_entities - ] parsed_message.quote_entities = types.List( - filter(lambda x: x is not None, quote_entities), + [ + e + for e in [ + types.MessageEntity._parse(client, entity, users) + for entity in message.reply_to.quote_entities + ] + if e is not None + ], ) if message.reply_to.forum_topic: if message.reply_to.reply_to_top_id: @@ -5134,7 +5142,7 @@ async def copy( return await self._client.send_web_page( chat_id, url=self.web_page_preview.webpage.url, - text=self.text, + text=self.text or "", entities=self.entities, parse_mode=enums.ParseMode.DISABLED, large_media=self.web_page_preview.force_large_media, @@ -5381,13 +5389,16 @@ async def click( ) return r.url if button.user_id: - return await self._client.get_chat(button.user_id, force_full=False) + return await self._client.get_chat(button.user_id) if button.switch_inline_query: return button.switch_inline_query if button.switch_inline_query_current_chat: return button.switch_inline_query_current_chat raise ValueError("This button is not supported yet") - await self.reply(text=button, quote=quote) + await self.reply( + text=button if isinstance(button, str) else button.text, + quote=quote, + ) return None async def react( diff --git a/pyrogram/types/messages_and_media/message_story.py b/pyrogram/types/messages_and_media/message_story.py index b1872289..6503397b 100644 --- a/pyrogram/types/messages_and_media/message_story.py +++ b/pyrogram/types/messages_and_media/message_story.py @@ -36,7 +36,14 @@ def __init__( async def _parse( client: pyrogram.Client, message_story: raw.types.MessageMediaStory, - ) -> MessageStory | types.Story | list[types.Story] | None: + ) -> ( + MessageStory + | types.Story + | types.StorySkipped + | types.StoryDeleted + | list[types.Story | types.StorySkipped | types.StoryDeleted] + | None + ): from_user = None sender_chat = None user_id = None diff --git a/pyrogram/types/messages_and_media/reaction.py b/pyrogram/types/messages_and_media/reaction.py index 34331e4d..6b523a74 100644 --- a/pyrogram/types/messages_and_media/reaction.py +++ b/pyrogram/types/messages_and_media/reaction.py @@ -69,8 +69,10 @@ def _parse_count( reaction_count: raw.base.ReactionCount, ) -> Reaction | None: reaction = Reaction._parse(client, reaction_count.reaction) - reaction.count = reaction_count.count - reaction.chosen_order = reaction_count.chosen_order + + if reaction: + reaction.count = reaction_count.count + reaction.chosen_order = reaction_count.chosen_order return reaction diff --git a/pyrogram/types/user_and_chats/chat.py b/pyrogram/types/user_and_chats/chat.py index b4062957..ca4bdf25 100644 --- a/pyrogram/types/user_and_chats/chat.py +++ b/pyrogram/types/user_and_chats/chat.py @@ -768,8 +768,11 @@ async def _parse_full( @staticmethod def _parse_chat( client, - chat: raw.types.Chat | raw.types.User | raw.types.Channel, + chat: raw.types.Chat | raw.types.User | raw.types.Channel | None, ) -> Chat | None: + if chat is None: + return None + if isinstance(chat, raw.types.Chat | raw.types.ChatForbidden): return Chat._parse_chat_chat(client, chat) if isinstance(chat, raw.types.User): diff --git a/pyrogram/types/user_and_chats/chat_event.py b/pyrogram/types/user_and_chats/chat_event.py index 4fec5f2c..f19a1351 100644 --- a/pyrogram/types/user_and_chats/chat_event.py +++ b/pyrogram/types/user_and_chats/chat_event.py @@ -308,10 +308,10 @@ async def _parse( users: list[raw.base.User], chats: list[raw.base.Chat], ): - users = {i.id: i for i in users} - chats = {i.id: i for i in chats} + users_map = {i.id: i for i in users} + chats_map = {i.id: i for i in chats} - user = types.User._parse(client, users[event.user_id]) + user = types.User._parse(client, users_map.get(event.user_id)) action = event.action old_description: str | None = None @@ -404,9 +404,12 @@ async def _parse( ): old_linked_chat = types.Chat._parse_chat( client, - chats[action.prev_value], + chats_map.get(action.prev_value), + ) + new_linked_chat = types.Chat._parse_chat( + client, + chats_map.get(action.new_value), ) - new_linked_chat = types.Chat._parse_chat(client, chats[action.new_value]) action = enums.ChatEventAction.LINKED_CHAT_CHANGED elif isinstance(action, raw.types.ChannelAdminLogEventActionChangePhoto): @@ -630,7 +633,9 @@ async def _parse( raw.types.ChannelAdminLogEventActionParticipantJoinByRequest, ): invite_link = types.ChatInviteLink._parse(client, action.invite, users) - approver_user = types.User._parse(client, users[action.approved_by]) + approver_user = types.User._parse( + client, users_map.get(action.approved_by) + ) action = enums.ChatEventAction.MEMBER_JOINED_BY_REQUEST elif isinstance( diff --git a/pyrogram/types/user_and_chats/chat_invite_link.py b/pyrogram/types/user_and_chats/chat_invite_link.py index 0fa3f410..4c4f5824 100644 --- a/pyrogram/types/user_and_chats/chat_invite_link.py +++ b/pyrogram/types/user_and_chats/chat_invite_link.py @@ -102,7 +102,7 @@ def __init__( @staticmethod def _parse( client: pyrogram.Client, - invite: raw.base.ExportedChatInvite, + invite: raw.base.ExportedChatInvite | None, users: dict[int, raw.types.User] | None = None, ) -> ChatInviteLink | None: if not isinstance(invite, raw.types.ChatInviteExported): diff --git a/pyrogram/types/user_and_chats/chat_join_request.py b/pyrogram/types/user_and_chats/chat_join_request.py index 8c739c8e..c06e9a4f 100644 --- a/pyrogram/types/user_and_chats/chat_join_request.py +++ b/pyrogram/types/user_and_chats/chat_join_request.py @@ -59,7 +59,10 @@ def _parse( chat_id = utils.get_raw_peer_id(update.peer) return ChatJoinRequest( - chat=types.Chat._parse_chat(client, chats.get(chat_id)), + chat=types.Chat._parse_chat( + client, + chats.get(chat_id) if chat_id is not None else None, + ), 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), diff --git a/pyrogram/types/user_and_chats/chat_joiner.py b/pyrogram/types/user_and_chats/chat_joiner.py index 0841946f..a16f0ab1 100644 --- a/pyrogram/types/user_and_chats/chat_joiner.py +++ b/pyrogram/types/user_and_chats/chat_joiner.py @@ -63,7 +63,12 @@ def _parse( pending=getattr(joiner, "requested", None), bio=getattr(joiner, "about", None), approved_by=( - types.User._parse(client, users.get(joiner.approved_by)) + types.User._parse( + client, + users.get(joiner.approved_by) + if joiner.approved_by is not None + else None, + ) if getattr(joiner, "approved_by", None) else None ),