Делаем чат-бот в 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 и вставьте спецификацию:

openapi: 3.0.0 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 { Telegraf } = require('telegraf'); 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.

bot.on('text', (ctx) => { 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:

/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 в мире и в России, где вы сможете найти еще больше полезных примеров использования функций:

Подписывайтесь на блог Yandex.Cloud, чтобы узнавать еще больше новостей и историй об IT и бизнесе.

Другие истории, которые активно читают наши подписчики:

0
24 комментария
Написать комментарий...
Евгений Трифонов
  мы используем известный в java-комьюнити фреймфорк Telegraf

Кажется, вы хотели написать «JavaScript-комьюнити»

Ответить
Развернуть ветку
Yandex Cloud
Автор

Спасибо! Поправили и объяснили нашему копирайтеру:) 

Ответить
Развернуть ветку
Db

Если статьи пишет пишет копирайтер, который не может отличить JavaScript от Java, ценность такой статьи — 0 рублей.

Ответить
Развернуть ветку
Евгений Трифонов

Ну слушайте, очевидно же, что в одиночку такой копирайтер просто не смог бы написать этот текст. Я не имею отношения к Яндексу, но по своей работе знаю, что такие тексты часто делаются «вмногером»: от кого-то техническая экспертиза, от кого-то грамотный русский, от кого-то оформление. И иногда на стыках вылезают шероховатости, но это «вкрались ошибки в материал от знающего человека», а не «статья с ценностью 0 рублей».

Похоже, тут в основу материала лёг доклад Антона Черноусова, где Антон случайно оговорился (позже поправился), а в текст пролезла его оговорка.

Ответить
Развернуть ветку
Василий Беляев

А ещё копирайтер неграмотен и не может понять, что слово "выберите" он всё это время писал неправильно. Яндекс, перестаньте нанимать школоту

Ответить
Развернуть ветку
Пегий Дудочник

Слишком много движений лишних.. а под капотом все равно интерпретаторы питона и ещё там чего то. Не проще ли получить API Key и самому поднять сервер бота если надо, дома либо арендовать вм у провайдера? И бота умного сделать можно, а не вот эти ваши картинки или единообразные ответы) Учите ЯП, иначе всегда будете в таких ситуациях зависимы от тех, кто их когда то освоил + платить им за пустяковых ботов.

Ответить
Развернуть ветку
Anton T.

Всё правильно!
А то ишь, понапишут микросервисов бессерверных своих, и давай по подъездам докером через кубернетис долбиться

Ответить
Развернуть ветку
Sergey Voloshin

Вебинар по этому боту https://cloud.yandex.ru/events/198

Ответить
Развернуть ветку
Аргумент Перигелия

Спасибо за инструкцию. Статью в закладки. Попробую повторить на досуге. Затем отпишусь... 👨🏻‍💻

Ответить
Развернуть ветку
Степан И.
Если не вылезать из лимитов Free tier, ваш бот обойдется вам в 0 рублей.

До 16 октября как я понимаю. После этой даты лимиты могут урезать, а потом ещё и ещё.

Ответить
Развернуть ветку
Anton T.

Кстати, да
@Yandex Cloud что нас ждёт после 16го?
В плане free tier

Ответить
Развернуть ветку
Yandex Cloud
Автор

Если есть какие-то вопросы по инструкции, можно обратиться в наше serverless-сообщество, помогут) https://t.me/YandexCloudFunctions

Ответить
Развернуть ветку
Eugen Levashov

А, в том смысле, что это бот что-то отвечает и всё. Ну, да. Это просто шаблон. Дальше учим js и добиваем боту возможностей.

Ответить
Развернуть ветку
Nikolay Kenig

Ну нееее, что-то там учить! Не! 😆😆😆😆😆

Ответить
Развернуть ветку
Eugen Levashov

Если писать статью про все сценарии ботов, то тут такой мануал на пару томов будет...)

Ответить
Развернуть ветку
Vika Belova

на 4ом шаге в API-шлюзе ошибку выдает при создании:Invalid openapi spec: while scanning for the next token found character '\t(TAB)' that cannot start any token. (Do not use \t(TAB) for indentation) in 'reader', line 2, column 1: info: ^ at [Source: (StringReader); line: 1, column: 15], все заменяю, на свои названия и прочее и никак. в чем проблема?

Ответить
Развернуть ветку
Dmitry Popov

скопируй в редактор типа vsc или pycharm, выполни "Convert indentation to Spaces", скопируй обратно. Не думаю, что актуально, но вдруг кому поможет)

Ответить
Развернуть ветку
Игорь Юдыцкий

Удаление гланд через задний проход

Ответить
Развернуть ветку
Nikolay Kenig

Это просто ответчик?
А чтобы он чтото делал, как тогда?

Ответить
Развернуть ветку
Eugen Levashov

Что, простите?

Ответить
Развернуть ветку
Yurij Georgievich

А это не старая статья а то pyton37preview(!) Nodejs12preview или эт Я - тормозит?

Ответить
Развернуть ветку
Eugene Sharawansky

Абсолютно бесплатный сервер для бота поднят на Heroku под Node.js
Redis в комплекте для "всякого такого"

Ответить
Развернуть ветку
Сфлом Христ

Телеграм 1 "м" , две ?
"Дуров" от слова "дурак" !? (машет гривой за пиндосом)
а что , инструкцию API по русски не панимаема составить как ??

Ответить
Развернуть ветку
Кирилл Косолапов

Как то сложно. Проще просто запушить код в Heroku или его отечественный аналог - Amvera Cloud. Все подхватится и развернется. И по факту это тот-же Serverless.

Ответить
Развернуть ветку
21 комментарий
Раскрывать всегда