Compare commits

..

13 commits

Author SHA1 Message Date
KurimuzonAkuma
f38e6a9d1d
Add transfer_business_account_stars method
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-06-10 22:35:27 +07:00
KurimuzonAkuma
83fe6e87fc
Add get_business_account_gifts and get_business_account_star_balance method
Signed-off-by: wulan17 <wulan17@komodos.id>
2025-06-10 22:35:27 +07:00
wulan17
52a51f4f12
pyrofork: Add reply_to_monoforum_id parameter to supported send_*
Signed-off-by: wulan17 <wulan17@komodos.id>
2025-06-10 22:35:27 +07:00
wulan17
be2a06e7fe
pyrofork: Add STARS_AMOUNT_INVALID exception
Signed-off-by: wulan17 <wulan17@komodos.id>
2025-06-10 22:35:27 +07:00
wulan17
8abab60824
pyrofork: Add paid_message_price_changed field to Message
Signed-off-by: wulan17 <wulan17@komodos.id>
2025-06-10 22:35:26 +07:00
wulan17
c56aaa073c
pyrofork: Add ALLOW_PAYMENT_REQUIRED_X exception
Signed-off-by: wulan17 <wulan17@komodos.id>
2025-06-10 22:35:26 +07:00
wulan17
c7b961df60
pyrofork: Add linked_forum field to Chat
Signed-off-by: wulan17 <wulan17@komodos.id>
2025-06-10 22:35:26 +07:00
wulan17
0e9a8c3966
pyrofork: Drop Chat.is_forum and add new ChatType (FORUM)
Signed-off-by: wulan17 <wulan17@komodos.id>
2025-06-10 22:35:26 +07:00
wulan17
c4fde1c6c9
pyrofork: Add new ChatType (MONOFORUM)
Signed-off-by: wulan17 <wulan17@komodos.id>
2025-06-10 22:35:18 +07:00
KurimuzonAkuma
e5ccb0f36e
pyrofork: Add privileges to RequestPeer buttons
Signed-off-by: wulan17 <wulan17@komodos.id>
2025-06-10 22:33:19 +07:00
KurimuzonAkuma
6fbae9b037
pyrofork: Add search_gifts_for_resale, send_resold_gift, set_gift_resale_price, set_pinned_gifts methods
Co-authored-by: "ALi.w" <aminnimaj@gmail.com>
Signed-off-by: wulan17 <wulan17@komodos.id>
2025-06-10 22:33:18 +07:00
uNickz
1d34154ae9
pyrofork: Add file_name param on InputMedia
* Add file_name param on InputMedia

Add file_name param on:
 - InputMediaVideo
 - InputMediaAudio
 - InputMediaDocument

---------

Co-authored-by: KurimuzonAkuma <31959970+KurimuzonAkuma@users.noreply.github.com>
Signed-off-by: wulan17 <wulan17@komodos.id>
2025-06-10 22:33:18 +07:00
wulan17
c242eaa4c9
pyrofork: Refactor Message.link
Signed-off-by: wulan17 <wulan17@komodos.id>
2025-06-10 22:33:18 +07:00
43 changed files with 1055 additions and 35 deletions

View file

@ -365,11 +365,15 @@ def pyrogram_api():
get_chat_gifts
hide_gift
refund_star_payment
search_gifts_for_resale
send_invoice
send_paid_media
send_paid_reaction
send_payment_form
send_gift
send_resold_gift
set_gift_resale_price
set_pinned_gift
show_gift
transfer_gift
upgrade_gift
@ -411,6 +415,9 @@ def pyrogram_api():
answer_shipping_query
delete_business_messages
get_business_connection
get_business_account_gifts
get_business_account_star_balance
transfer_business_account_stars
""",
authorization="""
Authorization
@ -605,6 +612,7 @@ def pyrogram_api():
Invoice
LabeledPrice
PaidMedia
PaidMessagePriceChanged
PaymentForm
PaymentInfo
PaymentRefunded
@ -714,6 +722,7 @@ def pyrogram_api():
InputMessageContent
InputMessageContent
InputReplyToMessage
InputReplyToMonoforum
InputReplyToStory
InputTextMessageContent
InputLocationMessageContent

View file

@ -35,6 +35,7 @@ BOT_GAMES_DISABLED Bot games cannot be used in this type of chat
BOT_GROUPS_BLOCKED This bot can't be added to groups
BOT_INLINE_DISABLED The inline feature of the bot is disabled
BOT_INVALID This is not a valid bot
BOT_INVOICE_INVALID The provided invoice is invalid
BOT_METHOD_INVALID The method can't be used by bots
BOT_MISSING This method can only be run by a bot
BOT_ONESIDE_NOT_AVAIL Bots can't pin messages for one side only in private chats
@ -46,6 +47,7 @@ BROADCAST_CALLS_DISABLED Broadcast calls disabled
BROADCAST_ID_INVALID The channel is invalid
BROADCAST_PUBLIC_VOTERS_FORBIDDEN Polls with public voters cannot be sent in channels
BROADCAST_REQUIRED The request can only be used with a channel
BUSINESS_BOT_MISSING Business bot missing
BUTTON_DATA_INVALID The button callback data is invalid or too large
BUTTON_ID_INVALID The button_id parameter is invalid
BUTTON_TEXT_INVALID The specified button text is invalid
@ -503,3 +505,4 @@ BOOSTS_EMPTY You can't modify the icon of the General topic.
BOOST_NOT_MODIFIED You're already boosting the specified channel.
PAYMENT_REQUIRED The payment is required
BOOST_PEER_INVALID The specified `boost_peer` is invalid.
STARS_AMOUNT_INVALID The specified `amount` is invalid.
1 id message
35 BOT_GROUPS_BLOCKED This bot can't be added to groups
36 BOT_INLINE_DISABLED The inline feature of the bot is disabled
37 BOT_INVALID This is not a valid bot
38 BOT_INVOICE_INVALID The provided invoice is invalid
39 BOT_METHOD_INVALID The method can't be used by bots
40 BOT_MISSING This method can only be run by a bot
41 BOT_ONESIDE_NOT_AVAIL Bots can't pin messages for one side only in private chats
47 BROADCAST_ID_INVALID The channel is invalid
48 BROADCAST_PUBLIC_VOTERS_FORBIDDEN Polls with public voters cannot be sent in channels
49 BROADCAST_REQUIRED The request can only be used with a channel
50 BUSINESS_BOT_MISSING Business bot missing
51 BUTTON_DATA_INVALID The button callback data is invalid or too large
52 BUTTON_ID_INVALID The button_id parameter is invalid
53 BUTTON_TEXT_INVALID The specified button text is invalid
505 BOOST_NOT_MODIFIED You're already boosting the specified channel.
506 PAYMENT_REQUIRED The payment is required
507 BOOST_PEER_INVALID The specified `boost_peer` is invalid.
508 STARS_AMOUNT_INVALID The specified `amount` is invalid.

View file

@ -44,3 +44,4 @@ GROUPCALL_ALREADY_STARTED The groupcall has already started, you can join direct
GROUPCALL_FORBIDDEN The group call has already ended
LIVE_DISABLED Story is disabled server-side
CHAT_GUEST_SEND_FORBIDDEN You need to join the discussion group before commenting
ALLOW_PAYMENT_REQUIRED_X Payment of {value} stars is required to perform this action
1 id message
44 GROUPCALL_FORBIDDEN The group call has already ended
45 LIVE_DISABLED Story is disabled server-side
46 CHAT_GUEST_SEND_FORBIDDEN You need to join the discussion group before commenting
47 ALLOW_PAYMENT_REQUIRED_X Payment of {value} stars is required to perform this action

View file

@ -0,0 +1,8 @@
GiftAttributeType
=================
.. autoclass:: pyrogram.enums.GiftForResaleOrder()
:members:
.. raw:: html
:file: ./cleanup.html

