Pyrofork: Sync Star Gift With Layer 198

Signed-off-by: Yasir <git@yasir.id>
This commit is contained in:
KurimuzonAkuma 2025-02-03 10:13:39 +07:00 committed by Yasir
parent 2923328bbb
commit 7662cc164f
15 changed files with 256 additions and 96 deletions

View file

@ -358,8 +358,8 @@ def pyrogram_api():
get_stars_transactions_by_id get_stars_transactions_by_id
get_available_gifts get_available_gifts
get_upgraded_gift get_upgraded_gift
get_user_gifts_count get_chat_gifts_count
get_user_gifts get_chat_gifts
hide_gift hide_gift
refund_star_payment refund_star_payment
send_invoice send_invoice
@ -861,6 +861,7 @@ def pyrogram_api():
Gift.convert Gift.convert
Gift.upgrade Gift.upgrade
Gift.transfer Gift.transfer
Gift.wear
""", """,
callback_query=""" callback_query="""
Callback Query Callback Query

View file

@ -27,8 +27,8 @@ from .get_upgraded_gift import GetUpgradedGift
from .get_available_gifts import GetAvailableGifts from .get_available_gifts import GetAvailableGifts
from .get_stars_transactions import GetStarsTransactions from .get_stars_transactions import GetStarsTransactions
from .get_stars_transactions_by_id import GetStarsTransactionsById from .get_stars_transactions_by_id import GetStarsTransactionsById
from .get_user_gifts_count import GetUserGiftsCount from .get_chat_gifts_count import GetChatGiftsCount
from .get_user_gifts import GetUserGifts from .get_chat_gifts import GetChatGifts
from .hide_gift import HideGift from .hide_gift import HideGift
from .refund_stars_payment import RefundStarPayment from .refund_stars_payment import RefundStarPayment
from .send_invoice import SendInvoice from .send_invoice import SendInvoice
@ -51,8 +51,8 @@ class Payments(
GetAvailableGifts, GetAvailableGifts,
GetStarsTransactions, GetStarsTransactions,
GetStarsTransactionsById, GetStarsTransactionsById,
GetUserGiftsCount, GetChatGiftsCount,
GetUserGifts, GetChatGifts,
HideGift, HideGift,
RefundStarPayment, RefundStarPayment,
SendPaidReaction, SendPaidReaction,

View file

@ -48,7 +48,7 @@ class ConvertGift:
""" """
r = await self.invoke( r = await self.invoke(
raw.functions.payments.ConvertStarGift( raw.functions.payments.ConvertStarGift(
msg_id=message_id stargift=raw.types.InputSavedStarGiftUser(msg_id=message_id)
) )
) )

View file

@ -43,4 +43,4 @@ class GetAvailableGifts:
raw.functions.payments.GetStarGifts(hash=0) raw.functions.payments.GetStarGifts(hash=0)
) )
return types.List([await types.Gift._parse(self, gift) for gift in r.gifts]) return types.List([await types.Gift._parse_regular(self, gift) for gift in r.gifts])

View file

