Урок 8.4 — Интеграция с Pyrogram
Учимся интегрировать aiosend с Pyrogram — асинхронной библиотекой для работы с MTProto API Telegram.
Pyrogram — это асинхронная библиотека, использующая MTProto протокол Telegram. Интеграция с aiosend естественна: обе библиотеки асинхронные. Запускаем Pyrogram через app.run(), а aiosend polling — в параллельной корутине.
Параллельный запуск Pyrogram + aiosend
Pyrogram использует app.run() для запуска, aiosend — cp.start_polling(). Обе корутины можно запустить через asyncio.gather() или используя app.run() с asyncio.ensure_future() внутри.
import asyncio
from pyrogram import Client, filters
from aiosend import CryptoPay
BOT_TOKEN = "123456:ABCdefGHIjklmNOP"
CP_TOKEN = "1234:ABCDefGHIJklmnOPQRST"
API_ID = 12345
API_HASH = "0123456789abcdef0123456789abcdef"
app = Client("my_bot", bot_token=BOT_TOKEN, api_id=API_ID, api_hash=API_HASH)
cp = CryptoPay(token=CP_TOKEN)
@app.on_message(filters.command("start"))
async def start(client, message):
await message.reply(
"Привет! Я бот на Pyrogram + aiosend!\n"
"Используй /pay 10 USDT для оплаты."
)
@app.on_message(filters.command("pay"))
async def pay(client, message):
args = message.text.split()[1:]
if len(args) < 2:
await message.reply("Пример: /pay 10 USDT")
return
amount, asset = float(args[0]), args[1].upper()
invoice = await cp.create_invoice(
amount=amount,
asset=asset,
payload=str(message.from_user.id),
)
await message.reply(
f"🧾 Счёт на {amount} {asset}:\n"
f"{invoice.bot_invoice_url}\n"
f"Mini App: {invoice.mini_app_invoice_url}"
)
@cp.invoice_paid()
async def on_paid(invoice):
user_id = int(invoice.payload)
await app.send_message(
user_id,
f"✅ Оплата {invoice.amount} {invoice.asset} получена!",
)
async def main():
await asyncio.gather(
app.start(), # Pyrogram
cp.start_polling(), # aiosend
)
asyncio.run(main())
💡 Вариант с app.run()
Вместо asyncio.gather() можно использовать app.run(), который запускает внутренний event loop. В этом случае aiosend нужно запустить через asyncio.ensure_future() внутри самого бота, например, в обработчике @app.on_startup().
Ожидание оплаты с invoice.poll()
В Pyrogram invoice.poll(message=message) также работает. Объект Message в Pyrogram поддерживается aiosend.
@app.on_message(filters.command("buy"))
async def buy(client, message):
invoice = await cp.create_invoice(
amount=15,
asset="USDT",
description="Премиум",
payload=str(message.from_user.id),
)
msg = await message.reply(
f"💳 Премиум\n"
f"Сумма: 15 USDT\n\n"
f"🔗 {invoice.bot_invoice_url}\n\n"
f"⏳ Ожидаем оплату...",
)
try:
paid = await invoice.poll(message=msg)
await msg.edit_text(
f"✅ Оплачено!\n"
f"{paid.paid_amount} {paid.paid_asset}",
)
except Exception as e:
await msg.edit_text(f"❌ Ошибка: {e}")
Полный пример: магазин на Pyrogram
import asyncio
from pyrogram import Client, filters
from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton
from aiosend import CryptoPay
BOT_TOKEN = "123456:ABCdefGHIjklmNOP"
CP_TOKEN = "1234:ABCDefGHIJklmnOPQRST"
API_ID = 12345
API_HASH = "0123456789abcdef0123456789abcdef"
app = Client("shop_bot", bot_token=BOT_TOKEN, api_id=API_ID, api_hash=API_HASH)
cp = CryptoPay(token=CP_TOKEN)
PRODUCTS = {
"premium": {"name": "Премиум", "price": 15, "asset": "USDT"},
"vip": {"name": "VIP-доступ", "price": 50, "asset": "USDT"},
}
@app.on_message(filters.command("start"))
async def start(client, message):
kb = InlineKeyboardMarkup([
[InlineKeyboardButton("💎 Премиум", callback_data="buy_premium")],
[InlineKeyboardButton("⭐ VIP", callback_data="buy_vip")],
])
await message.reply("🛒 Добро пожаловать!", reply_markup=kb)
@app.on_callback_query(filters.regex(r"^buy_"))
async def handle_buy(client, callback):
product_key = callback.data.replace("buy_", "")
product = PRODUCTS.get(product_key)
if not product:
await callback.answer("Товар не найден")
return
await callback.answer("Создаём счёт...")
invoice = await cp.create_invoice(
amount=product["price"],
asset=product["asset"],
description=product["name"],
payload=f"{callback.from_user.id}:{product_key}",
)
msg = await callback.message.reply(
f"💳 {product['name']}\n"
f"Сумма: {product['price']} {product['asset']}\n\n"
f"🔗 {invoice.bot_invoice_url}\n\n"
f"⏳ Ожидаем оплату...",
)
try:
paid = await invoice.poll(message=msg)
await msg.edit_text(
f"✅ Оплачено!\n"
f"{paid.paid_amount} {paid.paid_asset}\n"
f"Товар: {product['name']}",
)
except Exception as e:
await msg.edit_text(f"❌ Ошибка: {e}")
@cp.invoice_paid()
async def on_paid(invoice):
user_id, product_key = invoice.payload.split(":")
product = PRODUCTS.get(product_key, {"name": "товар"})
print(f"Платёж: user={user_id} product={product['name']}")
await app.send_message(
int(user_id),
f"✅ {product['name']} активирован! Спасибо!",
)
async def main():
await asyncio.gather(
app.start(),
cp.start_polling(),
)
asyncio.run(main())
🔍 Ключевые особенности Pyrogram
- Pyrogram требует
api_idиapi_hash(получить на my.telegram.org) - Декораторы:
@app.on_message(filters.command("x"))и@app.on_callback_query() app.start()— корутина, её нужно await- Pyrogram использует MTProto вместо Bot API
await message.reply()— отправка ответа
Что важно запомнить
Практическое задание
Задание: Donate-бот на Pyrogram
Создай бота на Pyrogram + aiosend:
- По команде /donate [сумма] [валюта] создаёт инвойс
- Отправляет ссылку на оплату
- Ожидает оплату через invoice.poll(message=msg)
- Благодарит пользователя после оплаты
- Запускает через asyncio.gather()
Подсказка:
import asyncio
from pyrogram import Client, filters
from aiosend import CryptoPay
app = Client("bot", bot_token="TOKEN", api_id=1, api_hash="hash")
cp = CryptoPay(token="CP_TOKEN")
@app.on_message(filters.command("donate"))
async def donate(client, message):
args = message.text.split()
amount, asset = float(args[1]), args[2].upper()
invoice = await cp.create_invoice(
amount=amount, asset=asset,
payload=str(message.from_user.id),
)
msg = await message.reply(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():
await asyncio.gather(app.start(), cp.start_polling())
asyncio.run(main())
Урок 8.4: Интеграция с Pyrogram
5 вопросов