Co-authored-by: Harshil <37377066+harshil21@users.noreply.github.com>
Co-authored-by: Bibo-Joshi <22366557+Bibo-Joshi@users.noreply.github.com>
This commit is contained in:
Poolitzer 2024-07-09 10:35:18 +02:00 committed by GitHub
parent 52237cf00c
commit 71e4015e22
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 256 additions and 3 deletions

View file

@ -11,7 +11,7 @@
:target: https://pypi.org/project/python-telegram-bot/ :target: https://pypi.org/project/python-telegram-bot/
:alt: Supported Python versions :alt: Supported Python versions
.. image:: https://img.shields.io/badge/Bot%20API-7.6-blue?logo=telegram .. image:: https://img.shields.io/badge/Bot%20API-7.7-blue?logo=telegram
:target: https://core.telegram.org/bots/api-changelog :target: https://core.telegram.org/bots/api-changelog
:alt: Supported Bot API version :alt: Supported Bot API version
@ -79,7 +79,7 @@ make the development of bots easy and straightforward. These classes are contain
Telegram API support Telegram API support
==================== ====================
All types and methods of the Telegram Bot API **7.6** are supported. All types and methods of the Telegram Bot API **7.7** are supported.
Installing Installing
========== ==========

View file

@ -8,6 +8,7 @@ Payments
telegram.labeledprice telegram.labeledprice
telegram.orderinfo telegram.orderinfo
telegram.precheckoutquery telegram.precheckoutquery
telegram.refundedpayment
telegram.revenuewithdrawalstate telegram.revenuewithdrawalstate
telegram.revenuewithdrawalstatefailed telegram.revenuewithdrawalstatefailed
telegram.revenuewithdrawalstatepending telegram.revenuewithdrawalstatepending

View file

@ -0,0 +1,6 @@
RefundedPayment
===============
.. autoclass:: telegram.RefundedPayment
:members:
:show-inheritance:

View file

