Documentation Improvements (#4573, #4565)

Co-authored-by: Snehashish Biswas <coderrx06@gmail.com>
Co-authored-by: poolitzer <github@poolitzer.eu>
This commit is contained in:
Bibo-Joshi 2024-12-01 11:47:38 +01:00 committed by GitHub
parent ef1685c436
commit ffe23be992
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 63 additions and 44 deletions

View file

@ -111,6 +111,7 @@ The following wonderful people contributed directly or indirectly to this projec
- `Rahiel Kasim <https://github.com/rahiel>`_ - `Rahiel Kasim <https://github.com/rahiel>`_
- `Riko Naka <https://github.com/rikonaka>`_ - `Riko Naka <https://github.com/rikonaka>`_
- `Rizlas <https://github.com/rizlas>`_ - `Rizlas <https://github.com/rizlas>`_
- `Snehashish Biswas <https://github.com/Snehashish06>`_
- `Sahil Sharma <https://github.com/sahilsharma811>`_ - `Sahil Sharma <https://github.com/sahilsharma811>`_
- `Sam Mosleh <https://github.com/sam-mosleh>`_ - `Sam Mosleh <https://github.com/sam-mosleh>`_
- `Sascha <https://github.com/saschalalala>`_ - `Sascha <https://github.com/saschalalala>`_

View file

@ -2,7 +2,7 @@
# pylint: disable=unused-argument # pylint: disable=unused-argument
# This program is dedicated to the public domain under the CC0 license. # This program is dedicated to the public domain under the CC0 license.
"""Basic example for a bot that can receive payment from user.""" """Basic example for a bot that can receive payments from users."""
import logging import logging
@ -26,36 +26,36 @@ logging.getLogger("httpx").setLevel(logging.WARNING)
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
# Insert the token from your payment provider.
# In order to get a provider_token see https://core.telegram.org/bots/payments#getting-a-token
PAYMENT_PROVIDER_TOKEN = "PAYMENT_PROVIDER_TOKEN" PAYMENT_PROVIDER_TOKEN = "PAYMENT_PROVIDER_TOKEN"
async def start_callback(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None: async def start_callback(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
"""Displays info on how to use the bot.""" """Provides instructions on how to use the bot."""
msg = ( msg = (
"Use /shipping to get an invoice for shipping-payment, or /noshipping for an " "Use /shipping to receive an invoice with shipping included, or /noshipping for an "
"invoice without shipping." "invoice without shipping."
) )
await update.message.reply_text(msg) await update.message.reply_text(msg)
async def start_with_shipping_callback(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None: async def start_with_shipping_callback(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
"""Sends an invoice with shipping-payment.""" """Sends an invoice which triggers a shipping query."""
chat_id = update.message.chat_id chat_id = update.message.chat_id
title = "Payment Example" title = "Payment Example"
description = "Payment Example using python-telegram-bot" description = "Example of a payment process using the python-telegram-bot library."
# select a payload just for you to recognize its the donation from your bot # Unique payload to identify this payment request as being from your bot
payload = "Custom-Payload" payload = "Custom-Payload"
# In order to get a provider_token see https://core.telegram.org/bots/payments#getting-a-token # Set up the currency.
# List of supported currencies: https://core.telegram.org/bots/payments#supported-currencies
currency = "USD" currency = "USD"
# price in dollars # Price in dollars
price = 1 price = 1
# price * 100 so as to include 2 decimal points # Convert price to cents from dollars.
# check https://core.telegram.org/bots/payments#supported-currencies for more details
prices = [LabeledPrice("Test", price * 100)] prices = [LabeledPrice("Test", price * 100)]
# Optional parameters like need_shipping_address and is_flexible trigger extra user prompts
# optionally pass need_name=True, need_phone_number=True, # https://docs.python-telegram-bot.org/en/stable/telegram.bot.html#telegram.Bot.send_invoice
# need_email=True, need_shipping_address=True, is_flexible=True
await context.bot.send_invoice( await context.bot.send_invoice(
chat_id, chat_id,
title, title,
@ -75,17 +75,16 @@ async def start_with_shipping_callback(update: Update, context: ContextTypes.DEF
async def start_without_shipping_callback( async def start_without_shipping_callback(
update: Update, context: ContextTypes.DEFAULT_TYPE update: Update, context: ContextTypes.DEFAULT_TYPE
) -> None: ) -> None:
"""Sends an invoice without shipping-payment.""" """Sends an invoice without requiring shipping details."""
chat_id = update.message.chat_id chat_id = update.message.chat_id
title = "Payment Example" title = "Payment Example"
description = "Payment Example using python-telegram-bot" description = "Example of a payment process using the python-telegram-bot library."
# select a payload just for you to recognize its the donation from your bot # Unique payload to identify this payment request as being from your bot
payload = "Custom-Payload" payload = "Custom-Payload"
# In order to get a provider_token see https://core.telegram.org/bots/payments#getting-a-token
currency = "USD" currency = "USD"
# price in dollars # Price in dollars
price = 1 price = 1
# price * 100 so as to include 2 decimal points # Convert price to cents from dollars.
prices = [LabeledPrice("Test", price * 100)] prices = [LabeledPrice("Test", price * 100)]
# optionally pass need_name=True, need_phone_number=True, # optionally pass need_name=True, need_phone_number=True,
@ -96,65 +95,65 @@ async def start_without_shipping_callback(
async def shipping_callback(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None: async def shipping_callback(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
"""Answers the ShippingQuery with ShippingOptions""" """Handles the ShippingQuery with available shipping options."""
query = update.shipping_query query = update.shipping_query
# check the payload, is this from your bot? # Verify if the payload matches, ensure it's from your bot
if query.invoice_payload != "Custom-Payload": if query.invoice_payload != "Custom-Payload":
# answer False pre_checkout_query # If not, respond with an error
await query.answer(ok=False, error_message="Something went wrong...") await query.answer(ok=False, error_message="Something went wrong...")
return return
# First option has a single LabeledPrice # Define available shipping options
# First option with a single price entry
options = [ShippingOption("1", "Shipping Option A", [LabeledPrice("A", 100)])] options = [ShippingOption("1", "Shipping Option A", [LabeledPrice("A", 100)])]
# second option has an array of LabeledPrice objects # Second option with multiple price entries
price_list = [LabeledPrice("B1", 150), LabeledPrice("B2", 200)] price_list = [LabeledPrice("B1", 150), LabeledPrice("B2", 200)]
options.append(ShippingOption("2", "Shipping Option B", price_list)) options.append(ShippingOption("2", "Shipping Option B", price_list))
await query.answer(ok=True, shipping_options=options) await query.answer(ok=True, shipping_options=options)
# after (optional) shipping, it's the pre-checkout # After (optional) shipping, process the pre-checkout step
async def precheckout_callback(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None: async def precheckout_callback(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
"""Answers the PreQecheckoutQuery""" """Responds to the PreCheckoutQuery as the final confirmation for checkout."""
query = update.pre_checkout_query query = update.pre_checkout_query
# check the payload, is this from your bot? # Verify if the payload matches, ensure it's from your bot
if query.invoice_payload != "Custom-Payload": if query.invoice_payload != "Custom-Payload":
# answer False pre_checkout_query # If not, respond with an error
await query.answer(ok=False, error_message="Something went wrong...") await query.answer(ok=False, error_message="Something went wrong...")
else: else:
await query.answer(ok=True) await query.answer(ok=True)
# finally, after contacting the payment provider... # Final callback after successful payment
async def successful_payment_callback(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None: async def successful_payment_callback(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
"""Confirms the successful payment.""" """Acknowledges successful payment and thanks the user."""
# do something after successfully receiving payment? await update.message.reply_text("Thank you for your payment.")
await update.message.reply_text("Thank you for your payment!")
def main() -> None: def main() -> None:
"""Run the bot.""" """Starts the bot and sets up handlers."""
# Create the Application and pass it your bot's token. # Create the Application and pass it your bot's token.
application = Application.builder().token("TOKEN").build() application = Application.builder().token("TOKEN").build()
# simple start function # Start command to display usage instructions
application.add_handler(CommandHandler("start", start_callback)) application.add_handler(CommandHandler("start", start_callback))
# Add command handler to start the payment invoice # Command handlers for starting the payment process
application.add_handler(CommandHandler("shipping", start_with_shipping_callback)) application.add_handler(CommandHandler("shipping", start_with_shipping_callback))
application.add_handler(CommandHandler("noshipping", start_without_shipping_callback)) application.add_handler(CommandHandler("noshipping", start_without_shipping_callback))
# Optional handler if your product requires shipping # Handler for shipping query (if product requires shipping)
application.add_handler(ShippingQueryHandler(shipping_callback)) application.add_handler(ShippingQueryHandler(shipping_callback))
# Pre-checkout handler to final check # Pre-checkout handler for verifying payment details.
application.add_handler(PreCheckoutQueryHandler(precheckout_callback)) application.add_handler(PreCheckoutQueryHandler(precheckout_callback))
# Success! Notify your user! # Handler for successful payment. Notify the user that the payment was successful.
application.add_handler( application.add_handler(
MessageHandler(filters.SUCCESSFUL_PAYMENT, successful_payment_callback) MessageHandler(filters.SUCCESSFUL_PAYMENT, successful_payment_callback)
) )
# Run the bot until the user presses Ctrl-C # Start polling for updates until interrupted (CTRL+C)
application.run_polling(allowed_updates=Update.ALL_TYPES) application.run_polling(allowed_updates=Update.ALL_TYPES)

View file

@ -88,6 +88,19 @@ class AIORateLimiter(BaseRateLimiter[int]):
necessary in some cases, e.g. the bot may hit a rate limit in one group but might still necessary in some cases, e.g. the bot may hit a rate limit in one group but might still
be allowed to send messages in another group. be allowed to send messages in another group.
Tip:
With `Bot API 7.1 <https://core.telegram.org/bots/api-changelog#october-31-2024>`_
(PTB v27.1), Telegram introduced the parameter
:paramref:`~telegram.Bot.send_message.allow_paid_broadcast`.
This allows bots to send up to
:tg-const:`telegram.constants.FloodLimit.PAID_MESSAGES_PER_SECOND` messages per second by
paying a fee in Telegram Stars.
.. caution::
This class currently doesn't take the
:paramref:`~telegram.Bot.send_message.allow_paid_broadcast` parameter into account.
This means that the rate limiting is applied just like for any other message.
Note: Note:
This class is to be understood as minimal effort reference implementation. This class is to be understood as minimal effort reference implementation.
If you would like to handle rate limiting in a more sophisticated, fine-tuned way, we If you would like to handle rate limiting in a more sophisticated, fine-tuned way, we

View file

@ -36,10 +36,11 @@ RT = TypeVar("RT")
class CommandHandler(BaseHandler[Update, CCT, RT]): class CommandHandler(BaseHandler[Update, CCT, RT]):
"""Handler class to handle Telegram commands. """Handler class to handle Telegram commands.
Commands are Telegram messages that start with ``/``, optionally followed by an ``@`` and the Commands are Telegram messages that start with a :attr:`telegram.MessageEntity.BOT_COMMAND`
bot's name and/or some additional text. The handler will add a :obj:`list` to the (so with ``/``, optionally followed by an ``@`` and the bot's name and/or some additional
:class:`CallbackContext` named :attr:`CallbackContext.args`. It will contain a list of strings, text). The handler will add a :obj:`list` to the :class:`CallbackContext` named
which is the text following the command split on single or consecutive whitespace characters. :attr:`CallbackContext.args`. It will contain a list of strings, which is the text following
the command split on single or consecutive whitespace characters.
By default, the handler listens to messages as well as edited messages. To change this behavior By default, the handler listens to messages as well as edited messages. To change this behavior
use :attr:`~filters.UpdateType.EDITED_MESSAGE <telegram.ext.filters.UpdateType.EDITED_MESSAGE>` use :attr:`~filters.UpdateType.EDITED_MESSAGE <telegram.ext.filters.UpdateType.EDITED_MESSAGE>`
@ -53,6 +54,11 @@ class CommandHandler(BaseHandler[Update, CCT, RT]):
:attr:`telegram.ext.filters.CAPTION` and :class:`telegram.ext.filters.Regex`) to handle :attr:`telegram.ext.filters.CAPTION` and :class:`telegram.ext.filters.Regex`) to handle
those messages. those messages.
Note:
If you want to support a different entity in the beginning, e.g. if a command message is
wrapped in a :attr:`telegram.MessageEntity.CODE`, use the
:class:`telegram.ext.PrefixHandler`.
Warning: Warning:
When setting :paramref:`block` to :obj:`False`, you cannot rely on adding custom When setting :paramref:`block` to :obj:`False`, you cannot rely on adding custom
attributes to :class:`telegram.ext.CallbackContext`. See its docs for more info. attributes to :class:`telegram.ext.CallbackContext`. See its docs for more info.