Движок сайта: бессерверные боты

Я мало рассказываю о своём движке сайта. Всё обещаю себе, что закончу и тогда напишу большую обзорную статью, но на деле очень страшусь объёма работы: он уже очень многое умеет, а то ли ещё будет — планов громадьё!

Поэтому лучше рассказывать потихоньку.

Со сменой движка многие обратили внимание, что комментарии из моей группы в «Телеграме» теперь транслируются на сайт. Ну как «транслируются» — приходилось руками экспортировать их в клиенте, потом загружать к себе. Конечно, логичнее было бы делать это через бота, да вот незадача — его надо было бы где-то хостить, а с учётом ограничений «Телеграма» в нашей стране искать хостинг пришлось бы за границей.

Выход на самом деле есть — так называемые «бессерверные боты», недавно появившаяся у «Телеграма» возможность. Небольшая цитата из руководства Telegram Serverless:

Telegram Serverless позволяет запускать серверный код бота и мини-приложения прямо на инфраструктуре «Телеграма» — не нужно настраивать серверы, поддерживать контейнеры в рабочем состоянии и думать о масштабировании.

Одна проблема — доступ пока дают не всем, сначала надо отстоять очередь. Я получил его вчера и сразу с нейросетью сделал бота для переноса комментариев. Теперь буду тестировать на живых обсуждениях.

Технически это набор обычных джаваскриптовых модулей. Для каждого события — свой обработчик: handlers/message.js получает сообщения, handlers/edited_message.js — правки. «Телеграм» вызывает функцию, она выполняет работу и завершается. Код работает в изолированной среде V8; полноценной Node.js со всеми npm-пакетами там нет.

Подключение начинается в мини-приложении BotFather: создаёшь бота, встаёшь в очередь, когда она подошла, выбираешь бота, включаешь Serverless и получаешь отдельный ключ для командной строки. На компьютере нужен Node.js 18 или новее:

npm create @tgcloud/bot my-bot
cd my-bot
npx tgcloud login
npx tgcloud push

login связывает проект с ботом, push загружает код. В комплекте есть SQLite, Bot API и fetch для внешних HTTP-запросов. База сохраняется между вызовами, поэтому можно хранить пользователей, настройки, очередь заданий.

Понятно, что все шаги я описываю поверхностно, чтобы самому не забыть, для подробностей есть документация.

У меня бот сначала сохраняет событие в локальную базу, потом пробует передать его сайту. Если сайт недоступен, запись остаётся для повторной отправки. Если одно сообщение придёт дважды, второй комментарий из него не получится — движок сайта помнит, что уже импортировал.

Связь со статьёй определяется по ссылке в исходном посте канала — я всегда ставлю её в заголовке. Ответы сохраняют структуру обсуждения, а мой Telegram ID связан с моей учётной записью на сайте, чтобы собственные комментарии узнавались как авторские. Так же из комментариев переносятся картинки, видео, стикеры и реакции, включая их снятие.

Приёмник на сайте защищён отдельным секретным ключом, поэтому злоумышленник не может прислать ему команду добавить комментарий. Сам сайт при этом за файлами в «Телеграм» не ходит — бот скачивает их у себя и отправляет вместе с остальными данными.

Вот такая получилась схема. Я пока не знаю удастся ли этим же путём сделать публикацию заметок, но планирую попробовать, если получится, будет здорово.