Урок 8.6 — Интеграция с python-telegram-bot (PTB)
Учимся интегрировать aiosend с python-telegram-bot (PTB) — асинхронной библиотекой с Application Builder и современным API.
python-telegram-bot (PTB) v20+ — это полностью асинхронная библиотека, использующая Application и ApplicationBuilder. Интеграция с aiosend естественна: обе библиотеки асинхронные. Запускаем app.run_polling() и cp.start_polling() параллельно.
ApplicationBuilder — современный подход PTB
PTB v20+ использует паттерн Builder для создания приложения. ApplicationBuilder позволяет сконфигурировать бота, добавить обработчики и запустить polling.
import asyncio
from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup
from telegram.ext import Application, CommandHandler, CallbackQueryHandler
from aiosend import CryptoPay
BOT_TOKEN = "123456:ABCdefGHIjklmNOP"
CP_TOKEN = "1234:ABCDefGHIJklmnOPQRST"
cp = CryptoPay(token=CP_TOKEN)
# PTB handler — Command
async def start(update: Update, context):
await update.message.reply_text(
"Привет! Я бот на PTB + aiosend!\n"
"Используй /pay 10 USDT для оплаты."
)
async def pay(update: Update, context):
args = context.args
if len(args) < 2:
await update.message.reply_text("Пример: /pay 10 USDT")
return
amount, asset = float(args[0]), args[1].upper()
invoice = await cp.create_invoice(
amount=amount,
asset=asset,
payload=str(update.effective_user.id),
)
await update.message.reply_text(
f"🧾 Счёт на {amount} {asset}:\n"
f"{invoice.bot_invoice_url}"
)
@cp.invoice_paid()
async def on_paid(invoice):
from telegram import Bot
bot = Bot(token=BOT_TOKEN)
user_id = int(invoice.payload)
await bot.send_message(
user_id,
f"✅ Оплата {invoice.amount} {invoice.asset} получена!",
)
async def main():
# Создаём PTB Application
app = (
Application.builder()
.token(BOT_TOKEN)
.build()
)
# Регистрируем хендлеры
app.add_handler(CommandHandler("start", start))
app.add_handler(CommandHandler("pay", pay))
# Запускаем параллельно
await asyncio.gather(
app.run_polling(), # PTB
cp.start_polling(), # aiosend
)
asyncio.run(main())
💡 Особенность PTB
app.run_polling() — это синхронная обёртка, которая создаёт event loop и запускает бота. Чтобы запустить aiosend параллельно, мы используем asyncio.gather() с app.run_polling(), который в PTB v20+ можно вызвать как корутину.
Различные обработчики PTB
PTB предоставляет множество готовых классов-обработчиков: CommandHandler, MessageHandler, CallbackQueryHandler и другие.
from telegram.ext import (
CommandHandler,
MessageHandler,
CallbackQueryHandler,
filters,
)
# CommandHandler — для команд
app.add_handler(CommandHandler("buy", buy_handler))
# MessageHandler — для текстовых сообщений
app.add_handler(
MessageHandler(filters.TEXT & ~filters.COMMAND, text_handler)
)
# CallbackQueryHandler — для inline-кнопок
app.add_handler(CallbackQueryHandler(callback_handler, pattern="^buy_"))
# Несколько команд в одном обработчике
app.add_handler(CommandHandler(["help", "info"], help_handler))
🔍 Параметры PTB-хендлеров
- update — объект Update с данными от Telegram
- context — объект ContextTypes с дополнительной информацией
context.args— аргументы команды (для CommandHandler)context.user_data— данные пользователя (словарь)update.effective_user.id— ID пользователя
Полный пример: магазин на PTB
import asyncio
from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup
from telegram.ext import (
Application,
CommandHandler,
CallbackQueryHandler,
ContextTypes,
)
from aiosend import CryptoPay
BOT_TOKEN = "123456:ABCdefGHIjklmNOP"
CP_TOKEN = "1234:ABCDefGHIJklmnOPQRST"
cp = CryptoPay(token=CP_TOKEN)
PRODUCTS = {
"premium": {"name": "Премиум", "price": 15, "asset": "USDT"},
"vip": {"name": "VIP-доступ", "price": 50, "asset": "USDT"},
}
async def start(update: Update, context: ContextTypes.DEFAULT_TYPE):
kb = InlineKeyboardMarkup([
[InlineKeyboardButton("💎 Премиум", callback_data="buy_premium")],
[InlineKeyboardButton("⭐ VIP", callback_data="buy_vip")],
])
await update.message.reply_text("🛒 Добро пожаловать!", reply_markup=kb)
async def buy_callback(update: Update, context: ContextTypes.DEFAULT_TYPE):
query = update.callback_query
await query.answer()
product_key = query.data.replace("buy_", "")
product = PRODUCTS.get(product_key)
if not product:
await query.message.reply_text("Товар не найден")
return
invoice = await cp.create_invoice(
amount=product["price"],
asset=product["asset"],
description=product["name"],
payload=f"{query.from_user.id}:{product_key}",
)
msg = await query.message.reply_text(
f"💳 {product['name']}\n"
f"Сумма: {product['price']} {product['asset']}\n\n"
f"🔗 {invoice.bot_invoice_url}\n\n"
f"⏳ Ожидаем оплату...",
parse_mode="HTML",
)
try:
paid = await invoice.poll(message=msg)
await msg.edit_text(
f"✅ Оплачено!\n"
f"{paid.paid_amount} {paid.paid_asset}\n"
f"Товар: {product['name']}",
parse_mode="HTML",
)
except Exception as e:
await msg.edit_text(f"❌ Ошибка: {e}")
@cp.invoice_paid()
async def on_paid(invoice):
from telegram import Bot
bot = Bot(token=BOT_TOKEN)
user_id, product_key = invoice.payload.split(":")
product = PRODUCTS.get(product_key, {"name": "товар"})
print(f"Платёж: user={user_id} product={product['name']}")
await bot.send_message(
int(user_id),
f"✅ {product['name']} активирован! Спасибо!",
)
async def main():
app = (
Application.builder()
.token(BOT_TOKEN)
.build()
)
app.add_handler(CommandHandler("start", start))
app.add_handler(CallbackQueryHandler(buy_callback, pattern="^buy_"))
await asyncio.gather(
app.run_polling(),
cp.start_polling(),
)
asyncio.run(main())
🔍 Ключевые особенности PTB
Application.builder().token(TOKEN).build()— создание приложенияapp.add_handler(CommandHandler("cmd", func))— регистрация командapp.add_handler(CallbackQueryHandler(func, pattern))— callback-кнопкиupdate.callback_query— для работы с callbackcontext.args— аргументы команды (после /cmd)await query.answer()— ответ на callback
Ожидание оплаты с PTB
invoice.poll(message=msg) работает и с PTB. Объект Message из PTB v20+ поддерживается aiosend.
async def buy(update: Update, context: ContextTypes.DEFAULT_TYPE):
invoice = await cp.create_invoice(
amount=10, asset="USDT",
payload=str(update.effective_user.id),
)
msg = await update.message.reply_text(
f"💳 Счёт на 10 USDT\n{invoice.bot_invoice_url}\n\n⏳ Ожидаем..."
)
try:
paid = await invoice.poll(message=msg)
await msg.edit_text(
f"✅ Оплачено: {paid.paid_amount} {paid.paid_asset}"
)
except Exception as e:
await msg.edit_text(f"❌ Ошибка: {e}")
Что важно запомнить
Практическое задание
Задание: Donate-бот на PTB
Создай бота на PTB + aiosend:
- По команде /donate [сумма] [валюта] создаёт инвойс
- Отправляет ссылку на оплату
- Ожидает оплату через invoice.poll(message=msg)
- Благодарит пользователя после оплаты
- Запускает через asyncio.gather()
Подсказка:
import asyncio
from telegram import Update
from telegram.ext import Application, CommandHandler, ContextTypes
from aiosend import CryptoPay
cp = CryptoPay(token="CP_TOKEN")
async def donate(update: Update, context: ContextTypes.DEFAULT_TYPE):
args = context.args
amount, asset = float(args[0]), args[1].upper()
invoice = await cp.create_invoice(
amount=amount, asset=asset,
payload=str(update.effective_user.id),
)
msg = await update.message.reply_text(f"💛 {invoice.bot_invoice_url}")
paid = await invoice.poll(message=msg)
await msg.edit_text(f"✅ Спасибо за {paid.paid_amount} {paid.paid_asset}!")
async def main():
app = Application.builder().token("BOT_TOKEN").build()
app.add_handler(CommandHandler("donate", donate))
await asyncio.gather(app.run_polling(), cp.start_polling())
asyncio.run(main())
Урок 8.6: Интеграция с python-telegram-bot
5 вопросов