From 47b054c99670a3072d7cfb26822fc6f7214ab260 Mon Sep 17 00:00:00 2001 From: wulan17 Date: Fri, 6 Jun 2025 18:01:38 +0700 Subject: [PATCH 1/6] pyrofork: filters: Add support for fragments usernames Signed-off-by: wulan17 --- pyrogram/filters.py | 60 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 57 insertions(+), 3 deletions(-) diff --git a/pyrogram/filters.py b/pyrogram/filters.py index 8b00fe81..3c3bc650 100644 --- a/pyrogram/filters.py +++ b/pyrogram/filters.py @@ -890,7 +890,12 @@ def command(commands: Union[str, List[str]], prefixes: Union[str, List[str]] = " command_re = re.compile(r"([\"'])(.*?)(? Date: Fri, 6 Jun 2025 18:56:33 +0700 Subject: [PATCH 2/6] pyrofork: Add missing Username docs Signed-off-by: wulan17 --- compiler/docs/compiler.py | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/docs/compiler.py b/compiler/docs/compiler.py index f335558e..10e20a1f 100644 --- a/compiler/docs/compiler.py +++ b/compiler/docs/compiler.py @@ -484,6 +484,7 @@ def pyrogram_api(): BusinessWeeklyOpen BusinessWorkingHours User + Username Chat ChatPreview ChatPhoto From 315f61d1ed3c1889b4dcd75b7ecbe85d48ff655f Mon Sep 17 00:00:00 2001 From: wulan17 Date: Fri, 6 Jun 2025 19:03:34 +0700 Subject: [PATCH 3/6] pyrofork: fix enums typo in Message (#135) Signed-off-by: wulan17 --- pyrogram/types/messages_and_media/message.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyrogram/types/messages_and_media/message.py b/pyrogram/types/messages_and_media/message.py index df9ccb62..4776410d 100644 --- a/pyrogram/types/messages_and_media/message.py +++ b/pyrogram/types/messages_and_media/message.py @@ -808,7 +808,7 @@ class Message(Object, Update): service_type = enums.MessageServiceType.BOT_ALLOWED elif isinstance(action, raw.types.MessageActionRequestedPeer) or isinstance(action, raw.types.MessageActionRequestedPeerSentMe): chats_shared = await types.RequestedChats._parse(client, action) - service_type = enums.MessageServiceType.ChatShared + service_type = enums.MessageServiceType.CHAT_SHARED elif isinstance(action, raw.types.MessageActionTopicCreate): forum_topic_created = types.ForumTopicCreated._parse(message) service_type = enums.MessageServiceType.FORUM_TOPIC_CREATED From 7d10a6fb9ce4bfabeb2c9edaf0437a37316fe932 Mon Sep 17 00:00:00 2001 From: Ling-ex Date: Sat, 24 May 2025 18:01:07 +0000 Subject: [PATCH 4/6] Fix: Register RawUpdateHandler and Refactor Dispatcher for Better Modularity. Signed-off-by: Ling-ex Signed-off-by: wulan17 --- pyrogram/dispatcher.py | 122 ++++++++++++++++++++++++----------------- 1 file changed, 72 insertions(+), 50 deletions(-) diff --git a/pyrogram/dispatcher.py b/pyrogram/dispatcher.py index 5cb97b5e..c5f166d5 100644 --- a/pyrogram/dispatcher.py +++ b/pyrogram/dispatcher.py @@ -21,6 +21,7 @@ import asyncio import inspect import logging from collections import OrderedDict +from typing import Any import pyrogram from pyrogram import raw, types, utils @@ -337,59 +338,88 @@ class Dispatcher: async def handler_worker(self, lock: asyncio.Lock): while True: packet = await self.updates_queue.get() + if packet is None: break - await self._process_packet(packet, lock) - async def _process_packet( - self, - packet: tuple[raw.core.TLObject, dict[int, types.Update], dict[int, types.Update]], - lock: asyncio.Lock, + try: + await self._handle_packet(packet, lock) + except pyrogram.StopPropagation: + pass + except Exception as e: + log.exception(e) + finally: + self.updates_queue.task_done() + + async def _handle_packet(self, packet, lock: asyncio.Lock): + update, users, chats = packet + parser = self.update_parsers.get(type(update)) + + parsed_update, handler_type = ( + await parser(update, users, chats) + if parser is not None else (None, type(None)) + ) + async with lock: + await self._dispatch_to_handlers(update, users, chats, parsed_update, handler_type) + + + async def _dispatch_to_handlers( + self, update, users, chats, parsed_update, handler_type, + ): + for group in self.groups.values(): + for handler in group: + args = await self._match_handler( + handler, update, users, chats, parsed_update, handler_type, + ) + if args is None: + continue + + try: + await self._execute_handler(handler, *args) + except pyrogram.StopPropagation: + raise + except pyrogram.ContinuePropagation: + continue + except Exception as error: + if parsed_update is not None: + await self._handle_exception(parsed_update, error) + break + + async def _match_handler( + self, handler, update, users, chats, parsed_update, handler_type, ): try: - update, users, chats = packet - parser = self.update_parsers.get(type(update)) - - if parser is not None: - parsed_result = parser(update, users, chats) - if inspect.isawaitable(parsed_result): - parsed_update, handler_type = await parsed_result - else: - parsed_update, handler_type = parsed_result - else: - parsed_update, handler_type = (None, type(None)) - - async with lock: - for group in self.groups.values(): - for handler in group: - try: - if parsed_update is not None: - if isinstance(handler, handler_type) and await handler.check( - self.client, parsed_update - ): - await self._execute_callback(handler, parsed_update) - break - elif isinstance(handler, RawUpdateHandler): - await self._execute_callback(handler, update, users, chats) - break - except (pyrogram.StopPropagation, pyrogram.ContinuePropagation) as e: - if isinstance(e, pyrogram.StopPropagation): - raise - except Exception as exception: - if parsed_update is not None: - await self._handle_exception(parsed_update, exception) - except pyrogram.StopPropagation: - pass + if isinstance(handler, handler_type): + if await handler.check(self.client, parsed_update): + return (parsed_update,) + elif isinstance(handler, RawUpdateHandler): + if await handler.check(self.client, update): + return (update, users, chats) except Exception as e: log.exception(e) - finally: - self.updates_queue.task_done() - async def _handle_exception(self, parsed_update: types.Update, exception: Exception): + return None + + async def _execute_handler(self, handler, *args: Any): + if inspect.iscoroutinefunction(handler.callback): + await handler.callback(self.client, *args) + else: + await self.loop.run_in_executor( + self.client.executor, + handler.callback, + self.client, + *args + ) + + async def _handle_exception( + self, parsed_update: types.Update, exception: Exception, + ): handled_error = False for error_handler in self.error_handlers: try: - if await error_handler.check(self.client, parsed_update, exception): + if await error_handler.check( + self.client, parsed_update, exception, + ): handled_error = True break except pyrogram.StopPropagation: @@ -401,11 +431,3 @@ class Dispatcher: if not handled_error: log.exception("Unhandled exception: %s", exception) - - async def _execute_callback(self, handler: Handler, *args): - if inspect.iscoroutinefunction(handler.callback): - await handler.callback(self.client, *args) - else: - await self.client.loop.run_in_executor( - self.client.executor, handler.callback, self.client, *args - ) \ No newline at end of file From eb2b854ea600fd6d1fb8bad188a5a1ff6b38ed79 Mon Sep 17 00:00:00 2001 From: Ling-ex Date: Sat, 24 May 2025 18:01:40 +0000 Subject: [PATCH 5/6] Update Gift class: add ton_address and clarify owner info. Signed-off-by: Ling-ex Signed-off-by: wulan17 --- pyrogram/types/payments/gift.py | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/pyrogram/types/payments/gift.py b/pyrogram/types/payments/gift.py index 348a937d..2af51f66 100644 --- a/pyrogram/types/payments/gift.py +++ b/pyrogram/types/payments/gift.py @@ -77,13 +77,16 @@ class Gift(Object): User who sent the star gift. owner (:obj:`~pyrogram.types.Chat`, *optional*): - Current gift owner. + Only available if the nfts is in telegram. owner_name (``str``, *optional*): Name of the user who received the star gift. owner_address (``str``, *optional*): - Address of the gift owner in TON blockchain. + Only available if the nfts is in ton network. + + ton_address (``str``, *optional*): + Only available if the nfts is in ton network. price (``int``, *optional*): Price of this gift in stars. @@ -141,7 +144,7 @@ class Gift(Object): raw (:obj:`~pyrogram.raw.base.StarGift`, *optional*): The raw object as received from the server. - + link (``str``, *property*): A link to the gift. For unique gifts only. @@ -163,6 +166,7 @@ class Gift(Object): owner: Optional["types.Chat"] = None, owner_name: Optional[str] = None, owner_address: Optional[str] = None, + ton_address: Optional[str] = None, price: Optional[int] = None, convert_price: Optional[int] = None, upgrade_price: Optional[int] = None, @@ -201,6 +205,7 @@ class Gift(Object): self.owner = owner self.owner_name = owner_name self.owner_address = owner_address + self.ton_address = ton_address self.price = price self.convert_price = convert_price self.upgrade_price = upgrade_price @@ -233,7 +238,7 @@ class Gift(Object): return await Gift._parse_unique(client, gift, users, chats) elif isinstance(gift, raw.types.StarGiftSaved): return await Gift._parse_saved(client, gift, users, chats) - + @staticmethod async def _parse_regular( client, @@ -277,9 +282,15 @@ class Gift(Object): ) or None, available_amount=getattr(star_gift, "availability_issued", None), total_amount=getattr(star_gift, "availability_total", None), - owner=types.Chat._parse_chat(client, users.get(owner_id) or chats.get(owner_id)), + owner=( + types.Chat._parse_chat(client, users.get(owner_id) or + chats.get(owner_id)) + if owner_id is not None + else None + ), owner_name=getattr(star_gift, "owner_name", None), owner_address=getattr(star_gift, "owner_address", None), + ton_address=getattr(star_gift, "gift_address", None), is_upgraded=True, raw=star_gift, client=client From 907f03197a2c41c07befa65a5f782ca91c7abf32 Mon Sep 17 00:00:00 2001 From: wulan17 Date: Fri, 6 Jun 2025 19:10:02 +0700 Subject: [PATCH 6/6] pyrofork: Bump version to 2.3.64 Signed-off-by: wulan17 --- pyrogram/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyrogram/__init__.py b/pyrogram/__init__.py index 8a82315a..49a2aeb9 100644 --- a/pyrogram/__init__.py +++ b/pyrogram/__init__.py @@ -18,7 +18,7 @@ # along with Pyrofork. If not, see . __fork_name__ = "PyroFork" -__version__ = "2.3.63" +__version__ = "2.3.64" __license__ = "GNU Lesser General Public License v3.0 (LGPL-3.0)" __copyright__ = "Copyright (C) 2022-present Mayuri-Chan "