Создаем чат-бот в Telegram на функциях: пошаговая инструкция

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

Мы напишем простого бота-заготовку, которого можно использовать для написания полноценного приложения, добавив нужную вам функциональность.

Такого бота можно написать с использованием serverless-подхода в крупных облаках, например, с помощью AWS Lambda или Google Cloud Functions. Мы напишем функцию на Yandex Cloud Function, сделаем Object Storage, чтобы хранить файлы, и спрячем нашу serverless-архитектуру от пользователя с помощью сервиса Yandex API Gateway, который позволяет выступить фронтом для пользователя.

Шаг 1. Создайте бота с помощью BotFather

Прежде всего нужно зарегистрировать наше приложение в Telegram. Найдите в мессенджере главного бота BotFather и наберите команду /newbot. Для этого достаточно написать его имя user name и account name. В нашем случае account name — Serverless Hello Telegram Bot, username — ServerlessHelloTelegramBot. В результате вы получите token, запомните его, он потребуется на следующих этапах.

С помощью команды /setuserpic установите иконку для вашего бота. В нашем случае это картинка с именем sayhello.png.

На этом этапе у нас уже есть заготовка для бота. Дальше переходим в Yandex.Cloud и начинаем создавать инфраструктуру для бота.

Шаг 2. Создайте сервисный аккаунт

Войдите в ваш рабочий каталог.

Создайте новый сервисный аккаунт для работы telegram-бота. Например, serverless-telegram. Задайте роли для него: serverless.functions.invoker и editor. Роль serverless.functions.invoker необходима для запуска функций.

Обратите внимание: editor перекрывает роль serverless.function.invoker.

Запомните идентификатор созданного сервисного аккаунта.

Шаг 3. Создайте Object Storage

Нам нужно где-то хранить файлы для бота. Перейдите в каталог и выберете сервис Object Storage. Нажмите кнопку Создать бакет.

Введите имя бакета: for-serverless-hello-telegram-bot. Затем задайте максимальный размер в 1 ГБ и установите параметр Доступ на чтение объектов — Публичный.

Когда мы размещаем объект, есть возможность поместить его в два разных хранилища: стандартное с быстрым доступом или холодное. Холодное — это долговременное хранилище, оно отдельно тарифицируется и чаще всего используется для бэкапов. В нашем случае выбираем стандартное.

Загрузите картинку в созданный бакет. В нашем случае это тот же самый файл, который мы установили аватаром для бота: sayhello.png. Получите ссылку на загруженную картинку и проверьте её доступность по ссылке в браузере.

Шаг 4. Опубликуйте картинку через API Gateway

Давайте опубликуем нашу картинку через сервис API Gateway. Таким образом мы создадим заготовку, чтобы пользователь мог работать с нашим telegram-ботом, но не видел, что находится внутри. Перейдите в каталог и выберете сервис API Gateway. Нажмите кнопку Создать API-шлюз:

Введите имя for-serverless-hello-telegram-bot и вставьте спецификацию:

info:
  title: for-serverless-hello-telegram-bot
  version: 1.0.0
paths:
  /sayhello.png:
    get:
      x-yc-apigateway-integration:
        type: object-storage
        bucket: for-serverless-hello-telegram-bot
        object: sayhello.png
        presigned_redirect: false
        service_account: IDYOURACCOUNT
      operationId: static

Обязательно замените:

  • sayhello.png — на имя вашей картинки (два раза).

  • for-serverless-hello-telegram-bot — на имя вашего бакета.

  • IDYOURACCOUNT— на id вашего сервисного аккаунта, созданного ранее.

После опубликования API-шлюза в спецификации появится секция servers с адресом url. Через этот адресом вы сможете обратиться к ранее опубликованной картинке. В нашем случае к sayhello.png.

Проверяем, все работает. Отлично! Мы соединили два сервиса. У нас, с одной стороны, есть Object Storage, в котором что-то хранится. И есть API Gateway, который публично предоставляет доступ к каким-то ресурсам.

