Подключение кода
Берите любую библиотеку для Telegram и укажите адрес Лизы
https://bot.tech.liza.ru. Больше ничего менять не нужно: обработчики команд,
кнопок и файлов работают как обычно.
Совместимость проверена на python-telegram-bot 21.6: команды, кнопки, правка сообщений, файлы, голосовые, long polling и вебхук.
- python-telegram-bot
- aiogram 3
- curl
- Вебхук
- Пример бота «Клуб XL»
from telegram.ext import Application, CommandHandler
BOT = "https://bot.tech.liza.ru"
app = (Application.builder()
.token("<ТОКЕН>")
.base_url(f"{BOT}/bot") # ← единственное отличие от Telegram
.base_file_url(f"{BOT}/file/bot") # чтобы get_file() скачивал с Лизы
.build())
async def start(update, context):
await update.message.reply_text("Привет из Лизы!")
app.add_handler(CommandHandler("start", start))
app.run_polling() # long polling — как в Telegram
base_file_url нужен, чтобы get_file() скачивал файлы с Лизы. Прокси и
другие доработки не нужны.
import asyncio
from aiogram import Bot, Dispatcher
from aiogram.client.session.aiohttp import AiohttpSession
from aiogram.client.telegram import TelegramAPIServer
session = AiohttpSession(api=TelegramAPIServer.from_base("https://bot.tech.liza.ru"))
bot = Bot("<ТОКЕН>", session=session)
dp = Dispatcher()
# дальше — обычные хендлеры aiogram
async def main():
await dp.start_polling(bot)
asyncio.run(main())
В aiogram адрес задаётся через TelegramAPIServer.from_base; файлы он
скачивает с того же адреса.
BOT=https://bot.tech.liza.ru
# кто я
curl -s "$BOT/bot<ТОКЕН>/getMe"
# ждать сообщений до 30 секунд (long polling, timeout не больше 50)
curl -s "$BOT/bot<ТОКЕН>/getUpdates?timeout=30"
# подтвердить полученное: offset = последний update_id + 1
curl -s "$BOT/bot<ТОКЕН>/getUpdates?offset=6"
# ответить
curl -s -X POST "$BOT/bot<ТОКЕН>/sendMessage" \
-H 'Content-Type: application/json' \
-d '{"chat_id": 1419716922, "text": "Привет!"}'
Пока offset не подтверждён, сообщение будет приходить снова, так что упавший
бот ничего не потеряет. Неподтверждённое хранится 24 часа.
# Платформы, которые сами настраивают вебхук (CRM, конструкторы ботов),
# делают этот вызов за вас — укажите им адрес https://bot.tech.liza.ru и токен.
curl -s -X POST "https://bot.tech.liza.ru/bot<ТОКЕН>/setWebhook" \
-H 'Content-Type: application/json' \
-d '{"url": "https://ваш-сервер/hook", "secret_token": "s3cret"}'
# Лиза шлёт каждый апдейт POST-запросом с заголовками:
# X-Telegram-Bot-Api-Secret-Token: s3cret
# X-Liza-Bot-Api-Secret-Token: s3cret
# Ответили не 2xx — апдейт придёт повторно, по порядку (подробности ниже).
Проверяйте update_id, чтобы не обработать повтор дважды. Пока задан вебхук,
getUpdates отвечает 409.
Бот со скриншотов этой документации — целиком, без библиотек, на requests:
import os
import requests
API = f"https://bot.tech.liza.ru/bot{os.environ['BOT_TOKEN']}"
def api(method, **params):
r = requests.post(f"{API}/{method}", json=params, timeout=60)
return r.json().get("result")
MENU = {"inline_keyboard": [
[{"text": "📚 Каталог курсов", "callback_data": "catalog"}],
[{"text": "💳 Оплатить подписку", "url": "https://example.org/pay"}]]}
CATALOG = {"inline_keyboard": [
[{"text": "Курс «Продажи»", "callback_data": "course_sales"},
{"text": "Курс «CRM»", "callback_data": "course_crm"}],
[{"text": "← Назад", "callback_data": "back"}]]}
api("setMyCommands", commands=[
{"command": "start", "description": "Главное меню клуба"},
{"command": "shop", "description": "Каталог курсов"},
{"command": "help", "description": "Помощь"}])
offset = 0
while True:
for u in api("getUpdates", offset=offset, timeout=30) or []:
offset = u["update_id"] + 1
m, cq = u.get("message"), u.get("callback_query")
if m and m["from"]["id"] == 777000: # служебное «бот подключён»
continue
if m and m["from"].get("is_bot"): # ботам не отвечаем
continue
if cq: # нажали кнопку
api("answerCallbackQuery", callback_query_id=cq["id"])
if cq["data"] == "catalog":
api("editMessageText", chat_id=cq["message"]["chat"]["id"],
message_id=cq["message"]["message_id"],
text="<b>Каталог курсов</b>\nВыберите курс:",
parse_mode="HTML", reply_markup=CATALOG)
elif m and m.get("voice"): # голосовое
api("sendMessage", chat_id=m["chat"]["id"],
reply_to_message_id=m["message_id"],
text=f"🎙 Получил голосовое ({m['voice']['duration']} с)")
elif m and m.get("text", "").startswith("/start"):
api("sendMessage", chat_id=m["chat"]["id"], text="<b>Клуб XL</b>",
parse_mode="HTML", reply_markup=MENU)
api(метод, **параметры) — это POST на
https://bot.tech.liza.ru/bot<ТОКЕН>/<метод> с JSON-телом. Как этот бот
выглядит у человека — на странице
Что видит человек и что получает бот.
Получение обновлений: getUpdates
getUpdates работает как в Telegram, поэтому готовые библиотеки подключаются
без доработок:
- Long polling.
timeout(до 50 секунд; больше — урезается до 50) держит запрос открытым до первого обновления — пауза между запросами не нужна. - Подтверждение через
offset. Выдача не помечает обновление обработанным. Следующий запрос сoffset = последний update_id + 1подтверждает всё, что раньше. Если бот упал во время обработки, он получит то же обновление снова.offsetменьше нуля возвращает последние обновления и подтверждает остальные. - Неподтверждённые обновления хранятся 24 часа.
- Один опрашивающий. На один токен действует один запрос
getUpdates: новый вытесняет предыдущий (тот получает ошибку 409). Пока задан вебхук,getUpdatesтоже отвечает 409 — снимите его черезdeleteWebhook. - Параметр
allowed_updatesигнорируется.
Вебхук: setWebhook
После setWebhook Лиза отправляет каждый Update JSON-запросом (POST) на
указанный URL.
- Если при установке указан
secret_token, он передаётся в заголовкахX-Telegram-Bot-Api-Secret-Token(стандарт Telegram — его проверяют python-telegram-bot и aiogram) иX-Liza-Bot-Api-Secret-Token. - Если ваш сервер ответил не 2xx, обновление остаётся в очереди и
отправляется повторно по порядку — дедуплицируйте по
update_id. - На 4xx (кроме 408 и 429) — не больше 3 повторов, затем обновление снимается.
- На 5xx и сетевые ошибки — повторы с паузой 30 с · 2ⁿ (не больше часа), пока обновление не старше 24 часов.
Файлы
getFile отдаёт относительный file_path; скачивайте файл по адресу
https://bot.tech.liza.ru/file/bot<ТОКЕН>/<file_path>. Библиотеки делают это
сами (в python-telegram-bot задайте base_file_url, как в примере выше). Не
сохраняйте прямые ссылки на сервер, которые выдавали версии до 1.2.