# 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/>.
from datetime import datetime
from typing import Dict, List, Optional, Union
import pyrogram
from pyrogram import raw, types, utils, enums
from ..object import Object
[docs]
class Gift(Object):
"""Describes a gift or an upgraded gift that can be transferred to another owner or transferred to the TON blockchain as an NFT.
Parameters:
id (``int``):
Unique identifier of the gift.
type (:obj:`~pyrogram.enums.GiftType`):
Type of the gift.
origin (:obj:`~pyrogram.enums.UpgradedGiftOrigin`, *optional*):
Origin of the gift.
received_gift_id (``str``, *optional*):
Unique identifier of the received gift for the current user.
regular_gift_id (``int``, *optional*):
Unique identifier of the regular gift from which the gift was upgraded.
publisher_chat (:obj:`~pyrogram.types.Chat`, *optional*):
Information about the chat that published the gift.
sticker (:obj:`~pyrogram.types.Sticker`, *optional*):
The sticker that represents the gift.
text (:obj:`~pyrogram.types.FormattedText`, *optional*):
Message added to the gift.
date (:py:obj:`~datetime.datetime`, *optional*):
Date when the gift was sent or received.
first_sale_date (:py:obj:`~datetime.datetime`, *optional*):
Date when the gift was sent for the first time.
For sold out gifts only.
last_sale_date (:py:obj:`~datetime.datetime`, *optional*):
Date when the gift was sent for the last time.
For sold out gifts only.
locked_until_date (:py:obj:`~datetime.datetime`, *optional*):
Date when the gift will be available for purchase.
craft_date (:py:obj:`~datetime.datetime`, *optional*):
Date when the gift can be used to craft another gift can be in the past.
sender (:obj:`~pyrogram.types.Chat`, *optional*):
User or a chat that sent the gift.
receiver (:obj:`~pyrogram.types.Chat`, *optional*):
User or a chat that received the gift.
host (:obj:`~pyrogram.types.Chat`, *optional*):
User or the chat to which the upgraded gift was assigned from blockchain.
owner (:obj:`~pyrogram.types.Chat`, *optional*):
User or the chat that owns the gift.
owner_address (``str``, *optional*):
Address of the gift owner in TON blockchain.
owner_name (``str``, *optional*):
Name of the user who received the star gift.
gift_address (``str``, *optional*):
Address of the gift in TON blockchain.
title (``str``, *optional*):
The title of the upgraded gift.
name (``str``, *optional*):
Unique name of the upgraded gift.
model (:obj:`~pyrogram.types.GiftAttribute`, *optional*):
Model of the upgraded gift.
symbol (:obj:`~pyrogram.types.GiftAttribute`, *optional*):
Symbol of the upgraded gift.
backdrop (:obj:`~pyrogram.types.GiftAttribute`, *optional*):
Backdrop of the upgraded gift.
original_details (:obj:`~pyrogram.types.UpgradedGiftOriginalDetails`, *optional*):
Information about the originally sent gift.
total_upgraded_count (``int``, *optional*):
Total number of gifts that were upgraded from the same gift.
max_upgraded_count (``int``, *optional*):
The maximum number of gifts that can be upgraded from the same gift.
available_resale_count (``int``, *optional*):
Total number of gifts that can be bought from other users on the market.
unique_gift_number (``int``, *optional*):
Unique number of the gift among gifts upgraded from the same gift after upgrade.
unique_gift_variant_count (``int``, *optional*):
The total number of different unique gifts that can be obtained by upgrading the gift.
star_count (``int``, *optional*):
Number of Telegram Stars that must be paid for the gift.
default_sell_star_count (``int``, *optional*):
Number of Telegram Stars that can be claimed by the receiver instead of the regular gift by default.
convert_star_count (``int``, *optional*):
Number of Telegram Stars that can be claimed by the receiver instead of the gift; omitted if the gift cannot be converted to Telegram Stars.
upgrade_star_count (``int``, *optional*):
Number of Telegram Stars that must be paid to upgrade the gift.
transfer_star_count (``int``, *optional*):
Number of Telegram Stars that must be paid to transfer the upgraded gift.
drop_original_details_star_count (``int``, *optional*):
Number of Telegram Stars that must be paid to drop original details of the upgraded gift.
minimum_resell_star_count (``int``, *optional*):
Number of Telegram Stars for which sales begin on the market for the gift.
minimum_offer_star_count (``int``, *optional*):
Number of Telegram Stars required to make an offer for the gift.
prepaid_upgrade_star_count (``int``, *optional*):
Number of Telegram Stars that were paid by the sender for the ability to upgrade the gift.
prepaid_upgrade_hash (``str``, *optional*):
If non-empty, then the user can pay for an upgrade of the gift using :meth:`~pyrogram.Client.buy_gift_upgrade`.
auction_info (:obj:`~pyrogram.types.GiftAuction`, *optional*):
Information about the auction on which the gift can be purchased.
resale_parameters (:obj:`~pyrogram.types.GiftResaleParameters`, *optional*):
Resale parameters of the gift.
user_limits (:obj:`~pyrogram.types.GiftPurchaseLimit`, *optional*):
Number of times the gift can be purchased by the current user.
overall_limits (:obj:`~pyrogram.types.GiftPurchaseLimit`, *optional*):
Number of times the gift can be purchased all users.
value_currency (``str``, *optional*):
ISO 4217 currency code of the currency in which value of the gift is represented.
value_amount (``int``, *optional*):
Estimated value of the gift; in the smallest units of the currency.
value_usd_amount (``int``, *optional*):
Estimated value of the gift in USD cents.
last_resale_currency (``str``, *optional*):
For gifts bought from other users, the currency in which the payment for the gift was done.
Currently, one of “XTR” for Telegram Stars or “TON” for toncoins.
last_resale_amount (``int``, *optional*):
For gifts bought from other users, the price paid for the gift in either Telegram Stars or nanotoncoins.
next_send_date (:py:obj:`~datetime.datetime`, *optional*):
Date when the gift can be sent next time by the current user.
next_transfer_date (:py:obj:`~datetime.datetime`, *optional*):
Date when the gift can be transferred to another owner.
next_resale_date (:py:obj:`~datetime.datetime`, *optional*):
Date when the gift can be resold to another user.
export_date (:py:obj:`~datetime.datetime`, *optional*):
Date when the gift can be transferred to the TON blockchain as an NFT.
collection_ids (List of ``int``, *optional*):
Identifiers of collections to which the gift is added.
Only for the receiver of the gift.
used_theme_chat_id (``int``, *optional*):
Identifier of the chat for which the gift is used to set a theme.
craft_probability_per_mille (``int``, *optional*):
Probability that the gift adds to the chance of successful crafting of a new gift.
has_colors (``bool``, *optional*):
True, if the gift can be used to customize user's name and backgrounds.
is_auction (``bool``, *optional*):
True, if the gift can be purchased only on an auction.
is_private (``bool``, *optional*):
True, if the sender and gift text are shown only to the gift receiver.
is_saved (``bool``, *optional*):
True, if the gift is displayed on the chat's profile page.
is_pinned (``bool``, *optional*):
True, if the gift is pinned to the top of the chat's profile page.
is_limited (``bool``, *optional*):
True, if the number of gifts is limited.
is_limited_per_user (``bool``, *optional*):
True, if the number of gifts per user is limited.
is_sold_out (``bool``, *optional*):
True, if the gift is sold out.
is_burned (``bool``, *optional*):
True, if the gift was used to craft another gift.
is_crafted (``bool``, *optional*):
True, if the gift was craft from another gifts.
is_premium (``bool``, *optional*):
True, if the gift can be bought only by Telegram Premium subscribers.
is_for_birthday (``bool``, *optional*):
True, if the gift is a birthday gift.
is_theme_available (``bool``, *optional*):
True, if the gift can be used to set a theme in a chat.
is_upgrade_separate (``bool``, *optional*):
True, if the upgrade was bought after the gift was sent.
is_name_hidden (``bool``, *optional*):
True, if the owner name of the gift is hidden.
can_be_upgraded (``bool``, *optional*):
True, if the gift can be upgraded to a unique gift.
can_be_transferred (``bool``, *optional*):
True, if the upgraded gift can be transferred to another owner.
can_send_purchase_offer (``bool``, *optional*):
True, if an offer to purchase the gift can be sent using :meth:`~pyrogram.Client.send_gift_purchase_offer`.
was_converted (``bool``, *optional*):
True, if the gift was converted to Telegram Stars.
Only for the receiver of the gift.
was_upgraded (``bool``, *optional*):
True, if the gift was upgraded to a unique gift.
was_refunded (``bool``, *optional*):
True, if the gift was refunded and isn't available anymore.
raw (:obj:`~pyrogram.raw.base.StarGift` | :obj:`~pyrogram.raw.base.SavedStarGift`):
The raw object as received from the server.
link (``str``, *property*):
A link to the gift.
owned_gift_id (``str``, *property*):
Unique identifier of the gift.
"""
# TODO: Add background_emoji_id and pattern_color fields from raw.types.StarGiftAttributeModel
def __init__(
self,
*,
client: "pyrogram.Client" = None,
id: int,
type: "enums.GiftType",
origin: Optional["enums.UpgradedGiftOrigin"] = None,
received_gift_id: Optional[str] = None,
regular_gift_id: Optional[int] = None,
publisher_chat: Optional["types.Chat"] = None,
sticker: Optional["types.Sticker"] = None,
text: Optional["types.FormattedText"] = None,
date: Optional[datetime] = None,
first_sale_date: Optional[datetime] = None,
last_sale_date: Optional[datetime] = None,
locked_until_date: Optional[datetime] = None,
craft_date: Optional[datetime] = None,
sender: Optional["types.Chat"] = None,
receiver: Optional["types.Chat"] = None,
host: Optional["types.Chat"] = None,
owner: Optional["types.Chat"] = None,
owner_address: Optional[str] = None,
owner_name: Optional[str] = None,
gift_address: Optional[str] = None,
title: Optional[str] = None,
name: Optional[str] = None,
model: Optional["types.GiftAttribute"] = None,
symbol: Optional["types.GiftAttribute"] = None,
backdrop: Optional["types.GiftAttribute"] = None,
original_details: Optional["types.UpgradedGiftOriginalDetails"] = None,
total_upgraded_count: Optional[int] = None,
max_upgraded_count: Optional[int] = None,
available_resale_count: Optional[int] = None,
unique_gift_variant_count: Optional[int] = None,
unique_gift_number: Optional[int] = None,
star_count: Optional[int] = None,
default_sell_star_count: Optional[int] = None,
convert_star_count: Optional[int] = None,
upgrade_star_count: Optional[int] = None,
transfer_star_count: Optional[int] = None,
drop_original_details_star_count: Optional[int] = None,
minimum_resell_star_count: Optional[int] = None,
minimum_offer_star_count: Optional[int] = None,
prepaid_upgrade_star_count: Optional[int] = None,
prepaid_upgrade_hash: Optional[str] = None,
auction_info: Optional["types.GiftAuction"] = None,
resale_parameters: Optional["types.GiftResaleParameters"] = None,
user_limits: Optional["types.GiftPurchaseLimit"] = None,
overall_limits: Optional["types.GiftPurchaseLimit"] = None,
value_currency: Optional[str] = None,
value_amount: Optional[int] = None,
value_usd_amount: Optional[int] = None,
last_resale_currency: Optional[str] = None,
last_resale_amount: Optional[int] = None,
next_send_date: Optional[datetime] = None,
next_transfer_date: Optional[datetime] = None,
next_resale_date: Optional[datetime] = None,
export_date: Optional[datetime] = None,
collection_ids: Optional[List[int]] = None,
used_theme_chat_id: Optional[int] = None,
craft_probability_per_mille: Optional[int] = None,
has_colors: Optional[bool] = None,
is_auction: Optional[bool] = None,
is_private: Optional[bool] = None,
is_saved: Optional[bool] = None,
is_pinned: Optional[bool] = None,
is_limited: Optional[bool] = None,
is_limited_per_user: Optional[bool] = None,
is_sold_out: Optional[bool] = None,
is_burned: Optional[bool] = None,
is_crafted: Optional[bool] = None,
is_premium: Optional[bool] = None,
is_for_birthday: Optional[bool] = None,
is_theme_available: Optional[bool] = None,
is_upgrade_separate: Optional[bool] = None,
is_name_hidden: Optional[bool] = None,
can_be_upgraded: Optional[bool] = None,
can_be_transferred: Optional[bool] = None,
can_send_purchase_offer: Optional[bool] = None,
was_converted: Optional[bool] = None,
was_upgraded: Optional[bool] = None,
was_refunded: Optional[bool] = None,
raw: Optional[
Union[
"raw.base.StarGift",
"raw.base.SavedStarGift"
]
]
):
super().__init__(client)
self.id = id
self.type = type
self.origin = origin
self.received_gift_id = received_gift_id
self.regular_gift_id = regular_gift_id
self.publisher_chat = publisher_chat
self.sticker = sticker
self.text = text
self.date = date
self.first_sale_date = first_sale_date
self.last_sale_date = last_sale_date
self.locked_until_date = locked_until_date
self.craft_date = craft_date
self.sender = sender
self.receiver = receiver
self.host = host
self.owner = owner
self.owner_address = owner_address
self.owner_name = owner_name
self.gift_address = gift_address
self.title = title
self.name = name
self.model = model
self.symbol = symbol
self.backdrop = backdrop
self.original_details = original_details
self.total_upgraded_count = total_upgraded_count
self.max_upgraded_count = max_upgraded_count
self.available_resale_count = available_resale_count
self.unique_gift_variant_count = unique_gift_variant_count
self.unique_gift_number = unique_gift_number
self.star_count = star_count
self.default_sell_star_count = default_sell_star_count
self.convert_star_count = convert_star_count
self.upgrade_star_count = upgrade_star_count
self.transfer_star_count = transfer_star_count
self.drop_original_details_star_count = drop_original_details_star_count
self.minimum_resell_star_count = minimum_resell_star_count
self.minimum_offer_star_count = minimum_offer_star_count
self.prepaid_upgrade_star_count = prepaid_upgrade_star_count
self.prepaid_upgrade_hash = prepaid_upgrade_hash
self.auction_info = auction_info
self.resale_parameters = resale_parameters
self.user_limits = user_limits
self.overall_limits = overall_limits
self.value_currency = value_currency
self.value_amount = value_amount
self.value_usd_amount = value_usd_amount
self.last_resale_currency = last_resale_currency
self.last_resale_amount = last_resale_amount
self.next_send_date = next_send_date
self.next_transfer_date = next_transfer_date
self.next_resale_date = next_resale_date
self.export_date = export_date
self.collection_ids = collection_ids
self.used_theme_chat_id = used_theme_chat_id
self.craft_probability_per_mille = craft_probability_per_mille
self.has_colors = has_colors
self.is_auction = is_auction
self.is_private = is_private
self.is_saved = is_saved
self.is_pinned = is_pinned
self.is_limited = is_limited
self.is_limited_per_user = is_limited_per_user
self.is_sold_out = is_sold_out
self.is_burned = is_burned
self.is_crafted = is_crafted
self.is_premium = is_premium
self.is_for_birthday = is_for_birthday
self.is_theme_available = is_theme_available
self.is_upgrade_separate = is_upgrade_separate
self.is_name_hidden = is_name_hidden
self.can_be_upgraded = can_be_upgraded
self.can_be_transferred = can_be_transferred
self.can_send_purchase_offer = can_send_purchase_offer
self.was_converted = was_converted
self.was_upgraded = was_upgraded
self.was_refunded = was_refunded
self.raw = raw
@staticmethod
async def _parse(
client: "pyrogram.Client",
gift: Union[
"raw.base.StarGift",
"raw.base.SavedStarGift",
"raw.types.MessageActionStarGift",
"raw.types.MessageActionStarGiftUnique"
],
receiver: Optional[Union["raw.base.User", "raw.base.Chat"]] = None,
users: Dict[int, "raw.base.User"] = {},
chats: Dict[int, "raw.base.Chat"] = {}
):
if isinstance(gift, raw.types.StarGift):
return await Gift._parse_regular(client, gift, receiver, users, chats)
elif isinstance(gift, raw.types.StarGiftUnique):
return await Gift._parse_upgraded(client, gift, receiver, users, chats)
elif isinstance(gift, raw.types.SavedStarGift):
return await Gift._parse_received(client, gift, receiver, users, chats)
elif isinstance(gift, (raw.types.MessageActionStarGift, raw.types.MessageActionStarGiftUnique)):
return await Gift._parse_action(client, gift, receiver, users, chats)
@staticmethod
async def _parse_regular(
client: "pyrogram.Client",
star_gift: "raw.types.StarGift",
receiver: Optional[Union["raw.base.User", "raw.base.Chat"]] = None,
users: Dict[int, "raw.base.User"] = {},
chats: Dict[int, "raw.base.Chat"] = {}
) -> "Gift":
if not isinstance(star_gift, raw.types.StarGift):
return
doc = star_gift.sticker
attributes = {type(i): i for i in doc.attributes}
# TODO?
# auction_slug
# background
return Gift(
id=star_gift.id,
type=enums.GiftType.REGULAR,
sticker=await types.Sticker._parse(client, doc, attributes),
star_count=star_gift.stars,
convert_star_count=star_gift.convert_stars,
upgrade_star_count=star_gift.upgrade_stars,
title=star_gift.title,
available_resale_count=star_gift.availability_resale,
user_limits=types.GiftPurchaseLimit._parse(star_gift.per_user_total, star_gift.per_user_remains),
overall_limits=types.GiftPurchaseLimit._parse(star_gift.availability_total, star_gift.availability_remains),
is_auction=star_gift.auction,
is_limited=star_gift.limited,
is_sold_out=star_gift.sold_out,
is_for_birthday=star_gift.birthday,
is_premium=star_gift.require_premium,
is_limited_per_user=star_gift.limited_per_user,
has_colors=star_gift.peer_color_available,
first_sale_date=utils.timestamp_to_datetime(star_gift.first_sale_date),
last_sale_date=utils.timestamp_to_datetime(star_gift.last_sale_date),
locked_until_date=utils.timestamp_to_datetime(star_gift.locked_until_date),
publisher_chat=types.Chat._parse_chat(client, chats.get(utils.get_raw_peer_id(star_gift.released_by))),
auction_info=types.GiftAuction._parse(star_gift),
unique_gift_variant_count=star_gift.upgrade_variants,
minimum_resell_star_count=star_gift.resell_min_stars,
raw=star_gift,
client=client
)
@staticmethod
async def _parse_upgraded(
client: "pyrogram.Client",
star_gift: "raw.types.StarGiftUnique",
receiver: Optional[Union["raw.base.User", "raw.base.Chat"]] = None,
users: Dict[int, "raw.base.User"] = {},
chats: Dict[int, "raw.base.Chat"] = {}
) -> "Gift":
if not isinstance(star_gift, raw.types.StarGiftUnique):
return
raw_host_id = utils.get_raw_peer_id(star_gift.host_id)
raw_owner_id = utils.get_raw_peer_id(star_gift.owner_id)
model = None
symbol = None
backdrop = None
original_details = None
for attr in star_gift.attributes:
if isinstance(attr, raw.types.StarGiftAttributeModel):
model = await types.GiftAttribute._parse(client, attr, users, chats)
elif isinstance(attr, raw.types.StarGiftAttributePattern):
symbol = await types.GiftAttribute._parse(client, attr, users, chats)
elif isinstance(attr, raw.types.StarGiftAttributeBackdrop):
backdrop = await types.GiftAttribute._parse(client, attr, users, chats)
elif isinstance(attr, raw.types.StarGiftAttributeOriginalDetails):
original_details = await types.UpgradedGiftOriginalDetails._parse(client, attr, users, chats)
# TODO?
# peer_color
return Gift(
id=star_gift.id,
type=enums.GiftType.UPGRADED,
can_send_purchase_offer=star_gift.offer_min_stars is not None,
gift_address=star_gift.gift_address,
host=types.Chat._parse_chat(client, users.get(raw_host_id) or chats.get(raw_host_id)),
is_burned=star_gift.burned,
is_crafted=star_gift.crafted,
is_premium=star_gift.require_premium,
is_theme_available=star_gift.theme_available,
max_upgraded_count=star_gift.availability_total,
minimum_offer_star_count=star_gift.offer_min_stars,
model=model,
symbol=symbol,
backdrop=backdrop,
title=star_gift.title,
name=star_gift.slug,
unique_gift_number=star_gift.num,
original_details=original_details,
owner=types.Chat._parse_chat(client, users.get(raw_owner_id) or chats.get(raw_owner_id)),
owner_address=star_gift.owner_address,
owner_name=star_gift.owner_name,
publisher_chat=types.Chat._parse_chat(client, chats.get(utils.get_raw_peer_id(star_gift.released_by))),
regular_gift_id=star_gift.gift_id,
resale_parameters=types.GiftResaleParameters._parse(star_gift.resell_amount, star_gift.resale_ton_only),
total_upgraded_count=star_gift.availability_issued,
used_theme_chat_id=utils.get_peer_id(star_gift.theme_peer) if star_gift.theme_peer else None,
craft_probability_per_mille=star_gift.craft_chance_permille,
value_amount=star_gift.value_amount,
value_currency=star_gift.value_currency,
value_usd_amount=star_gift.value_usd_amount,
raw=star_gift,
client=client
)
@staticmethod
async def _parse_received(
client,
saved_gift: "raw.types.SavedStarGift",
receiver: Optional[Union["raw.base.User", "raw.base.Chat"]] = None,
users: Dict[int, "raw.base.User"] = {},
chats: Dict[int, "raw.base.Chat"] = {}
) -> "Gift":
if not isinstance(saved_gift, raw.types.SavedStarGift):
return
if isinstance(saved_gift.gift, raw.types.StarGift):
parsed_gift = await Gift._parse_regular(client, saved_gift.gift, users=users, chats=chats)
elif isinstance(saved_gift.gift, raw.types.StarGiftUnique):
parsed_gift = await Gift._parse_upgraded(client, saved_gift.gift, users=users, chats=chats)
raw_from_id = utils.get_raw_peer_id(saved_gift.from_id)
if saved_gift.msg_id:
parsed_gift.received_gift_id = str(saved_gift.msg_id)
elif saved_gift.saved_id:
parsed_gift.received_gift_id = str(saved_gift.saved_id)
parsed_gift.date = utils.timestamp_to_datetime(saved_gift.date) or parsed_gift.date
parsed_gift.receiver = types.Chat._parse_chat(client, receiver) or parsed_gift.receiver
parsed_gift.is_name_hidden = saved_gift.name_hidden or parsed_gift.is_name_hidden
parsed_gift.is_saved = not saved_gift.unsaved or parsed_gift.is_saved
parsed_gift.was_refunded = saved_gift.refunded or parsed_gift.was_refunded
parsed_gift.can_be_upgraded = saved_gift.can_upgrade or parsed_gift.can_be_upgraded
parsed_gift.is_pinned = saved_gift.pinned_to_top or parsed_gift.is_pinned
parsed_gift.is_upgrade_separate = saved_gift.upgrade_separate or parsed_gift.is_upgrade_separate
parsed_gift.sender = types.Chat._parse_chat(client, users.get(raw_from_id) or chats.get(raw_from_id)) or parsed_gift.sender
parsed_gift.text = types.FormattedText._parse(client, saved_gift.message) or parsed_gift.text
parsed_gift.convert_star_count = saved_gift.convert_stars or parsed_gift.convert_star_count
parsed_gift.upgrade_star_count = saved_gift.upgrade_stars or parsed_gift.upgrade_star_count
parsed_gift.export_date = utils.timestamp_to_datetime(saved_gift.can_export_at) or parsed_gift.export_date
parsed_gift.transfer_star_count = saved_gift.transfer_stars or parsed_gift.transfer_star_count
parsed_gift.next_transfer_date = utils.timestamp_to_datetime(saved_gift.can_transfer_at) or parsed_gift.next_transfer_date
parsed_gift.next_resale_date = utils.timestamp_to_datetime(saved_gift.can_resell_at) or parsed_gift.next_resale_date
parsed_gift.craft_date = utils.timestamp_to_datetime(saved_gift.can_craft_at) or parsed_gift.craft_date
parsed_gift.collection_ids = list(saved_gift.collection_id) if saved_gift.collection_id else parsed_gift.collection_ids
parsed_gift.prepaid_upgrade_hash = saved_gift.prepaid_upgrade_hash or parsed_gift.prepaid_upgrade_hash
parsed_gift.drop_original_details_star_count = saved_gift.drop_original_details_stars or parsed_gift.drop_original_details_star_count
parsed_gift.unique_gift_number = saved_gift.gift_num or parsed_gift.unique_gift_number
parsed_gift.raw = saved_gift
return parsed_gift
@staticmethod
async def _parse_action(
client,
action_gift: Union[
"raw.types.MessageActionStarGift",
"raw.types.MessageActionStarGiftUnique"
],
receiver: Optional[Union["raw.base.User", "raw.base.Chat"]] = None,
users: Dict[int, "raw.base.User"] = {},
chats: Dict[int, "raw.base.Chat"] = {}
) -> "Gift":
# TODO: receiver is always the action.peer but sender needs from_id; verify correctness for all gift types
if isinstance(action_gift, raw.types.MessageActionStarGift):
# auction_acquired
# upgrade_msg_id
# peer
# gift_msg_id
raw_sender_id = utils.get_raw_peer_id(action_gift.from_id)
raw_receiver_id = utils.get_raw_peer_id(action_gift.peer)
parsed_gift = await Gift._parse_regular(client, action_gift.gift, users=users, chats=chats)
if action_gift.saved_id:
parsed_gift.received_gift_id = str(action_gift.saved_id)
parsed_gift.is_name_hidden = action_gift.name_hidden or parsed_gift.is_name_hidden
parsed_gift.is_saved = action_gift.saved or parsed_gift.is_saved
parsed_gift.was_converted = action_gift.converted or parsed_gift.was_converted
parsed_gift.was_upgraded = action_gift.upgraded or parsed_gift.was_upgraded
parsed_gift.was_refunded = action_gift.refunded or parsed_gift.was_refunded
parsed_gift.can_be_upgraded = action_gift.can_upgrade or parsed_gift.can_be_upgraded
parsed_gift.is_upgrade_separate = action_gift.upgrade_separate or parsed_gift.is_upgrade_separate
parsed_gift.text = types.FormattedText._parse(client, action_gift.message) or parsed_gift.text
parsed_gift.convert_star_count = action_gift.convert_stars or parsed_gift.convert_star_count
parsed_gift.upgrade_star_count = action_gift.upgrade_stars or parsed_gift.upgrade_star_count
parsed_gift.sender = types.Chat._parse_chat(client, users.get(raw_sender_id) or chats.get(raw_sender_id)) or parsed_gift.sender
parsed_gift.receiver = types.Chat._parse_chat(client, users.get(raw_receiver_id) or chats.get(raw_receiver_id)) or parsed_gift.receiver
parsed_gift.prepaid_upgrade_hash = action_gift.prepaid_upgrade_hash or parsed_gift.prepaid_upgrade_hash
parsed_gift.unique_gift_number = action_gift.gift_num or parsed_gift.unique_gift_number
parsed_gift.raw = action_gift
return parsed_gift
elif isinstance(action_gift, raw.types.MessageActionStarGiftUnique):
# peer
raw_sender_id = utils.get_raw_peer_id(action_gift.from_id)
raw_receiver_id = utils.get_raw_peer_id(action_gift.peer)
parsed_gift = await Gift._parse_upgraded(client, action_gift.gift, users=users, chats=chats)
if action_gift.from_offer:
parsed_gift.origin = enums.UpgradedGiftOrigin.OFFER
elif action_gift.assigned:
parsed_gift.origin = enums.UpgradedGiftOrigin.BLOCKCHAIN
elif action_gift.prepaid_upgrade:
parsed_gift.origin = enums.UpgradedGiftOrigin.GIFTED_UPGRADE
elif action_gift.resale_amount:
parsed_gift.origin = enums.UpgradedGiftOrigin.RESALE
elif action_gift.upgrade:
parsed_gift.origin = enums.UpgradedGiftOrigin.UPGRADE
elif action_gift.transferred:
parsed_gift.origin = enums.UpgradedGiftOrigin.TRANSFER
elif action_gift.craft:
parsed_gift.origin = enums.UpgradedGiftOrigin.CRAFT
if action_gift.saved_id:
parsed_gift.received_gift_id = str(action_gift.saved_id)
if isinstance(action_gift.resale_amount, raw.types.StarsAmount):
parsed_gift.last_resale_currency = "XTR"
parsed_gift.last_resale_amount = action_gift.resale_amount.amount
elif isinstance(action_gift.resale_amount, raw.types.StarsTonAmount):
parsed_gift.last_resale_currency = "TON"
parsed_gift.last_resale_amount = action_gift.resale_amount.amount
parsed_gift.was_upgraded = action_gift.upgrade or parsed_gift.was_upgraded
parsed_gift.is_saved = action_gift.saved or parsed_gift.is_saved
parsed_gift.was_refunded = action_gift.refunded or parsed_gift.was_refunded
parsed_gift.export_date = utils.timestamp_to_datetime(action_gift.can_export_at) or parsed_gift.export_date
parsed_gift.transfer_star_count = action_gift.transfer_stars or parsed_gift.transfer_star_count
parsed_gift.sender = types.Chat._parse_chat(client, users.get(raw_sender_id) or chats.get(raw_sender_id)) or parsed_gift.sender
parsed_gift.receiver = types.Chat._parse_chat(client, users.get(raw_receiver_id) or chats.get(raw_receiver_id)) or parsed_gift.receiver
parsed_gift.next_transfer_date = utils.timestamp_to_datetime(action_gift.can_transfer_at) or parsed_gift.next_transfer_date
parsed_gift.next_resale_date = utils.timestamp_to_datetime(action_gift.can_resell_at) or parsed_gift.next_resale_date
parsed_gift.craft_date = utils.timestamp_to_datetime(action_gift.can_craft_at) or parsed_gift.craft_date
parsed_gift.drop_original_details_star_count = action_gift.drop_original_details_stars or parsed_gift.drop_original_details_star_count
parsed_gift.raw = action_gift
return parsed_gift
@property
def link(self) -> Optional[str]:
if not self.name:
return None
return f"https://t.me/nft/{self.name}"
@property
def owned_gift_id(self) -> Optional[str]:
if not self.received_gift_id:
return None
if self.receiver and self.receiver.type != enums.ChatType.PRIVATE:
return f"{self.receiver.id}_{self.received_gift_id}"
return self.received_gift_id
[docs]
async def show(self) -> bool:
"""Bound method *show* of :obj:`~pyrogram.types.Gift`.
Use as a shortcut for:
.. code-block:: python
await client.show_gift(
owned_gift_id="message_id"
)
Example:
.. code-block:: python
await gift.show()
Returns:
``bool``: On success, True is returned.
"""
return await self._client.show_gift(
owned_gift_id=self.owned_gift_id
)
[docs]
async def hide(self) -> bool:
"""Bound method *hide* of :obj:`~pyrogram.types.Gift`.
Use as a shortcut for:
.. code-block:: python
await client.hide_gift(
owned_gift_id="message_id"
)
Example:
.. code-block:: python
await gift.hide()
Returns:
``bool``: On success, True is returned.
"""
return await self._client.hide_gift(
owned_gift_id=self.owned_gift_id
)
[docs]
async def convert(self) -> bool:
"""Bound method *convert* of :obj:`~pyrogram.types.Gift`.
.. note::
For regular gifts only.
Use as a shortcut for:
.. code-block:: python
await client.convert_gift_to_stars(
owned_gift_id="message_id"
)
Example:
.. code-block:: python
await gift.convert()
Returns:
``bool``: On success, True is returned.
"""
return await self._client.convert_gift_to_stars(
owned_gift_id=self.owned_gift_id
)
[docs]
async def upgrade(self, keep_original_details: Optional[bool] = None, star_count: Optional[int] = None) -> Optional["types.Message"]:
"""Bound method *upgrade* of :obj:`~pyrogram.types.Gift`.
.. note::
For regular gifts only.
Use as a shortcut for:
.. code-block:: python
await client.upgrade_gift(
owned_gift_id="message_id"
)
Example:
.. code-block:: python
await gift.upgrade()
Returns:
:obj:`~pyrogram.types.Message`: On success, the sent message is returned.
"""
return await self._client.upgrade_gift(
owned_gift_id=self.owned_gift_id,
keep_original_details=keep_original_details,
star_count=star_count
)
[docs]
async def transfer(self, to_chat_id: Union[int, str]) -> Optional["types.Message"]:
"""Bound method *transfer* of :obj:`~pyrogram.types.Gift`.
.. note::
For upgraded gifts only.
Use as a shortcut for:
.. code-block:: python
await client.transfer_gift(
owned_gift_id="message_id",
new_owner_chat_id=to_chat_id
)
Example:
.. code-block:: python
await gift.transfer(to_chat_id=123)
Returns:
:obj:`~pyrogram.types.Message`: On success, the sent message is returned.
"""
if not self.type == enums.GiftType.UPGRADED:
raise ValueError("Only upgraded gifts can be transferred.")
return await self._client.transfer_gift(
owned_gift_id=self.owned_gift_id or self.link,
new_owner_chat_id=to_chat_id
)
[docs]
async def wear(self) -> bool:
"""Bound method *wear* of :obj:`~pyrogram.types.Gift`.
.. note::
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 gift.wear()
Returns:
``bool``: On success, True is returned.
"""
return await self._client.set_emoji_status(
emoji_status=types.EmojiStatus(
gift_id=self.id
)
)
[docs]
async def buy(self, new_owner_chat_id: Optional[Union[int, str]] = None, price: Optional["types.GiftResalePrice"] = None) -> Optional["types.Message"]:
"""Bound method *buy* of :obj:`~pyrogram.types.Gift`.
.. note::
For upgraded gifts from market only.
Use as a shortcut for:
.. code-block:: python
await app.send_resold_gift(gift_link="https://t.me/nft/NekoHelmet-9215", new_owner_chat_id="me")
Example:
.. code-block:: python
await gift.buy()
Returns:
:obj:`~pyrogram.types.Message`: On success, the sent message is returned.
"""
if new_owner_chat_id is None:
new_owner_chat_id = "me"
if price is None:
if self.resale_parameters.toncoin_only:
price = types.GiftResalePriceTon(toncoin_cent_count=self.resale_parameters.toncoin_cent_count)
else:
price = types.GiftResalePriceStar(star_count=self.resale_parameters.star_count)
return await self._client.send_resold_gift(
gift_link=self.link,
new_owner_chat_id=new_owner_chat_id,
price=price
)
[docs]
async def send(
self,
chat_id: Union[int, str],
text: Optional[str] = None,
parse_mode: Optional["enums.ParseMode"] = None,
entities: Optional[List["types.MessageEntity"]] = None,
is_private: Optional[bool] = None,
pay_for_upgrade: Optional[bool] = None,
) -> Optional["types.Message"]:
"""Bound method *send* of :obj:`~pyrogram.types.Gift`.
.. note::
For regular gifts only.
May return an error with a message "STARGIFT_USAGE_LIMITED" if the gift was sold out.
Use as a shortcut for:
.. code-block:: python
await client.send_gift(
chat_id="me",
gift_id=gift.id
)
Example:
.. code-block:: python
await gift.send("me")
Returns:
:obj:`~pyrogram.types.Message`: On success, the sent message is returned.
"""
return await self._client.send_gift(
chat_id=chat_id,
gift_id=self.id,
text=text,
parse_mode=parse_mode,
entities=entities,
is_private=is_private,
pay_for_upgrade=pay_for_upgrade
)
[docs]
async def get_auction_state(self) -> "types.GiftAuctionState":
"""Bound method *get_auction_state* of :obj:`~pyrogram.types.Gift`.
.. note::
For regular gifts only.
Use as a shortcut for:
.. code-block:: python
await client.get_gift_auction_state(
auction_id=gift.id
)
Returns:
:obj:`~pyrogram.types.GiftAuctionState`: The auction state of the gift.
"""
return await self._client.get_gift_auction_state(auction_id=self.id)
[docs]
async def send_purchase_offer(
self,
price: "types.GiftResalePrice",
duration: int,
paid_message_star_count: Optional[int] = None
) -> Optional["types.Message"]:
"""Shortcut for method :obj:`~pyrogram.Client.send_gift_purchase_offer` will automatically fill method attributes:
* owner_id
* gift_id
Parameters:
price (:obj:`~pyrogram.types.GiftResalePrice`):
The price that the user agreed to pay for the gift.
duration (``int``):
Duration of the offer, in seconds.
Must be one of 21600, 43200, 86400, 129600, 172800, or 259200.
paid_message_star_count (``int``, *optional*):
The number of Telegram Stars the user agreed to pay additionally for sending of the offer message to the current gift owner.
Pass User.paid_message_star_count for users and None otherwise.
Returns:
:obj:`~pyrogram.types.Message`: On success, the sent Message is returned.
"""
if not self.can_send_purchase_offer:
raise ValueError("This gift cannot be purchased via offer.")
if not self.owner:
raise ValueError("Gift owner not found.")
return await self._client.send_gift_purchase_offer(
owner_id=self.owner.id,
gift_name=self.name,
price=price,
duration=duration,
paid_message_star_count=paid_message_star_count
)