Шаг 5. Создадим Cloud Function

Идем дальше. Теперь нам нужно сделать функцию. Перейдите в каталог и выберете сервис Cloud Functions. Нажмите кнопку Создать функцию. Задайте имя. В нашем случае: fshtb-function.

Мы создали объект, но сама функция еще не создана. Нам необходимо выбрать среду выполнения. Внутри Yandex.Cloud несколько разных сред. Мы выберем nodejs, у нас есть там python.

Выберете среду выполнения node12js-preview.

Создайте два файла: index.js и package.json. Здесь мы используем известный в JavaScript-комьюнити фреймфорк Telegraf.

Для файла index.js скопируйте следующий код:



const bot = new Telegraf(process.env.BOT_TOKEN);
bot.start((ctx) => ctx.reply(`Hello. \nMy name Serverless Hello Teleram Bot \nI'm working on Cloud Function in the Yandex.Cloud.`))
bot.help((ctx) => ctx.reply(`Hello, ${ctx.message.from.username}.\nI can say Hello and nothing more`))
bot.on('text', (ctx) => {
    ctx.reply(`Hello, ${ctx.message.from.username}`);


});


module.exports.handler = async function (event, context) {
    const message = JSON.parse(event.body);
    await bot.handleUpdate(message);
    return {
        statusCode: 200,
        body: '',
    };
};

Этим мы научили нашего бота отвечать на команды /start, /help, а также на любой написанный текст. Но давайте сразу изменим функцию так, чтобы она на любой текст отправляла картинку. Для этого внесите изменение в файл index.js.

    ctx.replyWithPhoto('YOURAPIGWURL/sayhello.png');
    ctx.reply(`Hello, ${ctx.message.from.username}`);

Важно: не забудьте заменить YOURAPIGWURL на url из секции servers вашего API-шлюза. После создания версии функции, ваш telegram-бот будет отправлять вам картинку из Object Storage, опубликованную через API-шлюз.

Для файла package.json введите следующий код:

  "name": "ycf-telegram-example",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "MIT",
  "dependencies": {
    "telegraf": "^3.38.0"
  }
}

Укажите точку входа index.handler. Увеличьте таймаут до 5 секунд. В переменные окружения добавьте переменную BOT_TOKEN со значением токена вашего telegram-бота, полученного ранее.

Обязательно нажмите кнопку — Создать версию. После создания функции сделайте ее публичной. Запомните идентификатор вашей функции.

Шаг 6. Свяжем функцию и бота в Telegram

Теперь нам нужно соединить нашу функцию с ботом в Telegram. Для этого вернитесь в сервис API Gateway и выберете ранее созданный API-шлюз с именем for-serverless-hello-telegram-bot. Измените его спецификацию — в конце добавьте в нее секцию fshtb-function:

    post:
      x-yc-apigateway-integration:
        type: cloud-functions
        function_id: IDYOURFUNCTION
      operationId: fshtb-function

Замените IDYOURFUNCTION на id вашей функции, созданной ранее. Сохраните изменения.

Теперь для создания связи между ранее созданным телеграм-ботом и вашей функцией нужно запустить команду в терминале (командной строке).

curl --request POST --url https://api.telegram.org/botYOURTOKEN/setWebhook --header 'content-type: application/json' --data '{"url": "YOURAPIGWURL/fshtb-function"}'

Замените YOURTOKEN на токен вашего telegram-бота и YOURAPIGWURL на url из секции servers вашего API-шлюза. Нажмите Enter. После положительного ответа связь создана, и вы сможете поговорить со своим ботом. Если не вылезать из лимитов Free tier, ваш бот обойдется вам в 0 рублей.

Оставляем полезные ссылки на каналы и сообщества Serverless в мире и в России, где вы сможете найти еще больше полезных примеров использования функций:

  • Туториалы