View file

@ -27,6 +27,7 @@ from .chat_type import ChatType
from .client_platform import ClientPlatform
from .folder_color import FolderColor
from .gift_attribute_type import GiftAttributeType
from .gift_for_resale_order import GiftForResaleOrder
from .listerner_types import ListenerTypes
from .message_entity_type import MessageEntityType
from .message_media_type import MessageMediaType
@ -55,6 +56,7 @@ __all__ = [
'ClientPlatform',
'FolderColor',
'GiftAttributeType',
'GiftForResaleOrder',
'ListenerTypes',
'MessageEntityType',
'MessageMediaType',

View file

@ -39,3 +39,9 @@ class ChatType(AutoName):
CHANNEL = auto()
"Chat is a channel"
FORUM = auto()
"Chat is a forum"
MONOFORUM = auto()
"Chat is a monoforum"

View file

@ -0,0 +1,35 @@
# Pyrofork - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance>
# Copyright (C) 2022-present Mayuri-Chan <https://github.com/Mayuri-Chan>
#
# This file is part of Pyrofork.
#
# Pyrofork is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Pyrofork is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrofork. If not, see <http://www.gnu.org/licenses/>.
from enum import auto
from .auto_name import AutoName
class GiftForResaleOrder(AutoName):
"""Describes order in which upgraded gifts for resale will be sorted. Used in :meth:`~pyrogram.Client.search_gifts_for_resale`."""
PRICE = auto()
"The gifts will be sorted by their price from the lowest to the highest"
CHANGE_DATE = auto()
"The gifts will be sorted by the last date when their price was changed from the newest to the oldest"
NUMBER = auto()
"The gifts will be sorted by their number from the smallest to the largest"

View file

@ -132,3 +132,6 @@ class MessageServiceType(AutoName):
SCREENSHOT_TAKEN = auto()
"Screenshot taken"
PAID_MESSAGE_PRICE_CHANGED = auto()
"Paid message price changed"

View file

@ -21,6 +21,9 @@ from .answer_pre_checkout_query import AnswerPreCheckoutQuery
from .answer_shipping_query import AnswerShippingQuery
from .delete_business_messages import DeleteBusinessMessages
from .get_business_connection import GetBusinessConnection
from .get_business_account_gifts import GetBusinessAccountGifts
from .get_business_account_star_balance import GetBusinessAccountStarBalance
from .transfer_business_account_stars import TransferBusinessAccountStars
class TelegramBusiness(
@ -28,5 +31,8 @@ class TelegramBusiness(
AnswerShippingQuery,
DeleteBusinessMessages,
GetBusinessConnection,
GetBusinessAccountGifts,
GetBusinessAccountStarBalance,
TransferBusinessAccountStars,
):
pass

View file

@ -0,0 +1,129 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance>
# Copyright (C) 2022-present Mayuri-Chan <https://github.com/Mayuri-Chan>
#
# This file is part of Pyrogram.
#
# Pyrogram is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Pyrogram is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from typing import Optional
import pyrogram
from pyrogram import raw, types
class GetBusinessAccountGifts:
async def get_business_account_gifts(
self: "pyrogram.Client",
business_connection_id: str,
exclude_unsaved: Optional[bool] = None,
exclude_saved: Optional[bool] = None,
exclude_unlimited: Optional[bool] = None,
exclude_limited: Optional[bool] = None,
exclude_upgraded: Optional[bool] = None,
sort_by_price: Optional[bool] = None,
limit: int = 0,
offset: str = "",
):
"""Return the gifts received and owned by a managed business account.
.. note::
Requires the `can_view_gifts_and_stars` business bot right.
.. include:: /_includes/usable-by/bots.rst
Parameters:
business_connection_id (``str``):
Unique identifier of business connection on behalf of which to send the request.
exclude_unsaved (``bool``, *optional*):
Pass True to exclude gifts that arent saved to the accounts profile page.
exclude_saved (``bool``, *optional*):
Pass True to exclude gifts that are saved to the accounts profile page.
exclude_unlimited (``bool``, *optional*):
Pass True to exclude gifts that can be purchased an unlimited number of times.
exclude_limited (``bool``, *optional*):
Pass True to exclude gifts that can be purchased a limited number of times.
exclude_upgraded (``bool``, *optional*):
Pass True to exclude upgraded gifts.
sort_by_price (``bool``, *optional*):
Pass True to sort results by gift price instead of send date. Sorting is applied before pagination.
offset (``str``, *optional*):
Offset of the first entry to return as received from the previous request.
limit (``int``, *optional*):
The maximum number of gifts to be returned.
Returns:
``Generator``: A generator yielding :obj:`~pyrogram.types.Gift` objects.
Example:
.. code-block:: python
async for gift in app.get_business_account_gifts(connection_id):
print(gift)
"""
current = 0
total = abs(limit) or (1 << 31) - 1
limit = min(100, total)
connection_info = await self.get_business_connection(business_connection_id)
while True:
r = await self.invoke(
raw.functions.payments.GetSavedStarGifts(
peer=await self.resolve_peer(connection_info.user.id),
offset=offset,
limit=limit,
exclude_unsaved=exclude_unsaved,
exclude_saved=exclude_saved,
exclude_unlimited=exclude_unlimited,
exclude_limited=exclude_limited,
exclude_unique=exclude_upgraded,
sort_by_value=sort_by_price
),
sleep_threshold=60,
business_connection_id=business_connection_id
)
users = {i.id: i for i in r.users}
chats = {i.id: i for i in r.chats}
user_star_gifts = [
await types.Gift._parse_saved(self, gift, users, chats)
for gift in r.gifts
]
if not user_star_gifts:
return
for gift in user_star_gifts:
yield gift
current += 1
if current >= total:
return
offset = r.next_offset
if not offset:
return

View file

@ -0,0 +1,61 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance>
# Copyright (C) 2022-present Mayuri-Chan <https://github.com/Mayuri-Chan>
#
# This file is part of Pyrogram.
#
# Pyrogram is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Pyrogram is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from typing import Optional, Union
import pyrogram
from pyrogram import raw
class GetBusinessAccountStarBalance:
async def get_business_account_star_balance(
self: "pyrogram.Client",
business_connection_id: str,
) -> int:
"""Return the amount of Telegram Stars owned by a managed business account.
.. note::
Requires the `can_view_gifts_and_stars` business bot right.
.. include:: /_includes/usable-by/bots.rst
Parameters:
business_connection_id (``str``):
Unique identifier of business connection on behalf of which to send the request.
Returns:
``int``: On success, the current stars balance is returned.
Example:
.. code-block:: python
# Get stars balance
await app.get_business_account_star_balance("connection_id")
"""
connection_info = await self.get_business_connection(business_connection_id)
r = await self.invoke(
raw.functions.payments.GetStarsStatus(
peer=await self.resolve_peer(connection_info.user.id),
),
business_connection_id=business_connection_id
)
return r.balance.amount

View file

@ -0,0 +1,72 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
# Pyrogram is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Pyrogram is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
import pyrogram
from pyrogram import raw
class TransferBusinessAccountStars:
async def transfer_business_account_stars(
self: "pyrogram.Client",
business_connection_id: str,
star_count: int,
) -> bool:
"""Transfers Telegram Stars from the business account balance to the bots balance.
.. note::
Requires the `can_transfer_stars` business bot right.
.. include:: /_includes/usable-by/users.rst
Parameters:
business_connection_id (``str``):
Unique identifier of the business connection.
star_count (``int`` | ``str``):
Number of Telegram Stars to transfer, 1-10000.
Returns:
``bool``: On success, True is returned.
"""
# Why telegram won't let us just use InputPeerSelf :(
if self.me:
bot_id = self.me.id
else:
bot_id = (
await self.invoke(raw.functions.users.GetUsers(id=[raw.types.InputPeerSelf()]))
)[0].id
invoice = raw.types.InputInvoiceBusinessBotTransferStars(
bot=await self.resolve_peer(bot_id), stars=star_count
)
payment_form = await self.invoke(
raw.functions.payments.GetPaymentForm(invoice=invoice),
business_connection_id=business_connection_id,
)
await self.invoke(
raw.functions.payments.SendStarsForm(
form_id=payment_form.form_id,
invoice=invoice,
),
business_connection_id=business_connection_id,
)
return True

View file

@ -52,6 +52,7 @@ class SendAnimation:
reply_to_message_id: int = None,
reply_to_story_id: int = None,
reply_to_chat_id: Union[int, str] = None,
reply_to_monoforum_id: Union[int, str] = None,
quote_text: str = None,
quote_entities: List["types.MessageEntity"] = None,
schedule_date: datetime = None,
@ -145,6 +146,11 @@ class SendAnimation:
for reply to message from another chat.
You can also use chat public link in form of *t.me/<username>* (str).
reply_to_monoforum_id (``int`` | ``str``, *optional*):
Unique identifier for the target user of monoforum.
for reply to message from monoforum.
for channel administrators only.
quote_text (``str``, *optional*):
Text to quote.
for reply_to_message only.
@ -226,6 +232,7 @@ class SendAnimation:
reply_to_story_id=reply_to_story_id,
message_thread_id=message_thread_id,
reply_to_chat_id=reply_to_chat_id,
reply_to_monoforum_id=reply_to_monoforum_id,
quote_text=quote_text,
quote_entities=quote_entities,
parse_mode=parse_mode

View file

@ -50,6 +50,7 @@ class SendAudio:
reply_to_message_id: int = None,
reply_to_story_id: int = None,
reply_to_chat_id: Union[int, str] = None,
reply_to_monoforum_id: Union[int, str] = None,
quote_text: str = None,
quote_entities: List["types.MessageEntity"] = None,
message_effect_id: int = None,
@ -137,6 +138,11 @@ class SendAudio:
for reply to message from another chat.
You can also use chat public link in form of *t.me/<username>* (str).
reply_to_monoforum_id (``int`` | ``str``, *optional*):
Unique identifier for the target user of monoforum.
for reply to message from monoforum.
for channel administrators only.
quote_text (``str``, *optional*):
Text to quote.
for reply_to_message only.
@ -216,6 +222,7 @@ class SendAudio:
reply_to_story_id=reply_to_story_id,
message_thread_id=message_thread_id,
reply_to_chat_id=reply_to_chat_id,
reply_to_monoforum_id=reply_to_monoforum_id,
quote_text=quote_text,
quote_entities=quote_entities,
parse_mode=parse_mode

View file

@ -40,6 +40,7 @@ class SendCachedMedia:
reply_to_message_id: int = None,
reply_to_story_id: int = None,
reply_to_chat_id: Union[int, str] = None,
reply_to_monoforum_id: Union[int, str] = None,
quote_text: str = None,
quote_entities: List["types.MessageEntity"] = None,
schedule_date: datetime = None,
@ -104,6 +105,11 @@ class SendCachedMedia:
for reply to message from another chat.
You can also use chat public link in form of *t.me/<username>* (str).
reply_to_monoforum_id (``int`` | ``str``, *optional*):
Unique identifier for the target user of monoforum.
for reply to message from monoforum.
for channel administrators only.
quote_text (``str``, *optional*):
Text to quote.
for reply_to_message only.
@ -144,6 +150,7 @@ class SendCachedMedia:
reply_to_story_id=reply_to_story_id,
message_thread_id=message_thread_id,
reply_to_chat_id=reply_to_chat_id,
reply_to_monoforum_id=reply_to_monoforum_id,
quote_text=quote_text,
quote_entities=quote_entities,
parse_mode=parse_mode

View file

@ -38,6 +38,7 @@ class SendContact:
business_connection_id: str = None,
reply_to_message_id: int = None,
reply_to_chat_id: Union[int, str] = None,
reply_to_monoforum_id: Union[int, str] = None,
quote_text: str = None,
quote_entities: List["types.MessageEntity"] = None,
parse_mode: Optional["enums.ParseMode"] = None,
@ -95,6 +96,11 @@ class SendContact:
for reply to message from another chat.
You can also use chat public link in form of *t.me/<username>* (str).
reply_to_monoforum_id (``int`` | ``str``, *optional*):
Unique identifier for the target user of monoforum.
for reply to message from monoforum.
for channel administrators only.
quote_text (``str``, *optional*):
Text to quote.
for reply_to_message only.
@ -139,6 +145,7 @@ class SendContact:
reply_to_message_id=reply_to_message_id,
message_thread_id=message_thread_id,
reply_to_chat_id=reply_to_chat_id,
reply_to_monoforum_id=reply_to_monoforum_id,
quote_text=quote_text,
quote_entities=quote_entities,
parse_mode=parse_mode

View file

@ -36,6 +36,7 @@ class SendDice:
reply_to_message_id: int = None,
reply_to_story_id: int = None,
reply_to_chat_id: Union[int, str] = None,
reply_to_monoforum_id: Union[int, str] = None,
quote_text: str = None,
quote_entities: List["types.MessageEntity"] = None,
parse_mode: Optional["enums.ParseMode"] = None,
@ -91,6 +92,11 @@ class SendDice:
for reply to message from another chat.
You can also use chat public link in form of *t.me/<username>* (str).
reply_to_monoforum_id (``int`` | ``str``, *optional*):
Unique identifier for the target user of monoforum.
for reply to message from monoforum.
for channel administrators only.
quote_text (``str``, *optional*):
Text to quote.
for reply_to_message only.
@ -143,6 +149,7 @@ class SendDice:
reply_to_story_id=reply_to_story_id,
message_thread_id=message_thread_id,
reply_to_chat_id=reply_to_chat_id,
reply_to_monoforum_id=reply_to_monoforum_id,
quote_text=quote_text,
quote_entities=quote_entities,
parse_mode=parse_mode

View file

@ -48,6 +48,7 @@ class SendDocument:
reply_to_message_id: int = None,
reply_to_story_id: int = None,
reply_to_chat_id: Union[int, str] = None,
reply_to_monoforum_id: Union[int, str] = None,
quote_text: str = None,
quote_entities: List["types.MessageEntity"] = None,
message_effect_id: int = None,
@ -129,6 +130,11 @@ class SendDocument:
for reply to message from another chat.
You can also use chat public link in form of *t.me/<username>* (str).
reply_to_monoforum_id (``int`` | ``str``, *optional*):
Unique identifier for the target user of monoforum.
for reply to message from monoforum.
for channel administrators only.
quote_text (``str``, *optional*):
Text to quote.
for reply_to_message only.
@ -203,6 +209,7 @@ class SendDocument:
reply_to_story_id=reply_to_story_id,
message_thread_id=message_thread_id,
reply_to_chat_id=reply_to_chat_id,
reply_to_monoforum_id=reply_to_monoforum_id,
quote_text=quote_text,
quote_entities=quote_entities,
parse_mode=parse_mode

View file

@ -38,6 +38,7 @@ class SendLocation:
business_connection_id: str = None,
reply_to_message_id: int = None,
reply_to_chat_id: Union[int, str] = None,
reply_to_monoforum_id: Union[int, str] = None,
quote_text: str = None,
quote_entities: List["types.MessageEntity"] = None,
parse_mode: Optional["enums.ParseMode"] = None,
@ -89,6 +90,11 @@ class SendLocation:
for reply to message from another chat.
You can also use chat public link in form of *t.me/<username>* (str).
reply_to_monoforum_id (``int`` | ``str``, *optional*):
Unique identifier for the target user of monoforum.
for reply to message from monoforum.
for channel administrators only.
reply_to_message_id (``int``, *optional*):
If the message is a reply, ID of the original message
@ -136,6 +142,7 @@ class SendLocation:
reply_to_message_id=reply_to_message_id,
message_thread_id=message_thread_id,
reply_to_chat_id=reply_to_chat_id,
reply_to_monoforum_id=reply_to_monoforum_id,
quote_text=quote_text,
quote_entities=quote_entities,
parse_mode=parse_mode

View file

@ -56,6 +56,7 @@ class SendMediaGroup:
reply_to_message_id: int = None,
reply_to_story_id: int = None,
reply_to_chat_id: Union[int, str] = None,
reply_to_monoforum_id: Union[int, str] = None,
quote_text: str = None,
quote_entities: List["types.MessageEntity"] = None,
parse_mode: Optional["enums.ParseMode"] = None,
@ -104,6 +105,11 @@ class SendMediaGroup:
for reply to message from another chat.
You can also use chat public link in form of *t.me/<username>* (str).
reply_to_monoforum_id (``int`` | ``str``, *optional*):
Unique identifier for the target user of monoforum.
for reply to message from monoforum.
for channel administrators only.
quote_text (``str``, *optional*):
Text to quote.
for reply_to_message only.
@ -180,6 +186,7 @@ class SendMediaGroup:
reply_to_story_id=reply_to_story_id,
message_thread_id=message_thread_id,
reply_to_chat_id=reply_to_chat_id,
reply_to_monoforum_id=reply_to_monoforum_id,
quote_text=quote_text,
quote_entities=quote_entities,
parse_mode=parse_mode,

View file

@ -39,6 +39,7 @@ class SendMessage:
reply_to_message_id: int = None,
reply_to_story_id: int = None,
reply_to_chat_id: int = None,
reply_to_monoforum_id: Union[int, str] = None,
quote_text: str = None,
quote_entities: List["types.MessageEntity"] = None,
schedule_date: datetime = None,
@ -100,6 +101,11 @@ class SendMessage:
for reply to message from another chat.
You can also use chat public link in form of *t.me/<username>* (str).
reply_to_monoforum_id (``int`` | ``str``, *optional*):
Unique identifier for the target user of the monoforum.
for reply to message from a monoforum.
for channel administrators only.
quote_text (``str``, *optional*):
Text to quote.
for reply_to_message only.
@ -174,6 +180,7 @@ class SendMessage:
reply_to_story_id=reply_to_story_id,
message_thread_id=message_thread_id,
reply_to_chat_id=reply_to_chat_id,
reply_to_monoforum_id=reply_to_monoforum_id,
quote_text=quote_text,
quote_entities=quote_entities,
parse_mode=parse_mode

View file

@ -46,6 +46,7 @@ class SendPhoto:
reply_to_message_id: int = None,
reply_to_story_id: int = None,
reply_to_chat_id: Union[int, str] = None,
reply_to_monoforum_id: Union[int, str] = None,
quote_text: str = None,
quote_entities: List["types.MessageEntity"] = None,
schedule_date: datetime = None,
@ -122,6 +123,11 @@ class SendPhoto:
for reply to message from another chat.
You can also use chat public link in form of *t.me/<username>* (str).
reply_to_monoforum_id (``int`` | ``str``, *optional*):
Unique identifier for the target user of monoforum.
for reply to message from monoforum.
for channel administrators only.
quote_text (``str``, *optional*):
Text to quote.
for reply_to_message only.
@ -203,6 +209,7 @@ class SendPhoto:
reply_to_story_id=reply_to_story_id,
message_thread_id=message_thread_id,
reply_to_chat_id=reply_to_chat_id,
reply_to_monoforum_id=reply_to_monoforum_id,
quote_text=quote_text,
quote_entities=quote_entities,
parse_mode=parse_mode

View file

@ -44,6 +44,7 @@ class SendSticker:
reply_to_message_id: int = None,
reply_to_story_id: int = None,
reply_to_chat_id: Union[int, str] = None,
reply_to_monoforum_id: Union[int, str] = None,
quote_text: str = None,
quote_entities: List["types.MessageEntity"] = None,
parse_mode: Optional["enums.ParseMode"] = None,
@ -104,6 +105,11 @@ class SendSticker:
for reply to message from another chat.
You can also use chat public link in form of *t.me/<username>* (str).
reply_to_monoforum_id (``int`` | ``str``, *optional*):
Unique identifier for the target user of monoforum.
for reply to message from monoforum.
for channel administrators only.
quote_text (``str``, *optional*):
Text to quote.
for reply_to_message only.
@ -178,6 +184,7 @@ class SendSticker:
reply_to_story_id=reply_to_story_id,
message_thread_id=message_thread_id,
reply_to_chat_id=reply_to_chat_id,
reply_to_monoforum_id=reply_to_monoforum_id,
quote_text=quote_text,
quote_entities=quote_entities,
parse_mode=parse_mode

View file

@ -50,6 +50,7 @@ class SendVideo:
reply_to_message_id: int = None,
reply_to_story_id: int = None,
reply_to_chat_id: Union[int, str] = None,
reply_to_monoforum_id: Union[int, str] = None,
quote_text: str = None,
quote_entities: List["types.MessageEntity"] = None,
cover: Union[str, BinaryIO] = None,
@ -151,6 +152,11 @@ class SendVideo:
for reply to message from another chat.
You can also use chat public link in form of *t.me/<username>* (str).
reply_to_monoforum_id (``int`` | ``str``, *optional*):
Unique identifier for the target user of monoforum.
for reply to message from monoforum.
for channel administrators only.
quote_text (``str``, *optional*):
Text to quote.
for reply_to_message only.
@ -251,6 +257,7 @@ class SendVideo:
reply_to_story_id=reply_to_story_id,
message_thread_id=message_thread_id,
reply_to_chat_id=reply_to_chat_id,
reply_to_monoforum_id=reply_to_monoforum_id,
quote_text=quote_text,
quote_entities=quote_entities,
parse_mode=parse_mode

View file

@ -45,6 +45,7 @@ class SendVideoNote:
reply_to_message_id: int = None,
reply_to_story_id: int = None,
reply_to_chat_id: Union[int, str] = None,
reply_to_monoforum_id: Union[int, str] = None,
quote_text: str = None,
quote_entities: List["types.MessageEntity"] = None,
parse_mode: Optional["enums.ParseMode"] = None,
@ -118,6 +119,11 @@ class SendVideoNote:
for reply to message from another chat.
You can also use chat public link in form of *t.me/<username>* (str).
reply_to_monoforum_id (``int`` | ``str``, *optional*):
Unique identifier for the target user of monoforum.
for reply to message from monoforum.
for channel administrators only.
quote_text (``str``, *optional*):
Text to quote.
for reply_to_message only.
@ -197,6 +203,7 @@ class SendVideoNote:
reply_to_story_id=reply_to_story_id,
message_thread_id=message_thread_id,
reply_to_chat_id=reply_to_chat_id,
reply_to_monoforum_id=reply_to_monoforum_id,
quote_text=quote_text,
quote_entities=quote_entities,
parse_mode=parse_mode

View file

@ -46,6 +46,7 @@ class SendVoice:
reply_to_message_id: int = None,
reply_to_story_id: int = None,
reply_to_chat_id: Union[int, str] = None,
reply_to_monoforum_id: Union[int, str] = None,
quote_text: str = None,
quote_entities: List["types.MessageEntity"] = None,
schedule_date: datetime = None,
@ -121,6 +122,11 @@ class SendVoice:
for reply to message from another chat.
You can also use chat public link in form of *t.me/<username>* (str).
reply_to_monoforum_id (``int`` | ``str``, *optional*):
Unique identifier for the target user of monoforum.
for reply to message from monoforum.
for channel administrators only.
quote_text (``str``, *optional*):
Text to quote.
for reply_to_message only.
@ -189,6 +195,7 @@ class SendVoice:
reply_to_story_id=reply_to_story_id,
message_thread_id=message_thread_id,
reply_to_chat_id=reply_to_chat_id,
reply_to_monoforum_id=reply_to_monoforum_id,
quote_text=quote_text,
quote_entities=quote_entities,
parse_mode=parse_mode

View file

@ -39,6 +39,7 @@ class SendWebPage:
reply_to_message_id: int = None,
reply_to_story_id: int = None,
reply_to_chat_id: Union[int, str] = None,
reply_to_monoforum_id: Union[int, str] = None,
quote_text: str = None,
quote_entities: List["types.MessageEntity"] = None,
schedule_date: datetime = None,
@ -106,6 +107,11 @@ class SendWebPage:
for reply to message from another chat.
You can also use chat public link in form of *t.me/<username>* (str).
reply_to_monoforum_id (``int`` | ``str``, *optional*):
Unique identifier for the target user of monoforum.
for reply to message from monoforum.
for channel administrators only.
quote_text (``str``, *optional*):
Text to quote.
for reply_to_message only.
@ -161,6 +167,7 @@ class SendWebPage:
reply_to_story_id=reply_to_story_id,
message_thread_id=message_thread_id,
reply_to_chat_id=reply_to_chat_id,
reply_to_monoforum_id=reply_to_monoforum_id,
quote_text=quote_text,
quote_entities=quote_entities,
parse_mode=parse_mode

View file

@ -31,11 +31,15 @@ from .get_chat_gifts_count import GetChatGiftsCount
from .get_chat_gifts import GetChatGifts
from .hide_gift import HideGift
from .refund_stars_payment import RefundStarPayment
from .search_gifts_for_resale import SearchGiftsForResale
from .send_invoice import SendInvoice
from .send_paid_media import SendPaidMedia
from .send_paid_reaction import SendPaidReaction
from .send_payment_form import SendPaymentForm
from .send_gift import SendGift
from .send_resold_gift import SendResoldGift
from .set_gift_resale_price import SetGiftResalePrice
from .set_pinned_gift import SetPinnedGift
from .show_gift import ShowGift
from .transfer_gift import TransferGift
from .upgrade_gift import UpgradeGift
@ -55,11 +59,15 @@ class Payments(
GetChatGifts,
HideGift,
RefundStarPayment,
SearchGiftsForResale,
SendPaidReaction,
SendPaidMedia,
SendInvoice,
SendPaymentForm,
SendGift,
SendResoldGift,
SetGiftResalePrice,
SetPinnedGift,
ShowGift,
TransferGift,
UpgradeGift

View file

@ -0,0 +1,110 @@
# Pyrofork - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance>
# Copyright (C) 2022-present Mayuri-Chan <https://github.com/Mayuri-Chan>
#
# This file is part of Pyrofork.
#
# Pyrofork is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Pyrofork is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrofork. If not, see <http://www.gnu.org/licenses/>.
from typing import List, Optional
import pyrogram
from pyrogram import enums, raw, types
class SearchGiftsForResale:
async def search_gifts_for_resale(
self: "pyrogram.Client",
gift_id: int,
order: "enums.GiftForResaleOrder" = enums.GiftForResaleOrder.CHANGE_DATE,
attributes: Optional[List["types.UpgradedGiftAttributeId"]] = None,
limit: int = 0,
offset: str = ""
):
"""Get upgraded gifts that can be bought from other owners.
.. include:: /_includes/usable-by/users.rst
Parameters:
gift_id (``int``):
Identifier of the regular gift that was upgraded to a unique gift.
order (:obj:`~pyrogram.enums.GiftForResaleOrder`):
Order in which the results will be sorted.
attributes (List of :obj:`~pyrogram.types.UpgradedGiftAttributeId`, *optional*):
Attributes used to filter received gifts.
If multiple attributes of the same type are specified, then all of them are allowed.
If none attributes of specific type are specified, then all values for this attribute type are allowed.
limit (``int``, *optional*):
The maximum number of gifts to return. Default is 0 (no limit).
offset (``str``, *optional*):
The offset from which to start returning results. Default is "" (no offset).
Returns:
``Generator``: A generator yielding :obj:`~pyrogram.types.Gift` objects.
Example:
.. code-block:: python
async for gift in app.search_gifts_for_resale(gift_id=123456):
print(gift)
# Buy first gift from resale market
async for gift in app.search_gifts_for_resale(gift_id=123456, limit=1):
await app.send_resold_gift(gift_link=gift.link, new_owner_chat_id="me") # or just use await gift.buy()
"""
current = 0
total = abs(limit) or (1 << 31) - 1
limit = min(100, total)
while True:
r = await self.invoke(
raw.functions.payments.GetResaleStarGifts(
gift_id=gift_id,
offset=offset,
limit=limit,
sort_by_price=order == enums.GiftForResaleOrder.PRICE,
sort_by_num=order == enums.GiftForResaleOrder.NUMBER,
attributes=[attr.write() for attr in attributes] if attributes else None,
),
sleep_threshold=60
)
users = {i.id: i for i in r.users}
chats = {i.id: i for i in r.chats}
gifts = [
await types.Gift._parse(self, gift, users, chats)
for gift in r.gifts
]
if not gifts:
return
for gift in gifts:
yield gift
current += 1
if current >= total:
return
offset = r.next_offset
if not offset:
return

View file

@ -0,0 +1,89 @@
# Pyrofork - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance>
# Copyright (C) 2022-present Mayuri-Chan <https://github.com/Mayuri-Chan>
#
# This file is part of Pyrofork.
#
# Pyrofork is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Pyrofork is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrofork. If not, see <http://www.gnu.org/licenses/>.
from typing import Optional, Union
import pyrogram
from pyrogram import raw, types, utils
class SendResoldGift:
async def send_resold_gift(
self: "pyrogram.Client",
gift_link: str,
new_owner_chat_id: Union[int, str],
) -> Optional["types.Message"]:
"""Send an upgraded gift that is available for resale to another user or channel chat.
.. note::
Gifts already owned by the current user must be transferred using :meth:`~pyrogram.Client.transfer_gift` and can't be passed to this method.
.. include:: /_includes/usable-by/users.rst
Parameters:
gift_link (``str``):
Link to the gift.
new_owner_chat_id (``int`` | ``str``):
Unique identifier (int) or username (str) of the target chat you want to transfer the star gift to.
For your personal cloud (Saved Messages) you can simply use "me" or "self".
For a contact that exists in your Telegram address book you can use his phone number (str).
Returns:
:obj:`~pyrogram.types.Message`: On success, the sent message is returned.
Example:
.. code-block:: python
# Transfer gift to another user
await app.send_resold_gift(gift_link="https://t.me/nft/NekoHelmet-9215", new_owner_chat_id=123)
"""
match = self.UPGRADED_GIFT_RE.match(gift_link)
if not match:
raise ValueError(
"Invalid gift link provided."
)
peer = await self.resolve_peer(new_owner_chat_id)
invoice = raw.types.InputInvoiceStarGiftResale(
slug=match.group(1),
to_id=peer
)
r = await self.invoke(
raw.functions.payments.SendStarsForm(
form_id=(await self.invoke(
raw.functions.payments.GetPaymentForm(
invoice=invoice
),
)).form_id,
invoice=invoice
),
)
messages = await utils.parse_messages(
client=self,
messages=r.updates if isinstance(r, raw.types.payments.PaymentResult) else r
)
return messages[0] if messages else None

View file

@ -0,0 +1,82 @@
# Pyrofork - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance>
# Copyright (C) 2022-present Mayuri-Chan <https://github.com/Mayuri-Chan>
#
# This file is part of Pyrofork.
#
# Pyrofork is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Pyrofork is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrofork. If not, see <http://www.gnu.org/licenses/>.
import re
import pyrogram
from pyrogram import raw
class SetGiftResalePrice:
async def set_gift_resale_price(
self: "pyrogram.Client",
owned_gift_id: str,
resale_star_count: int
) -> bool:
"""Change resale price of a unique gift owned by the current user.
.. include:: /_includes/usable-by/users.rst
Parameters:
owned_gift_id (``str``):
Unique identifier of the target gift.
For a user gift, you can use the message ID (int) of the gift message.
For a channel gift, you can use the packed format `chatID_savedID` (str).
For a upgraded gift, you can use the gift link.
resale_star_count (``int``):
The new price for the unique gift. Pass 0 to disallow gift resale.
Returns:
``bool``: On success, True is returned.
Example:
.. code-block:: python
# Change resale price of a unique gift
await app.set_gift_resale_price(owned_gift_id="123456", resale_star_count=100)
"""
if not isinstance(owned_gift_id, str):
raise ValueError(f"owned_gift_id has to be str, but {type(owned_gift_id)} was provided")
saved_gift_match = re.match(r"^(-\d+)_(\d+)$", owned_gift_id)
slug_match = self.UPGRADED_GIFT_RE.match(owned_gift_id)
if saved_gift_match:
stargift = raw.types.InputSavedStarGiftChat(
peer=await self.resolve_peer(saved_gift_match.group(1)),
saved_id=int(saved_gift_match.group(2))
)
elif slug_match:
stargift = raw.types.InputSavedStarGiftSlug(
slug=slug_match.group(1)
)
else:
stargift = raw.types.InputSavedStarGiftUser(
msg_id=int(owned_gift_id)
)
await self.invoke(
raw.functions.payments.UpdateStarGiftPrice(
stargift=stargift,
resell_stars=resale_star_count
)
)
return True

View file

@ -0,0 +1,95 @@
# Pyrofork - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance>
# Copyright (C) 2022-present Mayuri-Chan <https://github.com/Mayuri-Chan>
#
# This file is part of Pyrofork.
#
# Pyrofork is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Pyrofork is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrofork. If not, see <http://www.gnu.org/licenses/>.
import re
from typing import List, Union
import pyrogram
from pyrogram import raw
class SetPinnedGifts:
async def set_pinned_gifts(
self: "pyrogram.Client",
owner_id: Union[int, str],
owned_gift_ids: List[str],
) -> bool:
"""Change the list of pinned gifts on the current user.
.. include:: /_includes/usable-by/users.rst
Parameters:
owner_id (``int`` | ``str``):
Unique identifier (int) or username (str) of the target chat.
For your personal cloud (Saved Messages) you can simply use "me" or "self".
For a contact that exists in your Telegram address book you can use his phone number (str).
owned_gift_ids (List of ``str``):
New list of pinned gifts.
All gifts must be upgraded and saved on the profile page first.
For a user gift, you can use the message ID (int) of the gift message.
For a channel gift, you can use the packed format `chatID_savedID` (str).
For a upgraded gift, you can use the gift link.
Returns:
``bool``: On success, True is returned.
Example:
.. code-block:: python
# Set pinned gifts in user profile
await app.set_pinned_gifts(received_gift_ids=["123", "456"])
"""
stargifts = []
for gift in owned_gift_ids:
if not isinstance(gift, str):
raise ValueError(f"gift id has to be str, but {type(gift)} was provided")
saved_gift_match = re.match(r"^(-\d+)_(\d+)$", gift)
slug_match = self.UPGRADED_GIFT_RE.match(gift)
if saved_gift_match:
stargifts.append(
raw.types.InputSavedStarGiftChat(
peer=await self.resolve_peer(saved_gift_match.group(1)),
saved_id=int(saved_gift_match.group(2))
)
)
elif slug_match:
stargifts.append(
raw.types.InputSavedStarGiftSlug(
slug=slug_match.group(1)
)
)
else:
stargifts.append(
raw.types.InputSavedStarGiftUser(
msg_id=int(gift)
)
)
r = await self.invoke(
raw.functions.payments.ToggleStarGiftsPinnedToTop(
peer=await self.resolve_peer(owner_id),
stargift=stargifts
)
)
return r

View file

@ -17,7 +17,7 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrofork. If not, see <http://www.gnu.org/licenses/>.
from pyrogram import raw, types
from pyrogram import enums, raw, types
from ..object import Object
from typing import Union
@ -99,15 +99,21 @@ class KeyboardButton(Object):
if isinstance(b, raw.types.KeyboardButtonRequestPeer):
if isinstance(b.peer_type, raw.types.RequestPeerTypeBroadcast):
user_privileges = getattr(b.peer_type, "user_admin_rights", None)
bot_privileges = getattr(b.peer_type, "bot_admin_rights", None)
return KeyboardButton(
text=b.text,
request_chat=types.RequestPeerTypeChannel(
is_creator=b.peer_type.creator,
is_username=b.peer_type.has_username,
max=b.max_quantity
max=b.max_quantity,
user_privileges=user_privileges,
bot_privileges=bot_privileges
)
)
if isinstance(b.peer_type, raw.types.RequestPeerTypeChat):
user_privileges = getattr(b.peer_type, "user_admin_rights", None)
bot_privileges = getattr(b.peer_type, "bot_admin_rights", None)
return KeyboardButton(
text=b.text,
request_chat=types.RequestPeerTypeChat(
@ -115,7 +121,9 @@ class KeyboardButton(Object):
is_bot_participant=b.peer_type.bot_participant,
is_username=b.peer_type.has_username,
is_forum=b.peer_type.forum,
max=b.max_quantity
max=b.max_quantity,
user_privileges=user_privileges,
bot_privileges=bot_privileges
)
)
@ -135,13 +143,52 @@ class KeyboardButton(Object):
elif self.request_location:
return raw.types.KeyboardButtonRequestGeoLocation(text=self.text)
elif self.request_chat:
user_privileges = self.request_peer.user_privileges
bot_privileges = self.request_peer.bot_privileges
user_admin_rights = raw.types.ChatAdminRights(
change_info=user_privileges.can_change_info,
post_messages=user_privileges.can_post_messages,
post_stories=user_privileges.can_post_stories,
edit_messages=user_privileges.can_edit_messages,
edit_stories=user_privileges.can_post_stories,
delete_messages=user_privileges.can_delete_messages,
delete_stories=user_privileges.can_delete_stories,
ban_users=user_privileges.can_restrict_members,
invite_users=user_privileges.can_invite_users,
pin_messages=user_privileges.can_pin_messages,
add_admins=user_privileges.can_promote_members,
anonymous=user_privileges.is_anonymous,
manage_call=user_privileges.can_manage_video_chats,
other=user_privileges.can_manage_chat
) if user_privileges else None
bot_admin_rights = raw.types.ChatAdminRights(
change_info=bot_privileges.can_change_info,
post_messages=bot_privileges.can_post_messages,
post_stories=bot_privileges.can_post_stories,
edit_messages=bot_privileges.can_edit_messages,
edit_stories=bot_privileges.can_post_stories,
delete_messages=bot_privileges.can_delete_messages,
delete_stories=bot_privileges.can_delete_stories,
ban_users=bot_privileges.can_restrict_members,
invite_users=bot_privileges.can_invite_users,
pin_messages=bot_privileges.can_pin_messages,
add_admins=bot_privileges.can_promote_members,
anonymous=bot_privileges.is_anonymous,
manage_call=bot_privileges.can_manage_video_chats,
other=bot_privileges.can_manage_chat
) if bot_privileges else None
if isinstance(self.request_chat, types.RequestPeerTypeChannel):
return raw.types.InputKeyboardButtonRequestPeer(
text=self.text,
button_id=self.request_chat.button_id,
peer_type=raw.types.RequestPeerTypeBroadcast(
creator=self.request_chat.is_creator,
has_username=self.request_chat.is_username
has_username=self.request_chat.is_username,
user_admin_rights=user_admin_rights,
bot_admin_rights=bot_admin_rights
),
max_quantity=self.request_chat.max,
name_requested=self.request_chat.is_name_requested,
@ -155,7 +202,9 @@ class KeyboardButton(Object):
creator=self.request_chat.is_creator,
bot_participant=self.request_chat.is_bot_participant,
has_username=self.request_chat.is_username,
forum=self.request_chat.is_forum
forum=self.request_chat.is_forum,
user_admin_rights=user_admin_rights,
bot_admin_rights=bot_admin_rights
),
max_quantity=self.request_chat.max,
name_requested=self.request_chat.is_name_requested,

View file

@ -16,6 +16,8 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrofork. If not, see <http://www.gnu.org/licenses/>.
from pyrogram import types
from ..object import Object
@ -47,17 +49,25 @@ class RequestPeerTypeChannel(Object):
is_photo_requested (``bool``, *optional*):
If True, Channel photo is requested.
default True.
user_privileges (:obj:`~pyrogram.types.ChatPrivileges`, *optional*):
Privileged actions that an user administrator is able to take.
bot_privileges (:obj:`~pyrogram.types.ChatPrivileges`, *optional*):
Privileged actions that a bot administrator is able to take.
""" # TODO user_admin_rights, bot_admin_rights
def __init__(
self,
button_id: int=0,
is_creator: bool=None,
is_username: bool=None,
max: int=1,
is_name_requested: bool=True,
is_username_requested: bool=True,
is_photo_requested: bool=True
button_id: int = 0,
is_creator: bool = None,
is_username: bool = None,
max: int = 1,
is_name_requested: bool = True,
is_username_requested: bool = True,
is_photo_requested: bool = True,
user_privileges: "types.ChatPrivileges" = None,
bot_privileges: "types.ChatPrivileges" = None
):
super().__init__()
@ -68,3 +78,6 @@ class RequestPeerTypeChannel(Object):
self.is_name_requested = is_name_requested
self.is_username_requested = is_username_requested
self.is_photo_requested = is_photo_requested
self.user_privileges = user_privileges
self.bot_privileges = bot_privileges

View file

@ -16,6 +16,8 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrofork. If not, see <http://www.gnu.org/licenses/>.
from pyrogram import types
from ..object import Object
@ -53,19 +55,27 @@ class RequestPeerTypeChat(Object):
is_photo_requested (``bool``, *optional*):
If True, Chat photo is requested.
default True.
user_privileges (:obj:`~pyrogram.types.ChatPrivileges`, *optional*):
Privileged actions that an user administrator is able to take.
bot_privileges (:obj:`~pyrogram.types.ChatPrivileges`, *optional*):
Privileged actions that a bot administrator is able to take.
""" # TODO user_admin_rights, bot_admin_rights
def __init__(
self,
button_id: int=0,
is_creator: bool=None,
is_bot_participant: bool=None,
is_username: bool=None,
is_forum: bool=None,
max: int=1,
is_name_requested: bool=True,
is_username_requested: bool=True,
is_photo_requested: bool=True
button_id: int = 0,
is_creator: bool = None,
is_bot_participant: bool = None,
is_username: bool = None,
is_forum: bool = None,
max: int = 1,
is_name_requested: bool = True,
is_username_requested: bool = True,
is_photo_requested: bool = True,
user_privileges: "types.ChatPrivileges" = None,
bot_privileges: "types.ChatPrivileges" = None
):
super().__init__()
@ -78,3 +88,5 @@ class RequestPeerTypeChat(Object):
self.is_name_requested = is_name_requested
self.is_username_requested = is_username_requested
self.is_photo_requested = is_photo_requested
self.user_privileges = user_privileges
self.bot_privileges = bot_privileges

View file

@ -65,10 +65,8 @@ class RequestedChat(Object):
"raw.types.PeerChannel"
]
) -> "RequestedChat":
if getattr(request, "broadcast", None):
if isinstance(request, raw.types.RequestedPeerChannel) or isinstance(request, raw.types.PeerChannel):
type = enums.ChatType.CHANNEL
elif getattr(request, "megagroup", None):
type = enums.ChatType.SUPERGROUP
else:
type = enums.ChatType.GROUP
photo = None

View file

@ -19,6 +19,7 @@
from .input_message_content import InputMessageContent
from .input_reply_to_message import InputReplyToMessage
from .input_reply_to_monoforum import InputReplyToMonoforum
from .input_reply_to_story import InputReplyToStory
from .input_text_message_content import InputTextMessageContent
from .input_location_message_content import InputLocationMessageContent
@ -29,6 +30,7 @@ from .input_invoice_message_content import InputInvoiceMessageContent
__all__ = [
"InputMessageContent",
"InputReplyToMessage",
"InputReplyToMonoforum",
"InputReplyToStory",
"InputTextMessageContent",
"InputLocationMessageContent",

View file

@ -0,0 +1,43 @@
# Pyrofork - Telegram MTProto API Client Library for Python
# Copyright (C) 2022-present Mayuri-Chan <https://github.com/Mayuri-Chan>
#
# This file is part of Pyrofork.
#
# Pyrofork is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Pyrofork is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrofork. If not, see <http://www.gnu.org/licenses/>.
from pyrogram import raw
from ..object import Object
class InputReplyToMonoforum(Object):
"""Contains information about a target replied monoforum.
Parameters:
monoforum_peer (:obj:`~pyrogram.raw.types.InputPeer`):
An InputPeer.
"""
def __init__(
self, *,
monoforum_peer: "raw.types.InputPeer"
):
super().__init__()
self.monoforum_peer = monoforum_peer
def write(self):
return raw.types.InputReplyToMonoForum(
monoforum_peer_id=self.monoforum_peer
).write()

View file

@ -480,6 +480,7 @@ class Message(Object, Update):
gift_code: "types.GiftCode" = None,
gift: "types.Gift" = None,
screenshot_taken: "types.ScreenshotTaken" = None,
paid_message_price_changed: "types.PaidMessagePriceChanged" = None,
invoice: "types.Invoice" = None,
story: Union["types.MessageStory", "types.Story"] = None,
alternative_videos: List["types.AlternativeVideo"] = None,
@ -596,6 +597,7 @@ class Message(Object, Update):
self.gift_code = gift_code
self.gift = gift
self.screenshot_taken = screenshot_taken
self.paid_message_price_changed = paid_message_price_changed
self.invoice = invoice
self.story = story
self.video = video
@ -760,6 +762,7 @@ class Message(Object, Update):
gift_code = None
gift = None
screenshot_taken = None
paid_message_price_changed = None
service_type = None
chat_join_type = None
@ -881,6 +884,9 @@ class Message(Object, Update):
elif isinstance(action, raw.types.MessageActionScreenshotTaken):
screenshot_taken = types.ScreenshotTaken()
service_type = enums.MessageServiceType.SCREENSHOT_TAKEN
elif isinstance(action, raw.types.MessageActionPaidMessagesPrice):
paid_message_price_changed = types.PaidMessagePriceChanged._parse(action)
service_type = enums.MessageServiceType.PAID_MESSAGE_PRICE_CHANGED
parsed_message = Message(
id=message.id,
@ -926,6 +932,7 @@ class Message(Object, Update):
contact_registered=contact_registered,
gift_code=gift_code,
screenshot_taken=screenshot_taken,
paid_message_price_changed=paid_message_price_changed,
raw=message,
chat_join_type=chat_join_type,
client=client
@ -970,7 +977,7 @@ class Message(Object, Update):
else:
parsed_message.message_thread_id = message.reply_to.reply_to_msg_id
parsed_message.is_topic_message = True
elif parsed_message.chat.is_forum and parsed_message.message_thread_id is None:
elif parsed_message.chat.type == enums.ChatType.FORUM and parsed_message.message_thread_id is None:
parsed_message.message_thread_id = 1
parsed_message.is_topic_message = True
@ -1299,7 +1306,7 @@ class Message(Object, Update):
pass
else:
parsed_message.reply_to_story = reply_to_story
if parsed_message.chat.is_forum and parsed_message.message_thread_id is None:
if parsed_message.chat.type == enums.ChatType.FORUM and parsed_message.message_thread_id is None:
parsed_message.message_thread_id = 1
parsed_message.is_topic_message = True

View file

@ -27,6 +27,7 @@ from .input_stars_transaction import InputStarsTransaction
from .invoice import Invoice
from .labeled_price import LabeledPrice
from .paid_media import PaidMedia
from .paid_message_price_changed import PaidMessagePriceChanged
from .payment_form import PaymentForm
from .payment_info import PaymentInfo
from .payment_refunded import PaymentRefunded
@ -46,6 +47,7 @@ __all__ = [
"Invoice",
"LabeledPrice",
"PaidMedia",
"PaidMessagePriceChanged",
"PaymentForm",
"PaymentInfo",
"PaymentRefunded",

View file

@ -0,0 +1,49 @@
# Pyrofork - Telegram MTProto API Client Library for Python
# Copyright (C) 2022-present Mayuri-Chan <https://github.com/Mayuri-Chan>
#
# This file is part of Pyrofork.
#
# Pyrofork is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Pyrofork is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrofork. If not, see <http://www.gnu.org/licenses/>.
from typing import List, Union
from pyrogram import raw
from pyrogram import types
from ..object import Object
class PaidMessagePriceChanged(Object):
"""A PaidMessagePriceChanged.
Parameters:
stars_amount (``int``):
Amount of stars.
extended_media (List of :obj:`~pyrogram.types.Animation` | :obj:`~pyrogram.types.ExtendedMediaPreview` | :obj:`~pyrogram.types.Photo` | :obj:`~pyrogram.types.Video`, *optional*):
Extended media.
"""
def __init__(
self,
*,
stars_amount: int,
):
super().__init__()
self.stars_amount = stars_amount
@staticmethod
def _parse(action: "raw.types.MessageActionPaidMessagesPrice") -> "PaidMessagePriceChanged":
return PaidMessagePriceChanged(
stars_amount=action.stars
)

View file

@ -56,9 +56,6 @@ class Chat(Object):
is_support (``bool``):
True, if this chat is part of the Telegram support team. Users and bots only.
is_forum (``bool``, *optional*):
True, if the supergroup chat is a forum
is_participants_hidden (``bool``, *optional*):
True, if the chat members are hidden.
Returned only in :meth:`~pyrogram.Client.get_chat`.
@ -170,6 +167,10 @@ class Chat(Object):
The linked discussion group (in case of channels) or the linked channel (in case of supergroups).
Returned only in :meth:`~pyrogram.Client.get_chat`.
linked_forum (:obj:`~pyrogram.types.Chat`, *optional*):
The linked monoforum (in case of channels) or the linked channel (in case of monoforum).
Returned only in :meth:`~pyrogram.Client.get_chat`.
send_as_chat (:obj:`~pyrogram.types.Chat`, *optional*):
The default "send_as" chat.
Returned only in :meth:`~pyrogram.Client.get_chat`.
@ -231,7 +232,6 @@ class Chat(Object):
is_scam: bool = None,
is_fake: bool = None,
is_support: bool = None,
is_forum: bool = None,
is_participants_hidden: bool = None,
is_join_request: bool = None,
is_join_to_send: bool = None,
@ -263,6 +263,7 @@ class Chat(Object):
permissions: "types.ChatPermissions" = None,
distance: int = None,
linked_chat: "types.Chat" = None,
linked_forum: "types.Chat" = None,
send_as_chat: "types.Chat" = None,
available_reactions: Optional["types.ChatReactions"] = None,
usernames: List["types.Username"] = None,
@ -286,7 +287,6 @@ class Chat(Object):
self.is_scam = is_scam
self.is_fake = is_fake
self.is_support = is_support
self.is_forum = is_forum
self.is_participants_hidden = is_participants_hidden
self.is_join_request = is_join_request
self.is_join_to_send = is_join_to_send
@ -318,6 +318,7 @@ class Chat(Object):
self.permissions = permissions
self.distance = distance
self.linked_chat = linked_chat
self.linked_forum = linked_forum
self.send_as_chat = send_as_chat
self.available_reactions = available_reactions
self.usernames = usernames
@ -394,6 +395,16 @@ class Chat(Object):
restriction_reason = getattr(channel, "restriction_reason", [])
user_name = getattr(channel, "username", None)
active_usernames = getattr(channel, "usernames", [])
if getattr(channel, "monoforum", None):
chat_type = enums.ChatType.MONOFORUM
elif getattr(channel, "forum", None):
chat_type = enums.ChatType.FORUM
elif getattr(channel, "megagroup", None):
chat_type = enums.ChatType.SUPERGROUP
elif getattr(channel, "broadcast", None):
chat_type = enums.ChatType.CHANNEL
else:
chat_type = enums.ChatType.GROUP
usernames = None
if len(active_usernames) >= 1:
usernames = []
@ -410,13 +421,12 @@ class Chat(Object):
return Chat(
id=peer_id,
type=enums.ChatType.SUPERGROUP if getattr(channel, "megagroup", None) else enums.ChatType.CHANNEL,
type=chat_type,
is_verified=getattr(channel, "verified", None),
is_restricted=getattr(channel, "restricted", None),
is_creator=getattr(channel, "creator", None),
is_scam=getattr(channel, "scam", None),
is_fake=getattr(channel, "fake", None),
is_forum=getattr(channel, "forum", None),
is_join_request=getattr(channel, "join_request", None),
is_join_to_send=getattr(channel, "join_to_send", None),
is_slowmode_enabled=getattr(channel, "slowmode_enabled", None),
@ -546,9 +556,14 @@ class Chat(Object):
linked_chat_raw = chats.get(full_chat.linked_chat_id, None)
linked_forum_raw = chats.get(getattr(chat_raw, "linked_monoforum_id"), None)
if linked_chat_raw:
parsed_chat.linked_chat = Chat._parse_channel_chat(client, linked_chat_raw)
if linked_forum_raw:
parsed_chat.linked_forum = Chat._parse_channel_chat(client, linked_forum_raw)
default_send_as = full_chat.default_send_as
if default_send_as:

View file

@ -487,6 +487,7 @@ async def get_reply_to(
reply_to_message_id: int = None,
reply_to_story_id: int = None,
message_thread_id: int = None,
reply_to_monoforum_id: Union[int,str] = None,
reply_to_chat_id: Union[int,str] = None,
quote_text: str = None,
quote_entities: List["types.MessageEntity"] = None,
@ -495,7 +496,12 @@ async def get_reply_to(
):
reply_to = None
reply_to_chat = None
if reply_to_message_id or message_thread_id:
if reply_to_monoforum_id:
peer = await client.resolve_peer(reply_to_monoforum_id)
reply_to = types.InputReplyToMonoforum(
monoforum_peer=peer
)
elif reply_to_message_id or message_thread_id:
text, entities = (await parse_text_entities(client, quote_text, parse_mode, quote_entities)).values()
if reply_to_chat_id is not None:
reply_to_chat = await client.resolve_peer(reply_to_chat_id)
@ -507,7 +513,7 @@ async def get_reply_to(
quote_entities=entities,
quote_offset=quote_offset,
)
if reply_to_story_id:
elif reply_to_story_id:
peer = await client.resolve_peer(chat_id)
reply_to = types.InputReplyToStory(
peer=peer,