@ -204,6 +204,7 @@ __all__ = (
"ReactionType", "ReactionType",
"ReactionTypeCustomEmoji", "ReactionTypeCustomEmoji",
"ReactionTypeEmoji", "ReactionTypeEmoji",
"RefundedPayment",
"ReplyKeyboardMarkup", "ReplyKeyboardMarkup",
"ReplyKeyboardRemove", "ReplyKeyboardRemove",
"ReplyParameters", "ReplyParameters",
@ -446,6 +447,7 @@ from ._payment.invoice import Invoice
from ._payment.labeledprice import LabeledPrice from ._payment.labeledprice import LabeledPrice
from ._payment.orderinfo import OrderInfo from ._payment.orderinfo import OrderInfo
from ._payment.precheckoutquery import PreCheckoutQuery from ._payment.precheckoutquery import PreCheckoutQuery
from ._payment.refundedpayment import RefundedPayment
from ._payment.shippingaddress import ShippingAddress from ._payment.shippingaddress import ShippingAddress
from ._payment.shippingoption import ShippingOption from ._payment.shippingoption import ShippingOption
from ._payment.shippingquery import ShippingQuery from ._payment.shippingquery import ShippingQuery

View file

@ -55,6 +55,7 @@ from telegram._messageentity import MessageEntity
from telegram._paidmedia import PaidMediaInfo from telegram._paidmedia import PaidMediaInfo
from telegram._passport.passportdata import PassportData from telegram._passport.passportdata import PassportData
from telegram._payment.invoice import Invoice from telegram._payment.invoice import Invoice
from telegram._payment.refundedpayment import RefundedPayment
from telegram._payment.successfulpayment import SuccessfulPayment from telegram._payment.successfulpayment import SuccessfulPayment
from telegram._poll import Poll from telegram._poll import Poll
from telegram._proximityalerttriggered import ProximityAlertTriggered from telegram._proximityalerttriggered import ProximityAlertTriggered
@ -576,6 +577,10 @@ class Message(MaybeInaccessibleMessage):
paid_media (:obj:`telegram.PaidMediaInfo`, optional): Message contains paid media; paid_media (:obj:`telegram.PaidMediaInfo`, optional): Message contains paid media;
information about the paid media. information about the paid media.
.. versionadded:: NEXT.VERSION
refunded_payment (:obj:`telegram.RefundedPayment`, optional): Message is a service message
about a refunded payment, information about the payment.
.. versionadded:: NEXT.VERSION .. versionadded:: NEXT.VERSION
Attributes: Attributes:
@ -894,6 +899,10 @@ class Message(MaybeInaccessibleMessage):
paid_media (:obj:`telegram.PaidMediaInfo`): Optional. Message contains paid media; paid_media (:obj:`telegram.PaidMediaInfo`): Optional. Message contains paid media;
information about the paid media. information about the paid media.
.. versionadded:: NEXT.VERSION
refunded_payment (:obj:`telegram.RefundedPayment`): Optional. Message is a service message
about a refunded payment, information about the payment.
.. versionadded:: NEXT.VERSION .. versionadded:: NEXT.VERSION
.. |custom_emoji_no_md1_support| replace:: Since custom emoji entities are not supported by .. |custom_emoji_no_md1_support| replace:: Since custom emoji entities are not supported by
@ -968,6 +977,7 @@ class Message(MaybeInaccessibleMessage):
"poll", "poll",
"proximity_alert_triggered", "proximity_alert_triggered",
"quote", "quote",
"refunded_payment",
"reply_markup", "reply_markup",
"reply_to_message", "reply_to_message",
"reply_to_story", "reply_to_story",
@ -1080,6 +1090,7 @@ class Message(MaybeInaccessibleMessage):
effect_id: Optional[str] = None, effect_id: Optional[str] = None,
show_caption_above_media: Optional[bool] = None, show_caption_above_media: Optional[bool] = None,
paid_media: Optional[PaidMediaInfo] = None, paid_media: Optional[PaidMediaInfo] = None,
refunded_payment: Optional[RefundedPayment] = None,
*, *,
api_kwargs: Optional[JSONDict] = None, api_kwargs: Optional[JSONDict] = None,
): ):
@ -1182,6 +1193,7 @@ class Message(MaybeInaccessibleMessage):
self.effect_id: Optional[str] = effect_id self.effect_id: Optional[str] = effect_id
self.show_caption_above_media: Optional[bool] = show_caption_above_media self.show_caption_above_media: Optional[bool] = show_caption_above_media
self.paid_media: Optional[PaidMediaInfo] = paid_media self.paid_media: Optional[PaidMediaInfo] = paid_media
self.refunded_payment: Optional[RefundedPayment] = refunded_payment
self._effective_attachment = DEFAULT_NONE self._effective_attachment = DEFAULT_NONE
@ -1298,6 +1310,7 @@ class Message(MaybeInaccessibleMessage):
data["chat_shared"] = ChatShared.de_json(data.get("chat_shared"), bot) data["chat_shared"] = ChatShared.de_json(data.get("chat_shared"), bot)
data["chat_background_set"] = ChatBackground.de_json(data.get("chat_background_set"), bot) data["chat_background_set"] = ChatBackground.de_json(data.get("chat_background_set"), bot)
data["paid_media"] = PaidMediaInfo.de_json(data.get("paid_media"), bot) data["paid_media"] = PaidMediaInfo.de_json(data.get("paid_media"), bot)
data["refunded_payment"] = RefundedPayment.de_json(data.get("refunded_payment"), bot)
# Unfortunately, this needs to be here due to cyclic imports # Unfortunately, this needs to be here due to cyclic imports
from telegram._giveaway import ( # pylint: disable=import-outside-toplevel from telegram._giveaway import ( # pylint: disable=import-outside-toplevel

View file

@ -0,0 +1,91 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2024
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program 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 Public License for more details.
#
# You should have received a copy of the GNU Lesser Public License
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains an object that represents a Telegram RefundedPayment."""
from typing import Optional
from telegram._telegramobject import TelegramObject
from telegram._utils.types import JSONDict
class RefundedPayment(TelegramObject):
"""This object contains basic information about a refunded payment.
Objects of this class are comparable in terms of equality. Two objects of this class are
considered equal, if their :attr:`telegram_payment_charge_id` is equal.
Args:
currency (:obj:`str`): Three-letter ISO 4217 `currency
<https://core.telegram.org/bots/payments#supported-currencies>`_ code, or ``XTR`` for
payments in |tg_stars|. Currently, always ``XTR``.
total_amount (:obj:`int`): Total refunded price in the *smallest units* of the currency
(integer, **not** float/double). For example, for a price of ``US$ 1.45``,
``total_amount = 145``. See the *exp* parameter in
`currencies.json <https://core.telegram.org/bots/payments/currencies.json>`_,
it shows the number of digits past the decimal point for each currency
(2 for the majority of currencies).
invoice_payload (:obj:`str`): Bot-specified invoice payload.
telegram_payment_charge_id (:obj:`str`): Telegram payment identifier.
provider_payment_charge_id (:obj:`str`, optional): Provider payment identifier.
Attributes:
currency (:obj:`str`): Three-letter ISO 4217 `currency
<https://core.telegram.org/bots/payments#supported-currencies>`_ code, or ``XTR`` for
payments in |tg_stars|. Currently, always ``XTR``.
total_amount (:obj:`int`): Total refunded price in the *smallest units* of the currency
(integer, **not** float/double). For example, for a price of ``US$ 1.45``,
``total_amount = 145``. See the *exp* parameter in
`currencies.json <https://core.telegram.org/bots/payments/currencies.json>`_,
it shows the number of digits past the decimal point for each currency
(2 for the majority of currencies).
invoice_payload (:obj:`str`): Bot-specified invoice payload.
telegram_payment_charge_id (:obj:`str`): Telegram payment identifier.
provider_payment_charge_id (:obj:`str`): Optional. Provider payment identifier.
"""
__slots__ = (
"currency",
"invoice_payload",
"provider_payment_charge_id",
"telegram_payment_charge_id",
"total_amount",
)
def __init__(
self,
currency: str,
total_amount: int,
invoice_payload: str,
telegram_payment_charge_id: str,
provider_payment_charge_id: Optional[str] = None,
*,
api_kwargs: Optional[JSONDict] = None,
):
super().__init__(api_kwargs=api_kwargs)
self.currency: str = currency
self.total_amount: int = total_amount
self.invoice_payload: str = invoice_payload
self.telegram_payment_charge_id: str = telegram_payment_charge_id
# Optional
self.provider_payment_charge_id: Optional[str] = provider_payment_charge_id
self._id_attrs = (self.telegram_payment_charge_id,)
self._freeze()

View file

@ -151,7 +151,7 @@ class _AccentColor(NamedTuple):
#: :data:`telegram.__bot_api_version_info__`. #: :data:`telegram.__bot_api_version_info__`.
#: #:
#: .. versionadded:: 20.0 #: .. versionadded:: 20.0
BOT_API_VERSION_INFO: Final[_BotAPIVersion] = _BotAPIVersion(major=7, minor=6) BOT_API_VERSION_INFO: Final[_BotAPIVersion] = _BotAPIVersion(major=7, minor=7)
#: :obj:`str`: Telegram Bot API #: :obj:`str`: Telegram Bot API
#: version supported by this version of `python-telegram-bot`. Also available as #: version supported by this version of `python-telegram-bot`. Also available as
#: :data:`telegram.__bot_api_version__`. #: :data:`telegram.__bot_api_version__`.
@ -1920,6 +1920,11 @@ class MessageType(StringEnum):
""":obj:`str`: Messages with :attr:`telegram.Message.poll`.""" """:obj:`str`: Messages with :attr:`telegram.Message.poll`."""
PROXIMITY_ALERT_TRIGGERED = "proximity_alert_triggered" PROXIMITY_ALERT_TRIGGERED = "proximity_alert_triggered"
""":obj:`str`: Messages with :attr:`telegram.Message.proximity_alert_triggered`.""" """:obj:`str`: Messages with :attr:`telegram.Message.proximity_alert_triggered`."""
REFUNDED_PAYMENT = "refunded_payment"
""":obj:`str`: Messages with :attr:`telegram.Message.refunded_payment`.
.. versionadded:: NEXT.VERSION
"""
REPLY_TO_STORY = "reply_to_story" REPLY_TO_STORY = "reply_to_story"
""":obj:`str`: Messages with :attr:`telegram.Message.reply_to_story`. """:obj:`str`: Messages with :attr:`telegram.Message.reply_to_story`.

View file

@ -1959,6 +1959,7 @@ class StatusUpdate:
or StatusUpdate.NEW_CHAT_TITLE.check_update(update) or StatusUpdate.NEW_CHAT_TITLE.check_update(update)
or StatusUpdate.PINNED_MESSAGE.check_update(update) or StatusUpdate.PINNED_MESSAGE.check_update(update)
or StatusUpdate.PROXIMITY_ALERT_TRIGGERED.check_update(update) or StatusUpdate.PROXIMITY_ALERT_TRIGGERED.check_update(update)
or StatusUpdate.REFUNDED_PAYMENT.check_update(update)
or StatusUpdate.USERS_SHARED.check_update(update) or StatusUpdate.USERS_SHARED.check_update(update)
or StatusUpdate.USER_SHARED.check_update(update) or StatusUpdate.USER_SHARED.check_update(update)
or StatusUpdate.VIDEO_CHAT_ENDED.check_update(update) or StatusUpdate.VIDEO_CHAT_ENDED.check_update(update)
@ -2205,6 +2206,17 @@ class StatusUpdate:
) )
"""Messages that contain :attr:`telegram.Message.proximity_alert_triggered`.""" """Messages that contain :attr:`telegram.Message.proximity_alert_triggered`."""
class _RefundedPayment(MessageFilter):
__slots__ = ()
def filter(self, message: Message) -> bool:
return bool(message.refunded_payment)
REFUNDED_PAYMENT = _RefundedPayment("filters.StatusUpdate.REFUNDED_PAYMENT")
"""Messages that contain :attr:`telegram.Message.refunded_payment`.
.. versionadded:: NEXT.VERSION
"""
class _UserShared(MessageFilter): class _UserShared(MessageFilter):
__slots__ = () __slots__ = ()

View file

@ -0,0 +1,115 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2024
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program 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 Public License for more details.
#
# You should have received a copy of the GNU Lesser Public License
# along with this program. If not, see [http://www.gnu.org/licenses/].
import pytest
from telegram import RefundedPayment
from tests.auxil.slots import mro_slots
@pytest.fixture(scope="module")
def refunded_payment():
return RefundedPayment(
TestRefundedPaymentBase.currency,
TestRefundedPaymentBase.total_amount,
TestRefundedPaymentBase.invoice_payload,
TestRefundedPaymentBase.telegram_payment_charge_id,
TestRefundedPaymentBase.provider_payment_charge_id,
)
class TestRefundedPaymentBase:
invoice_payload = "invoice_payload"
currency = "EUR"
total_amount = 100
telegram_payment_charge_id = "telegram_payment_charge_id"
provider_payment_charge_id = "provider_payment_charge_id"
class TestRefundedPaymentWithoutRequest(TestRefundedPaymentBase):
def test_slot_behaviour(self, refunded_payment):
inst = refunded_payment
for attr in inst.__slots__:
assert getattr(inst, attr, "err") != "err", f"got extra slot '{attr}'"
assert len(mro_slots(inst)) == len(set(mro_slots(inst))), "duplicate slot"
def test_de_json(self, bot):
json_dict = {
"invoice_payload": self.invoice_payload,
"currency": self.currency,
"total_amount": self.total_amount,
"telegram_payment_charge_id": self.telegram_payment_charge_id,
"provider_payment_charge_id": self.provider_payment_charge_id,
}
refunded_payment = RefundedPayment.de_json(json_dict, bot)
assert refunded_payment.api_kwargs == {}
assert refunded_payment.invoice_payload == self.invoice_payload
assert refunded_payment.currency == self.currency
assert refunded_payment.total_amount == self.total_amount
assert refunded_payment.telegram_payment_charge_id == self.telegram_payment_charge_id
assert refunded_payment.provider_payment_charge_id == self.provider_payment_charge_id
def test_to_dict(self, refunded_payment):
refunded_payment_dict = refunded_payment.to_dict()
assert isinstance(refunded_payment_dict, dict)
assert refunded_payment_dict["invoice_payload"] == refunded_payment.invoice_payload
assert refunded_payment_dict["currency"] == refunded_payment.currency
assert refunded_payment_dict["total_amount"] == refunded_payment.total_amount
assert (
refunded_payment_dict["telegram_payment_charge_id"]
== refunded_payment.telegram_payment_charge_id
)
assert (
refunded_payment_dict["provider_payment_charge_id"]
== refunded_payment.provider_payment_charge_id
)
def test_equality(self):
a = RefundedPayment(
self.currency,
self.total_amount,
self.invoice_payload,
self.telegram_payment_charge_id,
self.provider_payment_charge_id,
)
b = RefundedPayment(
self.currency,
self.total_amount,
self.invoice_payload,
self.telegram_payment_charge_id,
self.provider_payment_charge_id,
)
c = RefundedPayment("", 0, "", self.telegram_payment_charge_id)
d = RefundedPayment(
self.currency,
self.total_amount,
self.invoice_payload,
"",
)
assert a == b
assert hash(a) == hash(b)
assert a is not b
assert a == c
assert hash(a) == hash(c)
assert a != d
assert hash(a) != hash(d)

View file

@ -1100,6 +1100,11 @@ class TestFilters:
assert filters.StatusUpdate.CHAT_BACKGROUND_SET.check_update(update) assert filters.StatusUpdate.CHAT_BACKGROUND_SET.check_update(update)
update.message.chat_background_set = None update.message.chat_background_set = None
update.message.refunded_payment = "refunded_payment"
assert filters.StatusUpdate.ALL.check_update(update)
assert filters.StatusUpdate.REFUNDED_PAYMENT.check_update(update)
update.message.refunded_payment = None
def test_filters_forwarded(self, update, message_origin_user): def test_filters_forwarded(self, update, message_origin_user):
assert filters.FORWARDED.check_update(update) assert filters.FORWARDED.check_update(update)
update.message.forward_origin = MessageOriginHiddenUser(datetime.datetime.utcnow(), 1) update.message.forward_origin = MessageOriginHiddenUser(datetime.datetime.utcnow(), 1)

View file

@ -53,6 +53,7 @@ from telegram import (
Poll, Poll,
PollOption, PollOption,
ProximityAlertTriggered, ProximityAlertTriggered,
RefundedPayment,
ReplyParameters, ReplyParameters,
SharedUser, SharedUser,
Sticker, Sticker,
@ -278,6 +279,7 @@ def message(bot):
{"effect_id": "123456789"}, {"effect_id": "123456789"},
{"show_caption_above_media": True}, {"show_caption_above_media": True},
{"paid_media": PaidMediaInfo(5, [PaidMediaPreview(10, 10, 10)])}, {"paid_media": PaidMediaInfo(5, [PaidMediaPreview(10, 10, 10)])},
{"refunded_payment": RefundedPayment("EUR", 243, "payload", "charge_id", "provider_id")},
], ],
ids=[ ids=[
"reply", "reply",
@ -350,6 +352,7 @@ def message(bot):
"effect_id", "effect_id",
"show_caption_above_media", "show_caption_above_media",
"paid_media", "paid_media",
"refunded_payment",
], ],
) )
def message_params(bot, request): def message_params(bot, request):