@ -16,16 +16,22 @@
# You should have received a copy of the GNU Lesser General Public License # You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>. # along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from typing import Union from typing import Optional, Union
import pyrogram import pyrogram
from pyrogram import raw, types from pyrogram import raw, types
class GetUserGifts: class GetChatGifts:
async def get_user_gifts( async def get_chat_gifts(
self: "pyrogram.Client", self: "pyrogram.Client",
chat_id: Union[int, str], chat_id: Union[int, 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_value: Optional[bool] = None,
limit: int = 0, limit: int = 0,
offset: str = "" offset: str = ""
): ):
@ -39,6 +45,24 @@ class GetUserGifts:
For your personal cloud (Saved Messages) you can simply use "me" or "self". 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). For a contact that exists in your Telegram address book you can use his phone number (str).
exclude_unsaved (``bool``, *optional*):
Exclude unsaved star gifts.
exclude_saved (``bool``, *optional*):
Exclude saved star gifts.
exclude_unlimited (``bool``, *optional*):
Exclude unlimited star gifts.
exclude_limited (``bool``, *optional*):
Exclude limited star gifts.
exclude_upgraded (``bool``, *optional*):
Exclude upgraded star gifts.
sort_by_value (``bool``, *optional*):
Sort star gifts by value.
offset (``str``, *optional*): offset (``str``, *optional*):
Offset of the results to be returned. Offset of the results to be returned.
@ -51,32 +75,36 @@ class GetUserGifts:
Example: Example:
.. code-block:: python .. code-block:: python
async for gift in app.get_user_gifts(chat_id): async for gift in app.get_chat_gifts(chat_id):
print(gift) print(gift)
""" """
peer = await self.resolve_peer(chat_id) peer = await self.resolve_peer(chat_id)
if not isinstance(peer, (raw.types.InputPeerUser, raw.types.InputPeerSelf)):
raise ValueError("chat_id must belong to a user.")
current = 0 current = 0
total = abs(limit) or (1 << 31) - 1 total = abs(limit) or (1 << 31) - 1
limit = min(100, total) limit = min(100, total)
while True: while True:
r = await self.invoke( r = await self.invoke(
raw.functions.payments.GetUserStarGifts( raw.functions.payments.GetSavedStarGifts(
user_id=peer, peer=peer,
offset=offset, offset=offset,
limit=limit 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_value
), ),
sleep_threshold=60 sleep_threshold=60
) )
users = {u.id: u for u in r.users} users = {i.id: i for i in r.users}
chats = {i.id: i for i in r.chats}
user_star_gifts = [ user_star_gifts = [
await types.Gift._parse_user(self, gift, users) await types.Gift._parse_saved(self, gift, users, chats)
for gift in r.gifts for gift in r.gifts
] ]

View file

@ -17,7 +17,7 @@
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>. # along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
import logging import logging
from typing import Union from typing import Optional, Union
import pyrogram import pyrogram
from pyrogram import raw from pyrogram import raw
@ -25,10 +25,15 @@ from pyrogram import raw
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
class GetUserGiftsCount: class GetChatGiftsCount:
async def get_user_gifts_count( async def get_chat_gifts_count(
self: "pyrogram.Client", self: "pyrogram.Client",
chat_id: Union[int, str] chat_id: Union[int, 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
) -> int: ) -> int:
"""Get the total count of star gifts of specified user. """Get the total count of star gifts of specified user.
@ -40,23 +45,40 @@ class GetUserGiftsCount:
For your personal cloud (Saved Messages) you can simply use "me" or "self". 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). For a contact that exists in your Telegram address book you can use his phone number (str).
exclude_unsaved (``bool``, *optional*):
Exclude unsaved star gifts.
exclude_saved (``bool``, *optional*):
Exclude saved star gifts.
exclude_unlimited (``bool``, *optional*):
Exclude unlimited star gifts.
exclude_limited (``bool``, *optional*):
Exclude limited star gifts.
exclude_upgraded (``bool``, *optional*):
Exclude upgraded star gifts.
Returns: Returns:
``int``: On success, the star gifts count is returned. ``int``: On success, the star gifts count is returned.
Example: Example:
.. code-block:: python .. code-block:: python
await app.get_user_gifts_count(chat_id) await app.get_chat_gifts_count(chat_id)
""" """
peer = await self.resolve_peer(chat_id) peer = await self.resolve_peer(chat_id)
if not isinstance(peer, (raw.types.InputPeerUser, raw.types.InputPeerSelf)):
raise ValueError("chat_id must belong to a user.")
r = await self.invoke( r = await self.invoke(
raw.functions.payments.GetUserStarGifts( raw.functions.payments.GetSavedStarGifts(
user_id=peer, peer=peer,
offset="", offset="",
exclude_unsaved=exclude_unsaved,
exclude_saved=exclude_saved,
exclude_unlimited=exclude_unlimited,
exclude_limited=exclude_limited,
exclude_unique=exclude_upgraded,
limit=1 limit=1
) )
) )

View file

@ -45,7 +45,9 @@ class HideGift:
""" """
r = await self.invoke( r = await self.invoke(
raw.functions.payments.SaveStarGift( raw.functions.payments.SaveStarGift(
msg_id=message_id, stargift=raw.types.InputSavedStarGiftUser(
msg_id=message_id
),
unsave=True unsave=True
) )
) )

View file

