Compare commits

..

11 commits

Author SHA1 Message Date
wulan17
ec209e0b2b
pyrofork: Add missing MessageOriginType enums docs
Some checks failed
Build-docs / build (push) Has been cancelled
Pyrofork / build (macos-latest, 3.10) (push) Has been cancelled
Pyrofork / build (macos-latest, 3.11) (push) Has been cancelled
Pyrofork / build (macos-latest, 3.12) (push) Has been cancelled
Pyrofork / build (macos-latest, 3.13) (push) Has been cancelled
Pyrofork / build (macos-latest, 3.9) (push) Has been cancelled
Pyrofork / build (ubuntu-latest, 3.10) (push) Has been cancelled
Pyrofork / build (ubuntu-latest, 3.11) (push) Has been cancelled
Pyrofork / build (ubuntu-latest, 3.12) (push) Has been cancelled
Pyrofork / build (ubuntu-latest, 3.13) (push) Has been cancelled
Pyrofork / build (ubuntu-latest, 3.9) (push) Has been cancelled
Signed-off-by: wulan17 <wulan17@komodos.id>
2025-05-16 22:42:11 +07:00
Ling-ex
a5cd3b92a6
Feat: Add group Parameter to the Decorator.on_error.
Some checks are pending
Build-docs / build (push) Waiting to run
Pyrofork / build (macos-latest, 3.10) (push) Waiting to run
Pyrofork / build (macos-latest, 3.11) (push) Waiting to run
Pyrofork / build (macos-latest, 3.12) (push) Waiting to run
Pyrofork / build (macos-latest, 3.13) (push) Waiting to run
Pyrofork / build (macos-latest, 3.9) (push) Waiting to run
Pyrofork / build (ubuntu-latest, 3.10) (push) Waiting to run
Pyrofork / build (ubuntu-latest, 3.11) (push) Waiting to run
Pyrofork / build (ubuntu-latest, 3.12) (push) Waiting to run
Pyrofork / build (ubuntu-latest, 3.13) (push) Waiting to run
Pyrofork / build (ubuntu-latest, 3.9) (push) Waiting to run
Signed-off-by: Ling-ex <nekochan@rizkiofficial.com>
2025-05-16 18:55:30 +07:00
wulan17
ce356e02f5
Revert "fix: handle connection closure and retry logic in session management"
This reverts commit 4df4478a80.

Signed-off-by: wulan17 <wulan17@komodos.id>
2025-05-16 18:54:25 +07:00
wulan17
632921b4b2
pyrofork: set Client.hide_password default value to True
Some checks are pending
Build-docs / build (push) Waiting to run
Pyrofork / build (macos-latest, 3.10) (push) Waiting to run
Pyrofork / build (macos-latest, 3.11) (push) Waiting to run
Pyrofork / build (macos-latest, 3.12) (push) Waiting to run
Pyrofork / build (macos-latest, 3.13) (push) Waiting to run
Pyrofork / build (macos-latest, 3.9) (push) Waiting to run
Pyrofork / build (ubuntu-latest, 3.10) (push) Waiting to run
Pyrofork / build (ubuntu-latest, 3.11) (push) Waiting to run
Pyrofork / build (ubuntu-latest, 3.12) (push) Waiting to run
Pyrofork / build (ubuntu-latest, 3.13) (push) Waiting to run
Pyrofork / build (ubuntu-latest, 3.9) (push) Waiting to run
Signed-off-by: wulan17 <wulan17@komodos.id>
2025-05-16 00:49:46 +07:00
wulan17
9401e246b6
pyrofork: Drop accept_terms_of_service and sign_up method
Signed-off-by: wulan17 <wulan17@komodos.id>
2025-05-16 00:49:46 +07:00
Ling-ex
7d85848bef
Add Ping method
Signed-off-by: Ling-ex <nekochan@rizkiofficial.com>
2025-05-16 00:49:46 +07:00
Ling-ex
7c3ed0da75
Add progress and progress_args parameters to Client.send_media_group and Message.reply_media_group
Signed-off-by: Ling-ex <nekochan@rizkiofficial.com>
2025-05-16 00:49:45 +07:00
wulan17
646f53d52f
pyrofork: Add is_frozen and frozen_icon field to User
Signed-off-by: wulan17 <wulan17@komodos.id>
2025-05-16 00:49:45 +07:00
wulan17
e083c5a48f
pyrofork: Refactor Qr Code Signin
Signed-off-by: wulan17 <wulan17@komodos.id>
2025-05-16 00:49:44 +07:00
wulan17
a08e10f5d7
pyrofork: fix MESSAGE_IDS_EMPTY error on get_scheduled_messages method
Signed-off-by: wulan17 <wulan17@komodos.id>
2025-05-15 23:02:25 +07:00
wulan17
0e0a8f7533
pyrofork: disable publish workflows
Signed-off-by: wulan17 <wulan17@nusantararom.org>
2025-05-15 23:02:19 +07:00
6 changed files with 60 additions and 148 deletions

