$ sudo teach IT
Модуль 8 · Интеграции с Telegram-ботами

Урок 8.5 — Интеграция с Telethon

Учимся интегрировать aiosend с Telethon — асинхронной библиотекой для MTProto с богатыми возможностями обработки событий.

Telethon — ещё одна асинхронная MTProto-библиотека для Python. Она предоставляет богатую систему событий через @client.on(). Интеграция с aiosend строится по тому же принципу, что и с Pyrogram: обе библиотеки асинхронные, запускаем параллельно.

⚡

Параллельный запуск Telethon + aiosend

Telethon использует @client.on(events.NewMessage) для обработки сообщений. Запускается через client.start() и client.run_until_disconnected().

Python · Параллельный запуск Telethon + aiosend
import asyncio
from telethon import TelegramClient, events
from aiosend import CryptoPay

BOT_TOKEN = "123456:ABCdefGHIjklmNOP"
CP_TOKEN = "1234:ABCDefGHIJklmnOPQRST"
API_ID = 12345
API_HASH = "0123456789abcdef0123456789abcdef"

client = TelegramClient("bot", API_ID, API_HASH).start(bot_token=BOT_TOKEN)
cp = CryptoPay(token=CP_TOKEN)

@client.on(events.NewMessage(pattern="/start"))
async def start(event):
    await event.reply(
        "Привет! Я бот на Telethon + aiosend!\n"
        "Используй /pay 10 USDT для оплаты."
    )

@client.on(events.NewMessage(pattern="/pay"))
async def pay(event):
    text = event.message.text
    parts = text.split()
    if len(parts) < 3:
        await event.reply("Пример: /pay 10 USDT")
        return

    amount, asset = float(parts[1]), parts[2].upper()
    invoice = await cp.create_invoice(
        amount=amount,
        asset=asset,
        payload=str(event.sender_id),
    )

    await event.reply(
        f"🧾 Счёт на {amount} {asset}:\n"
        f"{invoice.bot_invoice_url}"
    )

@cp.invoice_paid()
async def on_paid(invoice):
    user_id = int(invoice.payload)
    await client.send_message(
        user_id,
        f"✅ Оплата {invoice.amount} {invoice.asset} получена!",
    )

async def main():
    await asyncio.gather(
        client.run_until_disconnected(),
        cp.start_polling(),
    )

asyncio.run(main())

💡 Особенность Telethon

Telethon не требует отдельного вызова client.start() в асинхронном коде, если использовать TelegramClient("bot", API_ID, API_HASH).start(bot_token=TOKEN). Но client.start() можно вызвать и отдельно как корутину.

🎣

Система событий Telethon

Telethon использует богатую систему событий. Можно фильтровать по тексту, отправителю, чату и другим параметрам.

Python · Различные события Telethon
from telethon import events

# По команде
@client.on(events.NewMessage(pattern="/buy"))
async def buy(event):
    invoice = await cp.create_invoice(
        amount=10, asset="USDT",
        payload=str(event.sender_id),
    )
    msg = await event.reply(
        f"💳 Счёт: {invoice.bot_invoice_url}"
    )

    # Ожидаем оплату
    paid = await invoice.poll(message=msg)
    await msg.edit(f"✅ Оплачено: {paid.paid_amount} {paid.paid_asset}")

# Только личные сообщения
@client.on(events.NewMessage(pattern="/admin", from_users=ADMIN_ID))
async def admin(event):
    await event.reply("Панель администратора")

# Callback-запросы
@client.on(events.CallbackQuery())
async def callback(event):
    data = event.data.decode()
    if data.startswith("buy_"):
        # Обработка покупки
        await event.answer("Создаю счёт...")

🔍 События Telethon

  • events.NewMessage — новое сообщение
  • events.CallbackQuery — нажатие на inline-кнопку
  • events.MessageEdited — редактирование сообщения
  • events.UserUpdate — обновление пользователя
  • Фильтры: pattern, from_users, chats, incoming, outgoing
🚀

Полный пример: магазин на Telethon

Python · Полный бот на Telethon
import asyncio
from telethon import TelegramClient, events
from telethon.tl.types import InlineKeyboardButton, InlineKeyboardMarkup
from aiosend import CryptoPay

