DEV Community

Stanislav Karol
Stanislav Karol

Posted on

Телеграм-бот на NodeJS. 4. Развёртывание на Amazon web service (AWS).

У нашего бота есть один недостаток: Как только мы прервём выполнение скрипта, то бот перестанет работать. Поэтому неплохо было бы опубликовать его на каком-нибудь сервере, который поддерживает работу с Node.JS. В этой заметке будет описана работа с AWS . Я предполагаю, что Вы уже зарегистрировались на этом ресурсе, у Вас все секретные ключи. Если нет, то вот здесь описано, как его получить. У меня есть безплатный ключ скором на один год, а дальше посмотрим, как сложится.
После получения ключа установите пакет

npm install -g serverless
Enter fullscreen mode Exit fullscreen mode

Запишите этот ключ:

serverless config credentials --provider provider --key key --secret secret
Enter fullscreen mode Exit fullscreen mode

Следующий шаг: создание функции AWS Lambda, которая будет запускаться через Telegram HTTP webhook. Эта функция будет отвечать за вызов Telegram API отправку результата пользователю. Чтобы создать лямбда-функцию, просто создайте новую папку на компьютере, перейдите внутрь нее, откройте окно терминала и введите следующее:

serverless create --template aws-nodejs
Enter fullscreen mode Exit fullscreen mode

Как вы, вероятно, догадались, это создаст очень простой шаблон для будущих функций Node.js . Шаблон фактически состоит из двух файлов: handler.js и serverless.yml. handler.js - точка ввода кода функции, а serverless.yml - файл конфигурации сервера, в котором можно объявить триггер сервера и другие параметры. Больше прочитать о конфигурации - ссылка .
Вот как я предлагаю настроить будущий сервер:

service: short-bot

useDotenv: true

plugins:
  - serverless-dotenv-plugin

frameworkVersion: "2"

provider:
  name: aws
  runtime: nodejs12.x

  region: eu-west-1

  apiGateway:
    shouldStartNameWithService: true
  lambdaHashingVersion: "20201221"

functions:
  hello:
    handler: handler.hello
    events:
      - http:
          path: webhook
          method: post
          cors: true

Enter fullscreen mode Exit fullscreen mode

В каталоге этого проекта сделайте команды:

npm init -y
npm i --save dotenv node-fetch telegraf
npm i --save-dev serverless serverless-dotenv-plugin
Enter fullscreen mode Exit fullscreen mode

Мы сейчас сделали очень многое: сделали шаблон проекта, который можно будет опубликовать на амазоне. Для публикации нам понадобится пакет serverless, а для разработки - serverless-dotenv-plugin, который поможет нам во время развертывания подхватывать переменные из файла .env.
Теперь в этот проект скопируйте все файлы из каталога, где у нас был телеграм-бот и давайте немного изменим файл handler.js:

"use strict";

const { bot } = require("./bot.js");
const { getResponseHeaders } = require("./lib/common");

exports.getResponseHeaders = () => {
  return {
    "Access-Control-Allow-Origin": "*",
  };
};

/**
 * Вебхук для бота
 */
module.exports.hello = async (event) => {
  try {
    let body =
      event.body[0] === "{"
        ? JSON.parse(event.body)
        : JSON.parse(Buffer.from(event.body, "base64"));
    await bot.handleUpdate(body);
    return { statusCode: 200, body: "" };
  } catch (err) {
    return {
      statusCode: err.statusCode ? err.statusCode : 500,
      headers: getResponseHeaders(),
      body: JSON.stringify({
        error: err.name ? err.name : "Exception",
        message: err.message ? err.message : "Unknown error",
      }),
    };
  }
};

/**
 * Устновка веб-хука.
 * Если вызвать этот метод, то хук вступит в силу
 */
module.exports.setWebhook = async (event) => {
  try {
    const url = `https://${event.headers.Host}/${event.requestContext.stage}/webhook`;
    await bot.telegram.setWebhook(url);
    return {
      statusCode: 200,
      headers: getResponseHeaders(),
      body: JSON.stringify({ url }),
    };
  } catch (err) {
    return {
      statusCode: err.statusCode ? err.statusCode : 500,
      headers: getResponseHeaders(),
      body: JSON.stringify({
        error: err.name ? err.name : "Exception",
        message: err.message ? err.message : "Unknown error",
      }),
    };
  }
};
Enter fullscreen mode Exit fullscreen mode

Функция getResponseHeaders формирует заголовки ответа.
Функция hello, о которой говорилось в файле serverless.yml это и есть тот самый веб-хук, который будет отвечать за работу нашего бота.
Функция setWebhook - это метод, который привязывает веб-хук к боту. Как вы поняли, ключевые строки в нём это

1 const url = `https://${event.headers.Host}/${event.requestContext.stage}/webhook`;
2 bot.telegram.setWebhook(url);
Enter fullscreen mode Exit fullscreen mode

В первой строке мы получаем url нашего метода, когда он будет опубликован, вторая вызывает метод API телеграмм-бота.
Для публикации нужно слегка изменить файл bot.js. Поскольку наш бот будет теперь запущен не на локальной машине, нужно закомментировать строку bot.launch(); и ниже написать:

module.exports = {
  bot,
};
Enter fullscreen mode Exit fullscreen mode

У себя в проекте файл bot.js я переместил в каталог telegramBot, изменил пути в require.
Далее в секции scripts в package.json добавим:

{
  "deploy": "sls deploy",
  "logs": "sls logs --function hello -t"
}
Enter fullscreen mode Exit fullscreen mode

С помощью команды npm run local можно будет запустить функцию локально, deploy - задеплоить в amazon, logs - для вывода потока логов в консоль.

Деплой

Командой npm run deploy можно задеплоить функцию в AWS. В терминале вы будете видеть весь процесс деплоя лямбды (все файлы складываются в zip архив и заливаются в S3). В итоге вы получите постоянный эндпоинт, что-то типа: https://sg2bxp8khj.execute-api.us-east-2.amazonaws.com/dev/, его нужно установить в качестве вебхука для телеграма.
Для установки хука нужно отправить POST-запрос на адрес функции SetWebhook, который мы получили после развёртывания:
setWebhook
Запрос можно отправить используя команду curl -X POST https://address либо используя программу Postman. Если всё прошло без ошибок, то Ваш бот теперь обосновался на сервере амазон, поздравляю!

Ссылки

Вот какие материалы мне помогли в развёртывании на амазоне:

Top comments (0)