@ -44,7 +44,9 @@ class ShowGift:
""" """
r = await self.invoke( r = await self.invoke(
raw.functions.payments.SaveStarGift( raw.functions.payments.SaveStarGift(
msg_id=message_id, stargift=raw.types.InputSavedStarGiftUser(
msg_id=message_id
),
unsave=False unsave=False
) )
) )

View file

@ -19,7 +19,7 @@
from typing import Union from typing import Union
import pyrogram import pyrogram
from pyrogram import raw, errors from pyrogram import errors, raw
class TransferGift: class TransferGift:
@ -58,13 +58,17 @@ class TransferGift:
try: try:
await self.invoke( await self.invoke(
raw.functions.payments.TransferStarGift( raw.functions.payments.TransferStarGift(
msg_id=message_id, stargift=raw.types.InputSavedStarGiftUser(
msg_id=message_id
),
to_id=peer to_id=peer
) )
) )
except errors.PaymentRequired: except errors.PaymentRequired:
invoice = raw.types.InputInvoiceStarGiftTransfer( invoice = raw.types.InputInvoiceStarGiftTransfer(
msg_id=message_id, stargift=raw.types.InputSavedStarGiftUser(
msg_id=message_id
),
to_id=peer to_id=peer
) )

View file

@ -19,7 +19,7 @@
from typing import Optional from typing import Optional
import pyrogram import pyrogram
from pyrogram import raw, errors from pyrogram import errors, raw
class UpgradeGift: class UpgradeGift:
@ -51,13 +51,17 @@ class UpgradeGift:
try: try:
await self.invoke( await self.invoke(
raw.functions.payments.UpgradeStarGift( raw.functions.payments.UpgradeStarGift(
msg_id=message_id, stargift=raw.types.InputSavedStarGiftUser(
msg_id=message_id
),
keep_original_details=keep_details keep_original_details=keep_details
) )
) )
except errors.PaymentRequired: except errors.PaymentRequired:
invoice = raw.types.InputInvoiceStarGiftUpgrade( invoice = raw.types.InputInvoiceStarGiftUpgrade(
msg_id=message_id, stargift=raw.types.InputSavedStarGiftUser(
msg_id=message_id
),
keep_original_details=keep_details keep_original_details=keep_details
) )

View file