BOT_TOKEN = "123456:ABCdefGHIjklmNOP"
CP_TOKEN = "1234:ABCDefGHIJklmnOPQRST"
API_ID = 12345
API_HASH = "0123456789abcdef0123456789abcdef"

client = TelegramClient("shop", API_ID, API_HASH).start(bot_token=BOT_TOKEN)
cp = CryptoPay(token=CP_TOKEN)

PRODUCTS = {
    "premium": {"name": "Премиум", "price": 15, "asset": "USDT"},
    "vip": {"name": "VIP-доступ", "price": 50, "asset": "USDT"},
}

@client.on(events.NewMessage(pattern="/start"))
async def start(event):
    kb = InlineKeyboardMarkup([[
        InlineKeyboardButton("💎 Премиум", data=b"buy_premium"),
        InlineKeyboardButton("⭐ VIP", data=b"buy_vip"),
    ]])
    await event.reply("🛒 Добро пожаловать!", buttons=kb)

@client.on(events.CallbackQuery())
async def callback(event):
    data = event.data.decode()
    if not data.startswith("buy_"):
        return

    product_key = data.replace("buy_", "")
    product = PRODUCTS.get(product_key)
    if not product:
        await event.answer("Товар не найден")
        return

    await event.answer("Создаём счёт...")

    invoice = await cp.create_invoice(
        amount=product["price"],
        asset=product["asset"],
        description=product["name"],
        payload=f"{event.sender_id}:{product_key}",
    )

    msg = await event.reply(
        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(
            f"✅ Оплачено!\n"
            f"{paid.paid_amount} {paid.paid_asset}\n"
            f"Товар: {product['name']}",
            parse_mode="html",
        )
    except Exception as e:
        await msg.edit(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 client.send_message(
        int(user_id),
        f"✅ {product['name']} активирован! Спасибо!",
    )

async def main():
    await asyncio.gather(
        client.run_until_disconnected(),
        cp.start_polling(),
    )

asyncio.run(main())

🔍 Ключевые особенности Telethon

  • @client.on(events.NewMessage(pattern="/cmd")) — декоратор
  • await event.reply() — ответ на сообщение
  • event.sender_id — ID отправителя
  • await msg.edit() — редактирование сообщения
  • InlineKeyboardButton принимает data как байты (b"data")
  • event.answer() — ответ на callback (всплывающее уведомление)
📌

Что важно запомнить

1️⃣
@client.on(events.NewMessage) — основной способ обработки сообщений.
2️⃣
client.run_until_disconnected() — блокирует до отключения.
3️⃣
asyncio.gather() — параллельный запуск Telethon и aiosend.
4️⃣
CallbackQuery — обработка inline-кнопок.
🎯

Практическое задание

Задание: Donate-бот на Telethon

Создай бота на Telethon + aiosend:

  • По команде /donate [сумма] [валюта] создаёт инвойс
  • Отправляет ссылку на оплату
  • Ожидает оплату через invoice.poll(message=msg)
  • Благодарит пользователя после оплаты
  • Запускает через asyncio.gather()

Подсказка:

Python · Шаблон решения
import asyncio
from telethon import TelegramClient, events
from aiosend import CryptoPay

client = TelegramClient("bot", API_ID, API_HASH).start(bot_token="BOT_TOKEN")
cp = CryptoPay(token="CP_TOKEN")

@client.on(events.NewMessage(pattern="/donate"))
async def donate(event):
    parts = event.message.text.split()
    amount, asset = float(parts[1]), parts[2].upper()
    invoice = await cp.create_invoice(
        amount=amount, asset=asset,
        payload=str(event.sender_id),
    )
    msg = await event.reply(f"💛 {invoice.bot_invoice_url}")
    paid = await invoice.poll(message=msg)
    await msg.edit(f"✅ Спасибо за {paid.paid_amount} {paid.paid_asset}!")

async def main():
    await asyncio.gather(
        client.run_until_disconnected(),
        cp.start_polling(),
    )

asyncio.run(main())

Урок 8.5: Интеграция с Telethon

5 вопросов