View file

@ -484,7 +484,6 @@ def pyrogram_api():
BusinessWeeklyOpen BusinessWeeklyOpen
BusinessWorkingHours BusinessWorkingHours
User User
Username
Chat Chat
ChatPreview ChatPreview
ChatPhoto ChatPhoto

View file

@ -18,7 +18,7 @@
# along with Pyrofork. If not, see <http://www.gnu.org/licenses/>. # along with Pyrofork. If not, see <http://www.gnu.org/licenses/>.
__fork_name__ = "PyroFork" __fork_name__ = "PyroFork"
__version__ = "2.3.64" __version__ = "2.3.62"
__license__ = "GNU Lesser General Public License v3.0 (LGPL-3.0)" __license__ = "GNU Lesser General Public License v3.0 (LGPL-3.0)"
__copyright__ = "Copyright (C) 2022-present Mayuri-Chan <https://github.com/Mayuri-Chan>" __copyright__ = "Copyright (C) 2022-present Mayuri-Chan <https://github.com/Mayuri-Chan>"

View file

@ -21,7 +21,6 @@ import asyncio
import inspect import inspect
import logging import logging
from collections import OrderedDict from collections import OrderedDict
from typing import Any
import pyrogram import pyrogram
from pyrogram import raw, types, utils from pyrogram import raw, types, utils
@ -338,88 +337,59 @@ class Dispatcher:
async def handler_worker(self, lock: asyncio.Lock): async def handler_worker(self, lock: asyncio.Lock):
while True: while True:
packet = await self.updates_queue.get() packet = await self.updates_queue.get()
if packet is None: if packet is None:
break break
await self._process_packet(packet, lock)
try: async def _process_packet(
await self._handle_packet(packet, lock) self,
except pyrogram.StopPropagation: packet: tuple[raw.core.TLObject, dict[int, types.Update], dict[int, types.Update]],
pass lock: asyncio.Lock,
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: try:
if isinstance(handler, handler_type): update, users, chats = packet
if await handler.check(self.client, parsed_update): parser = self.update_parsers.get(type(update))
return (parsed_update,)
elif isinstance(handler, RawUpdateHandler): if parser is not None:
if await handler.check(self.client, update): parsed_result = parser(update, users, chats)
return (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
except Exception as e: except Exception as e:
log.exception(e) log.exception(e)
finally:
self.updates_queue.task_done()
return None async def _handle_exception(self, parsed_update: types.Update, exception: Exception):
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 handled_error = False
for error_handler in self.error_handlers: for error_handler in self.error_handlers:
try: try:
if await error_handler.check( if await error_handler.check(self.client, parsed_update, exception):
self.client, parsed_update, exception,
):
handled_error = True handled_error = True
break break
except pyrogram.StopPropagation: except pyrogram.StopPropagation:
@ -431,3 +401,11 @@ class Dispatcher:
if not handled_error: if not handled_error:
log.exception("Unhandled exception: %s", exception) 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

@ -890,12 +890,7 @@ def command(commands: Union[str, List[str]], prefixes: Union[str, List[str]] = "
command_re = re.compile(r"([\"'])(.*?)(?<!\\)\1|(\S+)") command_re = re.compile(r"([\"'])(.*?)(?<!\\)\1|(\S+)")
async def func(flt, client: pyrogram.Client, message: Message): async def func(flt, client: pyrogram.Client, message: Message):
usernames = []
username = client.me.username or "" username = client.me.username or ""
if client.me.usernames:
usernames.append(username)
for user in client.me.usernames:
usernames.append(user.username)
text = message.text or message.caption text = message.text or message.caption
message.command = None message.command = None
@ -909,24 +904,6 @@ def command(commands: Union[str, List[str]], prefixes: Union[str, List[str]] = "
without_prefix = text[len(prefix):] without_prefix = text[len(prefix):]
for cmd in flt.commands: for cmd in flt.commands:
if usernames:
for username in usernames:
if not re.match(rf"^(?:{cmd}(?:@?{username})?)(?:\s|$)", without_prefix,
flags=re.IGNORECASE if not flt.case_sensitive else 0):
continue
without_command = re.sub(rf"{cmd}(?:@?{username})?\s?", "", without_prefix, count=1,
flags=re.IGNORECASE if not flt.case_sensitive else 0)
# match.groups are 1-indexed, group(1) is the quote, group(2) is the text
# between the quotes, group(3) is unquoted, whitespace-split text
# Remove the escape character from the arguments
message.command = [cmd] + [
re.sub(r"\\([\"'])", r"\1", m.group(2) or m.group(3) or "")
for m in command_re.finditer(without_command)
]
return True
if not re.match(rf"^(?:{cmd}(?:@?{username})?)(?:\s|$)", without_prefix, if not re.match(rf"^(?:{cmd}(?:@?{username})?)(?:\s|$)", without_prefix,
flags=re.IGNORECASE if not flt.case_sensitive else 0): flags=re.IGNORECASE if not flt.case_sensitive else 0):
continue continue
@ -1034,22 +1011,12 @@ class user(Filter, set):
) )
async def __call__(self, _, message: Message): async def __call__(self, _, message: Message):
is_usernames_in_filters = False
if message.from_user.usernames:
for username in message.from_user.usernames:
if (
username.username in self
or username.username.lower() in self
):
is_usernames_in_filters = True
break
return (message.from_user return (message.from_user
and (message.from_user.id in self and (message.from_user.id in self
or (message.from_user.username or (message.from_user.username
and message.from_user.username.lower() in self) and message.from_user.username.lower() in self)
or ("me" in self or ("me" in self
and message.from_user.is_self)) and message.from_user.is_self)))
or is_usernames_in_filters)
# noinspection PyPep8Naming # noinspection PyPep8Naming
@ -1077,15 +1044,6 @@ class chat(Filter, set):
async def __call__(self, _, message: Union[Message, Story]): async def __call__(self, _, message: Union[Message, Story]):
if isinstance(message, Story): if isinstance(message, Story):
is_usernames_in_filters = False
if message.sender_chat.usernames:
for username in message.sender_chat.usernames:
if (
username.username in self
or username.username.lower() in self
):
is_usernames_in_filters = True
break
return ( return (
message.sender_chat message.sender_chat
and ( and (
@ -1104,17 +1062,8 @@ class chat(Filter, set):
and message.from_user.username.lower() in self and message.from_user.username.lower() in self
) )
) )
) or is_usernames_in_filters )
else: else:
is_usernames_in_filters = False
if message.chat.usernames:
for username in message._chat.usernames:
if (
username.username in self
or username.username.lower() in self
):
is_usernames_in_filters = True
break
return (message.chat return (message.chat
and (message.chat.id in self and (message.chat.id in self
or (message.chat.username or (message.chat.username
@ -1122,10 +1071,7 @@ class chat(Filter, set):
or ("me" in self or ("me" in self
and message.from_user and message.from_user
and message.from_user.is_self and message.from_user.is_self
and not message.outgoing)) and not message.outgoing)))
or (is_usernames_in_filters
and not message.outgoing)
)
# noinspection PyPep8Naming # noinspection PyPep8Naming

View file

@ -808,7 +808,7 @@ class Message(Object, Update):
service_type = enums.MessageServiceType.BOT_ALLOWED service_type = enums.MessageServiceType.BOT_ALLOWED
elif isinstance(action, raw.types.MessageActionRequestedPeer) or isinstance(action, raw.types.MessageActionRequestedPeerSentMe): elif isinstance(action, raw.types.MessageActionRequestedPeer) or isinstance(action, raw.types.MessageActionRequestedPeerSentMe):
chats_shared = await types.RequestedChats._parse(client, action) chats_shared = await types.RequestedChats._parse(client, action)
service_type = enums.MessageServiceType.CHAT_SHARED service_type = enums.MessageServiceType.ChatShared
elif isinstance(action, raw.types.MessageActionTopicCreate): elif isinstance(action, raw.types.MessageActionTopicCreate):
forum_topic_created = types.ForumTopicCreated._parse(message) forum_topic_created = types.ForumTopicCreated._parse(message)
service_type = enums.MessageServiceType.FORUM_TOPIC_CREATED service_type = enums.MessageServiceType.FORUM_TOPIC_CREATED

View file

@ -77,16 +77,13 @@ class Gift(Object):
User who sent the star gift. User who sent the star gift.
owner (:obj:`~pyrogram.types.Chat`, *optional*): owner (:obj:`~pyrogram.types.Chat`, *optional*):
Only available if the nfts is in telegram. Current gift owner.
owner_name (``str``, *optional*): owner_name (``str``, *optional*):
Name of the user who received the star gift. Name of the user who received the star gift.
owner_address (``str``, *optional*): owner_address (``str``, *optional*):
Only available if the nfts is in ton network. Address of the gift owner in TON blockchain.
ton_address (``str``, *optional*):
Only available if the nfts is in ton network.
price (``int``, *optional*): price (``int``, *optional*):
Price of this gift in stars. Price of this gift in stars.
@ -144,7 +141,7 @@ class Gift(Object):
raw (:obj:`~pyrogram.raw.base.StarGift`, *optional*): raw (:obj:`~pyrogram.raw.base.StarGift`, *optional*):
The raw object as received from the server. The raw object as received from the server.
link (``str``, *property*): link (``str``, *property*):
A link to the gift. A link to the gift.
For unique gifts only. For unique gifts only.
@ -166,7 +163,6 @@ class Gift(Object):
owner: Optional["types.Chat"] = None, owner: Optional["types.Chat"] = None,
owner_name: Optional[str] = None, owner_name: Optional[str] = None,
owner_address: Optional[str] = None, owner_address: Optional[str] = None,
ton_address: Optional[str] = None,
price: Optional[int] = None, price: Optional[int] = None,
convert_price: Optional[int] = None, convert_price: Optional[int] = None,
upgrade_price: Optional[int] = None, upgrade_price: Optional[int] = None,
@ -205,7 +201,6 @@ class Gift(Object):
self.owner = owner self.owner = owner
self.owner_name = owner_name self.owner_name = owner_name
self.owner_address = owner_address self.owner_address = owner_address
self.ton_address = ton_address
self.price = price self.price = price
self.convert_price = convert_price self.convert_price = convert_price
self.upgrade_price = upgrade_price self.upgrade_price = upgrade_price
@ -238,7 +233,7 @@ class Gift(Object):
return await Gift._parse_unique(client, gift, users, chats) return await Gift._parse_unique(client, gift, users, chats)
elif isinstance(gift, raw.types.StarGiftSaved): elif isinstance(gift, raw.types.StarGiftSaved):
return await Gift._parse_saved(client, gift, users, chats) return await Gift._parse_saved(client, gift, users, chats)
@staticmethod @staticmethod
async def _parse_regular( async def _parse_regular(
client, client,
@ -282,15 +277,9 @@ class Gift(Object):
) or None, ) or None,
available_amount=getattr(star_gift, "availability_issued", None), available_amount=getattr(star_gift, "availability_issued", None),
total_amount=getattr(star_gift, "availability_total", None), total_amount=getattr(star_gift, "availability_total", None),
owner=( owner=types.Chat._parse_chat(client, users.get(owner_id) or chats.get(owner_id)),
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_name=getattr(star_gift, "owner_name", None),
owner_address=getattr(star_gift, "owner_address", None), owner_address=getattr(star_gift, "owner_address", None),
ton_address=getattr(star_gift, "gift_address", None),
is_upgraded=True, is_upgraded=True,
raw=star_gift, raw=star_gift,
client=client client=client