@ -44,7 +44,11 @@ class SetEmojiStatus:
from pyrogram import types from pyrogram import types
# Set emoji status
await app.set_emoji_status(types.EmojiStatus(custom_emoji_id=1234567890987654321)) await app.set_emoji_status(types.EmojiStatus(custom_emoji_id=1234567890987654321))
# Set collectible emoji status
await app.set_emoji_status(types.EmojiStatus(collectible_id=1234567890987654321))
""" """
await self.invoke( await self.invoke(
raw.functions.account.UpdateEmojiStatus( raw.functions.account.UpdateEmojiStatus(

View file

@ -901,7 +901,7 @@ class Message(Object, Update):
gift_code = types.GiftCode._parse(client, action, chats) gift_code = types.GiftCode._parse(client, action, chats)
service_type = enums.MessageServiceType.GIFT_CODE service_type = enums.MessageServiceType.GIFT_CODE
elif isinstance(action, (raw.types.MessageActionStarGift, raw.types.MessageActionStarGiftUnique)): elif isinstance(action, (raw.types.MessageActionStarGift, raw.types.MessageActionStarGiftUnique)):
gift = await types.Gift._parse_action(client, message, users) gift = await types.Gift._parse_action(client, message, users, chats)
service_type = enums.MessageServiceType.GIFT service_type = enums.MessageServiceType.GIFT
elif isinstance(action, raw.types.MessageActionScreenshotTaken): elif isinstance(action, raw.types.MessageActionScreenshotTaken):
screenshot_taken = types.ScreenshotTaken() screenshot_taken = types.ScreenshotTaken()

View file

@ -18,12 +18,10 @@
# along with Pyrofork. If not, see <http://www.gnu.org/licenses/>. # along with Pyrofork. If not, see <http://www.gnu.org/licenses/>.
from datetime import datetime from datetime import datetime
from typing import Optional, List, Union from typing import List, Optional, Union
import pyrogram import pyrogram
from pyrogram import raw from pyrogram import raw, types, utils
from pyrogram import types
from pyrogram import utils
from ..object import Object from ..object import Object
@ -50,11 +48,15 @@ class Gift(Object):
Unique message identifier. Unique message identifier.
For unique gifts only. For unique gifts only.
name (``str``, *optional*):
Name of the star gift.
For unique gifts only.
title (``str``, *optional*): title (``str``, *optional*):
Title of the star gift. Title of the star gift.
For unique gifts only. For unique gifts only.
number (``int``, *optional*): collectible_id (``int``, *optional*):
Collectible number of the star gift. Collectible number of the star gift.
For unique gifts only. For unique gifts only.
@ -62,18 +64,27 @@ class Gift(Object):
Attributes of the star gift. Attributes of the star gift.
For unique gifts only. For unique gifts only.
date (``datetime``, *optional*): date (:py:obj:`~datetime.datetime`, *optional*):
Date when the star gift was received. Date when the star gift was received.
first_sale_date (``datetime``, *optional*): first_sale_date (:py:obj:`~datetime.datetime`, *optional*):
Date when the star gift was first purchased. Date when the star gift was first purchased.
last_sale_date (``datetime``, *optional*): last_sale_date (:py:obj:`~datetime.datetime`, *optional*):
Date when the star gift was last purchased. Date when the star gift was last purchased.
from_user (:obj:`~pyrogram.types.User`, *optional*): from_user (:obj:`~pyrogram.types.User`, *optional*):
User who sent the star gift. User who sent the star gift.
owner (:obj:`~pyrogram.types.Chat`, *optional*):
Current gift owner.
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.
price (``int``, *optional*): price (``int``, *optional*):
Price of this gift in stars. Price of this gift in stars.
@ -97,7 +108,7 @@ class Gift(Object):
can_upgrade (``bool``, *optional*): can_upgrade (``bool``, *optional*):
True, if the gift can be upgraded. True, if the gift can be upgraded.
can_export_at (``datetime``, *optional*): can_export_at (:py:obj:`~datetime.datetime`, *optional*):
Date when the gift can be exported via blockchain. Date when the gift can be exported via blockchain.
is_limited (``bool``, *optional*): is_limited (``bool``, *optional*):
@ -127,6 +138,13 @@ class Gift(Object):
is_birthday (``bool``, *optional*): is_birthday (``bool``, *optional*):
True, if the gift is a birthday gift. True, if the gift is a birthday gift.
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.
""" """
def __init__( def __init__(
@ -142,13 +160,17 @@ class Gift(Object):
first_sale_date: Optional[datetime] = None, first_sale_date: Optional[datetime] = None,
last_sale_date: Optional[datetime] = None, last_sale_date: Optional[datetime] = None,
from_user: Optional["types.User"] = None, from_user: Optional["types.User"] = None,
owner: Optional["types.Chat"] = None,
owner_name: Optional[str] = None,
owner_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,
transfer_price: Optional[int] = None, transfer_price: Optional[int] = None,
upgrade_message_id: Optional[int] = None, upgrade_message_id: Optional[int] = None,
name: Optional[str] = None,
title: Optional[str] = None, title: Optional[str] = None,
number: Optional[int] = None, collectible_id: Optional[int] = None,
attributes: Optional[List["types.GiftAttribute"]] = None, attributes: Optional[List["types.GiftAttribute"]] = None,
available_amount: Optional[int] = None, available_amount: Optional[int] = None,
total_amount: Optional[int] = None, total_amount: Optional[int] = None,
@ -162,7 +184,8 @@ class Gift(Object):
is_upgraded: Optional[bool] = None, is_upgraded: Optional[bool] = None,
is_refunded: Optional[bool] = None, is_refunded: Optional[bool] = None,
is_transferred: Optional[bool] = None, is_transferred: Optional[bool] = None,
is_birthday: Optional[bool] = None is_birthday: Optional[bool] = None,
raw: Optional["raw.base.StarGift"] = None
): ):
super().__init__(client) super().__init__(client)
@ -175,13 +198,17 @@ class Gift(Object):
self.first_sale_date = first_sale_date self.first_sale_date = first_sale_date
self.last_sale_date = last_sale_date self.last_sale_date = last_sale_date
self.from_user = from_user self.from_user = from_user
self.owner = owner
self.owner_name = owner_name
self.owner_address = owner_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
self.transfer_price = transfer_price self.transfer_price = transfer_price
self.upgrade_message_id = upgrade_message_id self.upgrade_message_id = upgrade_message_id
self.name = name
self.title = title self.title = title
self.number = number self.collectible_id = collectible_id
self.attributes = attributes self.attributes = attributes
self.available_amount = available_amount self.available_amount = available_amount
self.total_amount = total_amount self.total_amount = total_amount
@ -196,9 +223,19 @@ class Gift(Object):
self.is_refunded = is_refunded self.is_refunded = is_refunded
self.is_transferred = is_transferred self.is_transferred = is_transferred
self.is_birthday = is_birthday self.is_birthday = is_birthday
self.raw = raw
@staticmethod @staticmethod
async def _parse( async def _parse(client, gift, users={}, chats={}):
if isinstance(gift, raw.types.StarGift):
return await Gift._parse_regular(client, gift)
elif isinstance(gift, raw.types.StarGiftUnique):
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, client,
star_gift: "raw.types.StarGift", star_gift: "raw.types.StarGift",
) -> "Gift": ) -> "Gift":
@ -218,6 +255,7 @@ class Gift(Object):
is_birthday=getattr(star_gift, "birthday", None), is_birthday=getattr(star_gift, "birthday", None),
first_sale_date=utils.timestamp_to_datetime(getattr(star_gift, "first_sale_date", None)), first_sale_date=utils.timestamp_to_datetime(getattr(star_gift, "first_sale_date", None)),
last_sale_date=utils.timestamp_to_datetime(getattr(star_gift, "last_sale_date", None)), last_sale_date=utils.timestamp_to_datetime(getattr(star_gift, "last_sale_date", None)),
raw=star_gift,
client=client client=client
) )
@ -225,51 +263,59 @@ class Gift(Object):
async def _parse_unique( async def _parse_unique(
client, client,
star_gift: "raw.types.StarGiftUnique", star_gift: "raw.types.StarGiftUnique",
users users: dict = {},
chats: dict = {}
) -> "Gift": ) -> "Gift":
owner_id = utils.get_raw_peer_id(getattr(star_gift, "owner_id", None))
return Gift( return Gift(
id=star_gift.id, id=star_gift.id,
name=star_gift.slug,
title=star_gift.title, title=star_gift.title,
number=star_gift.num, collectible_id=star_gift.num,
attributes=types.List( attributes=types.List(
[await types.GiftAttribute._parse(client, attr, users) for attr in star_gift.attributes] [await types.GiftAttribute._parse(client, attr, users, chats) for attr in star_gift.attributes]
) 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=types.Chat._parse_chat(client, users.get(owner_id) or chats.get(owner_id)),
owner_name=getattr(star_gift, "owner_name", None),
owner_address=getattr(star_gift, "owner_address", None),
is_upgraded=True, is_upgraded=True,
raw=star_gift,
client=client client=client
) )
@staticmethod @staticmethod
async def _parse_user( async def _parse_saved(
client, client,
user_star_gift: "raw.types.UserStarGift", saved_gift: "raw.types.SavedStarGift",
users: dict users: dict = {},
chats: dict = {}
) -> "Gift": ) -> "Gift":
caption, caption_entities = ( caption, caption_entities = (
utils.parse_text_with_entities( utils.parse_text_with_entities(
client, getattr(user_star_gift, "message", None), users client, getattr(saved_gift, "message", None), users
) )
).values() ).values()
if isinstance(user_star_gift.gift, raw.types.StarGift): if isinstance(saved_gift.gift, raw.types.StarGift):
parsed_gift = await Gift._parse(client, user_star_gift.gift) parsed_gift = await Gift._parse_regular(client, saved_gift.gift)
elif isinstance(user_star_gift.gift, raw.types.StarGiftUnique): elif isinstance(saved_gift.gift, raw.types.StarGiftUnique):
parsed_gift = await Gift._parse_unique(client, user_star_gift.gift, users) parsed_gift = await Gift._parse_unique(client, saved_gift.gift, users, chats)
parsed_gift.date = utils.timestamp_to_datetime(saved_gift.date)
parsed_gift.date = utils.timestamp_to_datetime(user_star_gift.date) parsed_gift.is_name_hidden = getattr(saved_gift, "name_hidden", None)
parsed_gift.is_name_hidden = getattr(user_star_gift, "name_hidden", None) parsed_gift.is_saved = not saved_gift.unsaved if getattr(saved_gift, "unsaved", None) else None
parsed_gift.is_saved = not user_star_gift.unsaved if getattr(user_star_gift, "unsaved", None) else None parsed_gift.is_refunded = getattr(saved_gift, "refunded", None)
parsed_gift.is_refunded = getattr(user_star_gift, "refunded", None) parsed_gift.can_upgrade = getattr(saved_gift, "can_upgrade", None)
parsed_gift.can_upgrade = getattr(user_star_gift, "can_upgrade", None) parsed_gift.from_user = types.User._parse(client, users.get(utils.get_raw_peer_id(saved_gift.from_id), None))
parsed_gift.from_user = types.User._parse(client, users.get(user_star_gift.from_id))
parsed_gift.caption = caption parsed_gift.caption = caption
parsed_gift.caption_entities = caption_entities parsed_gift.caption_entities = caption_entities
parsed_gift.message_id = getattr(user_star_gift, "msg_id", None) parsed_gift.message_id = getattr(saved_gift, "msg_id", None)
parsed_gift.convert_price = getattr(user_star_gift, "convert_stars", None) parsed_gift.saved_id = getattr(saved_gift, "saved_id", None)
parsed_gift.upgrade_price = getattr(user_star_gift, "upgrade_stars", None) parsed_gift.convert_price = getattr(saved_gift, "convert_stars", None)
parsed_gift.transfer_price = getattr(user_star_gift, "transfer_stars", None) parsed_gift.upgrade_price = getattr(saved_gift, "upgrade_stars", None)
parsed_gift.can_export_at = utils.timestamp_to_datetime(getattr(user_star_gift, "can_export_at", None)) parsed_gift.transfer_price = getattr(saved_gift, "transfer_stars", None)
parsed_gift.can_export_at = utils.timestamp_to_datetime(getattr(saved_gift, "can_export_at", None))
return parsed_gift return parsed_gift
@ -278,12 +324,13 @@ class Gift(Object):
async def _parse_action( async def _parse_action(
client, client,
message: "raw.base.Message", message: "raw.base.Message",
users: dict users: dict = {},
chats: dict = {}
) -> "Gift": ) -> "Gift":
action = message.action # type: raw.types.MessageActionStarGift action = message.action # type: raw.types.MessageActionStarGift
if isinstance(action, raw.types.MessageActionStarGift): if isinstance(action, raw.types.MessageActionStarGift):
parsed_gift = await Gift._parse(client, action.gift) parsed_gift = await Gift._parse_regular(client, action.gift)
caption, caption_entities = ( caption, caption_entities = (
utils.parse_text_with_entities( utils.parse_text_with_entities(
@ -301,9 +348,10 @@ class Gift(Object):
parsed_gift.caption_entities = caption_entities parsed_gift.caption_entities = caption_entities
parsed_gift.convert_price = getattr(action, "convert_stars", None) parsed_gift.convert_price = getattr(action, "convert_stars", None)
parsed_gift.upgrade_price = getattr(action, "upgrade_stars", None) parsed_gift.upgrade_price = getattr(action, "upgrade_stars", None)
parsed_gift.message_id = getattr(action, "saved_id", message.id)
parsed_gift.upgrade_message_id = getattr(action, "upgrade_msg_id", None) parsed_gift.upgrade_message_id = getattr(action, "upgrade_msg_id", None)
elif isinstance(action, raw.types.MessageActionStarGiftUnique): elif isinstance(action, raw.types.MessageActionStarGiftUnique):
parsed_gift = await Gift._parse_unique(client, action.gift, users) parsed_gift = await Gift._parse_unique(client, action.gift, users, chats)
parsed_gift.is_upgraded = getattr(action, "upgrade", None) parsed_gift.is_upgraded = getattr(action, "upgrade", None)
parsed_gift.is_transferred = getattr(action, "transferred", None) parsed_gift.is_transferred = getattr(action, "transferred", None)
@ -311,13 +359,19 @@ class Gift(Object):
parsed_gift.is_refunded = getattr(action, "refunded", None) parsed_gift.is_refunded = getattr(action, "refunded", None)
parsed_gift.can_export_at = utils.timestamp_to_datetime(getattr(action, "can_export_at", None)) parsed_gift.can_export_at = utils.timestamp_to_datetime(getattr(action, "can_export_at", None))
parsed_gift.transfer_price = getattr(action, "transfer_stars", None) parsed_gift.transfer_price = getattr(action, "transfer_stars", None)
parsed_gift.message_id = getattr(action, "saved_id", None)
parsed_gift.upgrade_message_id = message.id
parsed_gift.date = utils.timestamp_to_datetime(message.date) parsed_gift.date = utils.timestamp_to_datetime(message.date)
parsed_gift.from_user = types.User._parse(client, users.get(utils.get_raw_peer_id(message.peer_id)))
parsed_gift.message_id = message.id
return parsed_gift return parsed_gift
@property
def link(self) -> Optional[str]:
if not self.name:
return None
return f"https://t.me/nft/{self.name}"
async def show(self) -> bool: async def show(self) -> bool:
"""Bound method *show* of :obj:`~pyrogram.types.Gift`. """Bound method *show* of :obj:`~pyrogram.types.Gift`.
@ -434,3 +488,30 @@ class Gift(Object):
message_id=self.message_id, message_id=self.message_id,
to_chat_id=to_chat_id to_chat_id=to_chat_id
) )
async def wear(self) -> bool:
"""Bound method *wear* of :obj:`~pyrogram.types.Gift`.
.. note::
This works for upgraded gifts only.
Use as a shortcut for:
.. code-block:: python
await client.set_emoji_status(types.EmojiStatus(gift_id=123))
Example:
.. code-block:: python
await star_gift.wear()
Returns:
``bool``: On success, True is returned.
"""
return self._client.set_emoji_status(
emoji_status=types.EmojiStatus(
gift_id=self.id
)
)

View file

@ -18,13 +18,10 @@
# along with Pyrofork. If not, see <http://www.gnu.org/licenses/>. # along with Pyrofork. If not, see <http://www.gnu.org/licenses/>.
from datetime import datetime from datetime import datetime
from typing import Optional, List from typing import List, Optional
import pyrogram import pyrogram
from pyrogram import raw from pyrogram import enums, raw, types, utils
from pyrogram import types
from pyrogram import enums
from pyrogram import utils
from ..object import Object from ..object import Object
@ -42,7 +39,7 @@ class GiftAttribute(Object):
Rarity of the attribute in permilles. Rarity of the attribute in permilles.
For example, 15 means 1.5%. So only 1.5% of such collectibles have this attribute. For example, 15 means 1.5%. So only 1.5% of such collectibles have this attribute.
date (``datetime``, *optional*): date (:py:obj:`~datetime.datetime`, *optional*):
Date when the gift was received. Date when the gift was received.
Available only if the original details are available. Available only if the original details are available.
@ -122,7 +119,8 @@ class GiftAttribute(Object):
async def _parse( async def _parse(
client, client,
attr: "raw.base.StarGiftAttribute", attr: "raw.base.StarGiftAttribute",
users users: dict,
chats: dict
) -> "GiftAttribute": ) -> "GiftAttribute":
caption = None caption = None
caption_entities = None caption_entities = None
@ -140,8 +138,10 @@ class GiftAttribute(Object):
client, attr.message, users client, attr.message, users
)).values() )).values()
from_user = types.User._parse(client, users.get(attr.sender_id)) sender_id = utils.get_raw_peer_id(attr.sender_id)
to_user = types.User._parse(client, users.get(attr.recipient_id)) recipient_id = utils.get_raw_peer_id(attr.recipient_id)
from_user = types.User._parse(client, users.get(sender_id))
to_user = types.User._parse(client, users.get(recipient_id))
return GiftAttribute( return GiftAttribute(
name=getattr(attr, "name", None), name=getattr(attr, "name", None),

View file

@ -80,6 +80,9 @@ class Chat(Object):
True, if paid reactions are available in chat. True, if paid reactions are available in chat.
Returned only in :meth:`~pyrogram.Client.get_chat`. Returned only in :meth:`~pyrogram.Client.get_chat`.
is_gifts_available (``bool``, *optional*):
True, if star gifts can be received by this chat.
title (``str``, *optional*): title (``str``, *optional*):
Title, for supergroups, channels and basic group chats. Title, for supergroups, channels and basic group chats.
@ -232,6 +235,7 @@ class Chat(Object):
is_antispam: bool = None, is_antispam: bool = None,
is_paid_reactions_available: bool = None, is_paid_reactions_available: bool = None,
is_slowmode_enabled: bool = None, is_slowmode_enabled: bool = None,
is_gifts_available: bool = None,
title: str = None, title: str = None,
username: str = None, username: str = None,
first_name: str = None, first_name: str = None,
@ -285,6 +289,7 @@ class Chat(Object):
self.is_antispam = is_antispam self.is_antispam = is_antispam
self.is_paid_reactions_available = is_paid_reactions_available self.is_paid_reactions_available = is_paid_reactions_available
self.is_slowmode_enabled = is_slowmode_enabled self.is_slowmode_enabled = is_slowmode_enabled
self.is_gifts_available = is_gifts_available
self.title = title self.title = title
self.username = username self.username = username
self.first_name = first_name self.first_name = first_name
@ -325,7 +330,9 @@ class Chat(Object):
return " ".join(filter(None, [self.first_name, self.last_name])) or self.title or None return " ".join(filter(None, [self.first_name, self.last_name])) or self.title or None
@staticmethod @staticmethod
def _parse_user_chat(client, user: raw.types.User) -> "Chat": def _parse_user_chat(client, user: raw.types.User) -> Optional["Chat"]:
if user is None or isinstance(user, raw.types.UserEmpty):
return None
peer_id = user.id peer_id = user.id
return Chat( return Chat(
@ -348,7 +355,9 @@ class Chat(Object):
) )
@staticmethod @staticmethod
def _parse_chat_chat(client, chat: raw.types.Chat) -> "Chat": def _parse_chat_chat(client, chat: raw.types.Chat) -> Optional["Chat"]:
if chat is None or isinstance(chat, raw.types.ChatEmpty):
return None
peer_id = -chat.id peer_id = -chat.id
active_usernames = getattr(chat, "usernames", []) active_usernames = getattr(chat, "usernames", [])
usernames = None usernames = None
@ -373,7 +382,9 @@ class Chat(Object):
) )
@staticmethod @staticmethod
def _parse_channel_chat(client, channel: raw.types.Channel) -> "Chat": def _parse_channel_chat(client, channel: raw.types.Channel) -> Optional["Chat"]:
if channel is None:
return None
peer_id = utils.get_channel_id(channel.id) peer_id = utils.get_channel_id(channel.id)
restriction_reason = getattr(channel, "restriction_reason", []) restriction_reason = getattr(channel, "restriction_reason", [])
user_name = getattr(channel, "username", None) user_name = getattr(channel, "username", None)
@ -514,6 +525,8 @@ class Chat(Object):
parsed_chat.is_participants_hidden = full_chat.participants_hidden parsed_chat.is_participants_hidden = full_chat.participants_hidden
parsed_chat.is_antispam = full_chat.antispam parsed_chat.is_antispam = full_chat.antispam
parsed_chat.is_paid_reactions_available = full_chat.paid_reactions_available parsed_chat.is_paid_reactions_available = full_chat.paid_reactions_available
parsed_chat.is_gifts_available = getattr(full_chat, "stargifts_available", None)
parsed_chat.gifts_count = getattr(full_chat, "stargifts_count", None)
parsed_chat.folder_id = getattr(full_chat, "folder_id", None) parsed_chat.folder_id = getattr(full_chat, "folder_id", None)
linked_chat_raw = chats.get(full_chat.linked_chat_id, None) linked_chat_raw = chats.get(full_chat.linked_chat_id, None)
@ -532,13 +545,12 @@ class Chat(Object):
parsed_chat.send_as_chat = Chat._parse_chat(client, send_as_raw) parsed_chat.send_as_chat = Chat._parse_chat(client, send_as_raw)
if getattr(full_chat, "stories"): if getattr(full_chat, "stories"):
peer_stories: raw.types.PeerStories = full_chat.stories
parsed_chat.stories = types.List( parsed_chat.stories = types.List(
[ [
await types.Story._parse( await types.Story._parse(
client, story, peer_stories.peer client, story, full_chat.stories.peer
) )
for story in peer_stories.stories for story in full_chat.stories.stories
] ]
) or None ) or None