У меня есть хобби — я учу финский язык. Просто так зубрить новые слова сложно, поэтому я решила написать бота для геймификации процесса. Бот поддерживает разные режимы тренировок, скоринг слов и объединение слов по темам, в общем — имеет довольно сложную ветвистую логику. В процессе создания бота мне удалось создать структуру кода и ресурсов, которая позволяет легко написать диалогового бота любой сложности, не рискуя запутаться и не беспокоясь о создании инфраструктуры. Этой структурой и хочу с вами поделиться.
Это первая статья цикла, в ней я расскажу, как создать базу — шаблонного serverless бота на Python с использованием Yandex Cloud Functions и базы данных YDB с нуля.
В следующих статьях расскажу о том, как добавить боту свои команды, о структуре кода, настройке и обработке пользовательских стейтов, безопасной работе с базой данных, удобном логировании и тестировании бота, которые реализованы в шаблоне. В качестве примера буду использовать примитивного бота, реализованного в моём репозитории ydb_serverless_telegram_bot.
Запускаем бота с нуля
Цель этой статьи - научить создавать основу для бота с нуля. Для этого нам понадобится:
База данных YDB
TeleBot (pyTelegramBotAPI) Python3 библиотека для работы с Телеграм
30 минут на выполнение инструкции (серьёзно, мы замеряли!)
0 потраченных денег
В итоге получится простой бот, который умеет
Спрашивать пошагово имя, фамилию и возраст пользователя, записывать данные в базу
Показывать хранящиеся данные по запросу
Удалять данные по запросу
С реализацией бота можно познакомиться по ссылке - YDB serverless example. В этой статье мы сделаем точно такого же.
Код бота можно использовать в качестве основы для более сложной логики. В нём реализованы пользовательские стейты, удобные логи, адаптированные под интерфейс Яндекс Облака и основа для тестирования с помощью pytest
.
Создаём Yandex Cloud Function
Шаг 1
Перейдите на сайт Яндекс.Облака и нажмите кнопку Подключиться
/ Консоль
в правом верхнем углу экрана. Надпись на кнопке зависит от наличия у вас аккаунта в Облаке.
Авторизуйтесь или зарегистрируйтесь в Яндекс ID.
Шаг 2
В консоли Облака создайте платёжный аккаунт в Яндекс.Облаке. Для создания нужно привязать банковскую карту, но в процессе создания и тестирования бота не потребуется делать платежей. Поддержка бота станет платной только при существенной нагрузке, подробнее об условиях, в которых бот останется бесплатным, можно прочесть здесь.
Скриншот
Шаг 3
В консоли Яндекс.Облака создайте каталог (папку) для нового проекта, дайте ей любое имя. Здесь и далее имена папок и ресурсов имеют значение только для вас — чтобы было удобно их идентифицировать. С технической точки зрения важны только ID ресурсов, которые генерируются автоматически.
Скриншот
Шаг 4
В новой папке создайте сервисный аккаунт и выдайте ему права editor
и serverless.functions.invoker
. Сервисный аккаунт нужен для разграничения прав в управлении ресурсами Облака между вашим личным аккаунтом и программными действиями для защиты от случайных действий.
Скриншот
Шаг 5
В папке создайте новый ресурс - API gateway
(API шлюз
), дайте ему имя и сохраните с настройками по умолчанию. Шлюз понадобится для связи Телеграма и функции — запросы от Телеграма будут запускать функцию через шлюз.
Скриншот
Шаг 6
В папке создайте новый ресурс — Функция
. Дайте ей имя и сохраните. После создания вы попадете на страницу редактора. Выберите среду выполнения Python 3.11
, а затем создайте версию с настройками по умолчанию.
Скриншоты
Шаг 7
На вкладке Обзор
созданной функции сделайте функцию публичной и скопируйте значение из поля Идентификатор
.
Скриншот
Шаг 8
Свяжите между собой шлюз и функцию. Для этого перейдите на страницу шлюза, во вкладку Обзор
и в поле Спецификация добавьте в конец следующий код, заменив <function ID>
на скопированный на предыдущем шаге идентификатор. Сохраните изменения.
/fshtb-function:
post:
x-yc-apigateway-integration:
type: cloud_functions
function_id: <function ID>
operationId: fshtb-function
Создаём бота и подключаем его к функции
Шаг 1
Найдите в Телеграме аккаунт BotFather и пошлите ему команду /newbot
. Введите публичное имя бота и его логин. В ответ BotFather
пришлет вам токен бота, дающий доступ к его управлению. Храните токен в секрете.
Скриншот
Шаг 2
Создайте меню команд бота. Для этого пошлите команду /setcommands
, выберите вашего бота из списка и отправьте следующий список команд:
start - show welcome message and bot description
register - store your name and age in the database
cancel - stop registering process
show_data - show your name and age stored in the database
delete_account - delete your info from the database
Это необязательный шаг, но он добавит удобства общению с ботом. Команды будут подсказываться при наборе текста, а также в левом нижнем углу появится кнопка со списком всех команд.
Скриншоты
Шаг 3
Создайте связь между ботом и функцией через API шлюз. Для этого сделайте следующий запрос через командную строку, заменив <YOUR BOT TOKEN>
на токен, который вам прислал BotFather
, а <API GATEWAY DOMAIN>
на значение Служебный домен с вкладки Обзор вашего API шлюза.
curl \
--request POST \
--url https://api.telegram.org/bot<YOUR BOT TOKEN>/setWebhook \
--header "content-type:application/json" \
--data "{\"url\": \"<API GATEWAY DOMAIN>/fshtb-function\"}"
При успешном запросе вы должны получить ответ {"ok":true,"result":true,"description":"Webhook was set"}
.
Командная строка Windows не поддерживает переносы строк, поэтому воспользуйтесь запросом ниже.
Запрос для Windows
curl --request POST --url https://api.telegram.org/bot<YOUR BOT TOKEN>/setWebhook --header "content-type:application/json" --data "{\"url\": \"<API gateway domain>/fshtb-function\"}"
Шаг 4
Проверим подключение. Отошлите вашему боту команду /start
. На данном этапе это должно привести к успешному POST
запросу от API шлюза к функции (с кодом 200) и успешному запуску функции. Проверить это можно на вкладках Логи
API шлюза и функции.
Скриншот - успешные логи API шлюза
Скриншот - успешные логи функции
Заметьте, что сейчас функция еще ничего не умеет делать, кроме запуска и засыпания, поэтому не ожидайте ответа на команду. Добавим функциональности в бота позже, в разделе Запускаем бота
.
Создаём базу данных
Шаг 1
В папке проекта создайте новый ресурс — База данных YDB
. Дайте ей имя и сохраните с дефолтными настройками.
Скриншоты
Шаг 2
Создайте необходимые таблицы в базе данных. Для этого на странице базы данных во вкладке Навигация
нажмите на кнопку Новый SQL-запрос
и выполните следующий запрос, который создаст таблицу для хранения данных пользователей и таблицу со стейтами пользователей.
CREATE TABLE `user_personal_info`
(
`user_id` Uint64,
`last_name` Utf8,
`first_name` Utf8,
`age` Uint64,
PRIMARY KEY (`user_id`)
);
COMMIT;
CREATE TABLE `states`
(
`user_id` Uint64,
`state` Utf8,
PRIMARY KEY (`user_id`)
);
Скриншот
Запускаем бота
В ручном режиме
Шаг 1
Скачайте код из репозитория ydb_serverless_telegram_bot. Создайте ZIP архив с полным содержимым папки. Для этого перейдите в директорию, содержащую файл index.py
, выделите все файлы и папки в директории, кликните правой клавишей мыши и выберитe “Создать ZIP архив” для Windows или “Сжать” для MacOS.
Ещё на Linux / MacOS можно выполнить команду zip -r ../code.zip *
внутри директории, содержащей файл index.py
, архив создастся в родительской директории.
Скриншот - как скачать код из репозитория
Шаг 2
Загрузите код в функцию. Для этого на странице функции во вкладке Редактор
выберите в поле Способ
значение ZIP-архив
, кликните Прикрепить файл
, выберите архив с кодом.
Настройте точку входа в функцию — введите в поле Точка входа
значение index.handler
.
Это будет означать, что запросы от Телеграма к функции будут обрабатываться python функцией под названием handler в файле index.py.
Выберите сервисный аккаунт, созданный в самом начале, в соответствующем поле.
Задайте переменные окружения:
YDB_DATABASE
со значениемСоединение > Размещение базы данных
с вкладкиОбзор
базы данных YDBYDB_ENDPOINT
со значениемСоединение > Эндпоинт
с вкладкиОбзор
базы данных YDBBOT_TOKEN
с токеном вашего бота, полученным отBotFather
Нажмите Создать версию
.
Скриншот
Настраивать точку входа, сервисный аккаунт и переменные окружения понадобится только один раз, при необходимости обновить код функции достаточно будет загрузить новый ZIP-архив с кодом.
С помощью командной строки (Linux, MacOS)
Есть другой способ загрузить код в функцию и настроить все необходимые переменные. Для него потребуется немного больше подготовки, но он позволит создавать новую версию функции одной командой. Это полезно на этапе активной разработки.
Для Windows этот способ не сработает из-за отсутствия команды zip
.
Шаг 1
Скачайте код из репозитория ydb_serverless_telegram_bot и перейдите внутрь директории с кодом.
Шаг 2
Подготовьте утилиту YC
для работы с ресурсами Облака через командную строку по инструкции.
Шаг 3
Отредактируйте файл create_function_version.sh
- заполните плейсхолдеры ID ваших ресурсов и токеном. Сохраните изменения и выполните файл из командной строки.
В результате выполнения создастся архив с необходимым кодом и зальется в качестве новой версии функции. В версию функции также автоматически подставятся точка входа, сервисный аккаунт и переменные окружения.
Выполняйте файл каждый раз, когда требуется обновить код функции.
Поговорите с ботом!
Волшебно! Ваш бот готов - кликните меню бота и выберите любую команду или просто отправьте /start
.
Попробуйте выполнить все команды из меню.
Примеры команд
Зайдите во вкладку Логи
функции, чтобы увидеть логи выполнения кода или логи ошибок, если что-то всё-таки пошло не так.
Как выглядят логи
Во вкладке Навигация
базы данных YDB проверьте содержимое таблицы user_personal_info
. В ней должны появиться данные, которые вы передали боту.
Содержимое таблицы user_personal_info
Что дальше?
В этой статье я сосредоточилась на том, чтобы показать, как быстро создать инфраструктуру для бота и запустить бота с нуля, не вдаваясь в подробности о том, как он работает и почему шаблон удобен.
Следующие статьи будут посвящены рассказу о том, как реализован бот, как добавить в него новые сценарии, о пользовательских стейтах, логировании, корректном взаимодействии с базой данных и end-to-end тестировании. Kiitos lukemisesta ja nähdään!
mikegordan
"Для создания нужно привязать банковскую карту,"
Жаль, хорошая статья (наверно), но тут стена продолжать бессмысленно...
Надеюсь автор статьи как нибудь сделает еще одну с сервисами которые бесплатные и не требуют карт, например Render или Cyclic.sh или Deta.space
mskozlova Автор
Понимаю, что это может отпугивать. Спасибо за предложение, попробую поисследовать!