This commit is contained in:
NekoChan 2025-05-24 18:02:16 +00:00 committed by GitHub
commit 07a96f932b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 90 additions and 57 deletions

View file

@ -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
)

View file

@ -305,7 +305,7 @@ class Message(Object, Update):
views (``int``, *optional*):
Channel post views.
forwards (``int``, *optional*):
Channel post forwards.
@ -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

View file

@ -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