Бот: Кто понял жизнь, тот не спешит.
Это простой и неспешный телеграм-бот для ведения списка задач. Задачи в списке располагаются в порядке добавления.
Чтобы добавить задачу, нужно написать её текст в чат бота и в ответном сообщении нажать кнопку 'Add this message as a new Task'. Текст сообщения не должен полностью совпадать с текстом уже существующей задачи.
Для удаления задачи из списка, нужно отправить боту команду /del и через пробел указать номер задачи в списке (например, /del 1).
Бот работает через webhook и рассчитан на использование serverless-технологий Yandex Cloud (Cloud Functions, API Gateway, Message Queue, Managed Service for YDB). Если потребление ресурсов Yandex Cloud будет укладываться во free tier (https://yandex.cloud/ru/docs/billing/concepts/serverless-free-tier), то бот будет работать бесплатно.
Бот общается только в приватном чате и только с тем пользователем, чей идентификатор указан в файле с настройками (.env).
На данный момент есть версии бота, написаные на языках:
- Python
- TypeScript
Информация о версии бота указана на Help странице.
Бот написан на Python (среда выполнения Python/3.12) с испольлзованием библиотеки aiogram 3. Для взаимодействия с базой данных (YDB) используется асинхронная SQLAlchemy. Фильтрация типа чата и пользователя реализована в файле routers/__init__.py . Версия функции для загрузки находится в файле todo-tg-bot-python.zip. Журналирование выполнения функции на Python в Cloud Functions https://yandex.cloud/ru/docs/functions/lang/python/logging
Бот написан на TypeScript (среда выполнения Node.js/22) с испольлзованием библиотеки Telegraf.js 4. Для взаимодействия с базой данных (YDB) используются сырые SQL запросы. Фильтрация типа чата и пользователя реализована в файле index.ts . Версия функции для загрузки находится в файле todo-tg-bot-typescript.zip
В качестве шаблона можно использовать файл .env.example
BOT_TOKEN=<токен телеграм бота>
TG_ID=<идентификатор пользователя>
CLOUD_ID=<идентификатор облака>
DB_ID=<идентификатор базы данных>
Создание и получение токена телеграм бота через BotFather https://core.telegram.org/bots/features#botfather
Получение идентификатора пользователя Телеграма: погуглить и воспользваться одним из ботов.
Идентификатор облака, документация https://yandex.cloud/ru/docs/resource-manager/operations/cloud/get-id
Идентификатор базы данных можно найти в её свойствах, например, в Консоли Yandex Cloud. Документация https://yandex.cloud/ru/docs/ydb/operations/manage-databases
- Создать сервисные аккаунты:
- В самом простом случае можно создать один аккаунт с ролью
editorна каталог и везде его использовать. - В идеале нужно ограничивать права минимально необходимыми. Не уверен, что в случае с телеграм-ботом стоит так заморачиваться. Но если в облаке кроме бота есть что-то ещё и важное, то стоит заморочиться.
- Вариант попроще: создать два сервисных аккаунта с ролями на каталог (как в варианте развёртывании через Terraform). Один для работы с БД и функцией (роли
ydb.editorиfunctions.functionInvoker), другой для работы с очередью сообщений (ролиymq.writerиymq.reader). - Документация. Создание сервисного аккаунта https://yandex.cloud/ru/docs/iam/operations/sa/create . Назначить роль на каталог или облако https://yandex.cloud/ru/docs/iam/operations/roles/grant#cloud-or-folder .
- Создать БД и таблицу:
- Создать Serverless базу данных https://yandex.cloud/ru/docs/ydb/operations/manage-databases#create-db-serverless .
- Создать таблицу https://yandex.cloud/ru/docs/ydb/operations/schema#create-table . Название таблицы и столбцов можно посмотреть в файле
src/database/models/task.py. - Либо для создания таблицы возспользоваться SQL-запросом из файла
create-db.sql. Для этого в Консоли Yandex Cloud нужно в базе данных перейти во вкладку "Навигация" и там нажать кнопку "Новый SQL-запрос", скопировать туда запрос и выполнить его.
- Создать очередь и шлюз:
- Создание новой очереди сообщений https://yandex.cloud/ru/docs/message-queue/operations/message-queue-new-queue . Срок хранения сообщений 1 минута.
- Создание API-шлюза для очереди сообщений https://yandex.cloud/ru/docs/api-gateway/operations/spec-constructor/ymq . Путь указать
/todo-tg-bot.
- Создать функцию и триггер:
- Создать функцию https://yandex.cloud/ru/docs/functions/operations/function/function-create .
- Создать версию функции из zip-архива (лежит в папке terraform) https://yandex.cloud/ru/docs/functions/operations/function/version-manage .
- Не забыть нажать "Сохранить изменения".
- Создать триггер для Message Queue, который передает сообщения в функцию Cloud Functions https://yandex.cloud/ru/docs/functions/operations/trigger/ymq-trigger-create .
- В "Редакторе" функции:
- Создать файл
.envи задать в нём переменные. - Установить значения: "Таймаут" 30 секунтд, "Память" 256 МБ.
- Не забыть нажать "Сохранить изменения".
- Подключить webhook.
- Например, воспользоваться кодом из файла
set-webhook.txt. - Для выполнения кода можно воспользоваться Cloud Shell https://yandex.cloud/ru/docs/console/quickstart/cloud-shell
curl \
--request POST \
--url https://api.telegram.org/bot<токен_бота>/setWebhook \
--header 'content-type: application/json' \
--data '{"url": "<домен_API-шлюза>/todo-tg-bot"}'
- При успешном подключении вебхука в консоли будет сообщение, содержащее текст
{"ok":true,"result":true,"description":"Webhook was set"}
Подразумевается, что все действия будут выполняться в Yandex Cloud Shell, поэтому иногда нужно будет использовать sudo, а Terraform и Git там уже установлены.
- Получить файлы проекта (
sudo git clone https://github.com/smallslowtank/todo-tg-bot-serverless.git) и перейти в папку terraform проекта (cd todo-tg-bot-serverless/terraform). - При необходимости инициализировать Terraform (
cp .terraformrc ~иsudo terraform init) и задать переменные (nano terraform.tfvars)
token = "<OAuth-токен>"
cloud_id = "<идентификатор_облака>"
folder_id = "<идентификатор_каталога>"
zone = "ru-central1-d"
-
tokenOAuth-токен в сервисе Яндекс ID, для получения нужно перейти по ссылке и от туда его скопировать. Ссылка https://oauth.yandex.ru/authorize?response_type=token&client_id=1a6990aa636648e9b2ef855fa7bec2fb . Документация https://yandex.cloud/ru/docs/iam/concepts/authorization/oauth-token -
cloud_idИдентификатор облака, документация https://yandex.cloud/ru/docs/resource-manager/operations/cloud/get-id -
folder_idИдентификатор каталога, документация https://yandex.cloud/ru/docs/resource-manager/operations/folder/get-id -
zoneПри необходимости можно изменить зону на a или b, документация https://yandex.cloud/ru/docs/overview/concepts/geo-scope
- Проверить файлы (
terraform validate), посмотреть план (terraform plan) и создать ресурсы:
- БД, сервисные аккаунты и статический ключ
terraform apply \
-target=yandex_ydb_database_serverless.todo-tg-bot-ydb \
-target=yandex_iam_service_account.sa-todo-tg-bot-ydb-cf \
-target=yandex_resourcemanager_folder_iam_binding.sa-todo-tg-bot-ydb-cf \
-target=yandex_iam_service_account.sa-todo-tg-bot-ymq \
-target=yandex_resourcemanager_folder_iam_binding.sa-todo-tg-bot-ymq \
-target=yandex_iam_service_account_static_access_key.sa-todo-tg-bot-ymq-static-key
- Остальные ресурсы
terraform apply
- В "Редакторе" функции:
- Создать файл
.envи задать в нём переменные. - Не забыть нажать "Сохранить изменения".
- Подключить webhook.
- Например, воспользоваться кодом из файла
set-webhook.txt. - Для выполнения кода можно воспользоваться Cloud Shell https://yandex.cloud/ru/docs/console/quickstart/cloud-shell
curl \
--request POST \
--url https://api.telegram.org/bot<токен_бота>/setWebhook \
--header 'content-type: application/json' \
--data '{"url": "<домен_API-шлюза>/todo-tg-bot"}'
- При успешном подключении вебхука в консоли будет сообщение, содержащее текст
{"ok":true,"result":true,"description":"Webhook was set"}
Не получится удалить все ресурсы за один проход командой terraform destroy, т.к. как минимум у сервисного аккаунта, созданного для очереди сообщений, не хватит прав на её удаление. Варианты:
- Выдать сервисному аккаунту роль
ymq.adminили выше и удалять ресурссы за два проходаterraform destroy - Удалить оставшиеся ресурсы другим способом, например, руками через Консоль Yandex Cloud.
- Мой выбор:
- Редактировать файл
create-service-account.tfи выдать сервисному аккаунту рольymq.admin. Применить измененияterraform apply. - Удалить таблицу и очередь сообщений (вместе с ней удалятся шлюз и триггер)
terraform destroy \
-target=yandex_ydb_table.todo-tg-bot-ydb-table-tasks \
-target=yandex_message_queue.todo-tg-bot-message-queue
- Удалить всё остальное
terraform destroy
Обычно включается автоматически по умолчанию. При желании можно отключить.
В общем и целом для работы бота можно ограничиться использованием только сервиса Cloud Functions. Но тогда нужно внести изменение в код:
event['messages'][0]['details']['message']['body']
заменить на
event['body']
Функцию сделать публичной и, при подключении webhook, указать её адрес, а не адрес шлюза и путь.
Архивы с версиями функции (бота) лежат в папке terraform.
В скриптах Terraform указано имя файла todo-tg-bot.zip, по умолчанию в этом архиве лежит первая версия на Python.