Пишем телеграм бота на Go и AWS Lambda

от автора

Что будем делать?

Будем писать простой телеграм бот, отвечающий тем же сообщением, что и отправили.

Почему AWS Lambda ?

  1. Удобство деплоя, просто пишешь sls deploy, и lambda уже выгружена

  2. Платишь только за время, когда lambda работает

  3. Не надо настраивать никаких серверов, и беспокоиться о масштабировании

Что понадобится?

  • Установленный go

  • Nodejs и npm для установки serverless

  • AWS аккаунт для деплоя

TLDR

  • Клонируем репозиторий https://github.com/R11baka/echotgbot

  • Устанавливаем в .env файле BOT_TOKEN переменную

  • Компилируем бинарник env GOOS=linux go build -o bin/webhook main.go

  • Выгружаем лямбду с помощью sls deploy

  • Устанавливаем webhook с помощью BOT_TOKEN

Регистрация в AWS

  • Регистирируем пользователя в AWS aws console и получаем aws_access_key_id, и aws_secret_access_key и прописываем их в .aws/credentials файле

Вот как выглядит мой .aws/credentials

cat ~/.aws/credentials [default] aws_access_key_id = ADEFEFEFFEBDXK3 aws_secret_access_key = Zy6ewfir/zGaT1B2/o9JDWDSssdrla region = us-west-1

Регистрация бота

Для начала, нам надо зарегистировать бота в BotFather. Идем по ссылке, отправляем команду BotFather /newbot, придумываем имя боту, описание. В конце, BotFather вернет нам токен бота.Этот токен понадобится,нам для дальнейшей разработки.

Установка Serverless

Serverless-это framework, облегчающий настройку, деплой AWS Lambda функций. Написан на node, поэтому для его установки понадобится nodejs и npm. Устанавливаем serverless через npm

npm install -g serverless

После установки serverless проверяем, все ли установилось

sls -v Framework Core: 2.35.0 (standalone) Plugin: 4.5.3 SDK: 4.2.2 Components: 3.8.2

Теперь можно приступить к конфигурации serverless. Все настройки для serverless лежат в serverless.yml файле,который мы и создадим со следующим контентом

service: echoBot useDotenv: true configValidationMode: error # если в конфиге,чтото неправильно ,то ошибка frameworkVersion: '>=1.28.0 <2.50.0'  provider:   region: "us-west-1"   lambdaHashingVersion: "20201221"   name: aws   runtime: go1.x   logRetentionInDays: 30 # сколько дней хранить логи   endpointType: regional   tracing: # включаем трейсинг для лямбды     apiGateway: true     lambda: true   iam:     role:       statements:         - Effect: "Allow"           Resource: "*"           Action:             - "xray:*" package:   patterns:     - "bin/webhook" # деплоить только бинарник  functions:   webhook:      handler: bin/webhook     timeout: 15     description: simple echo bot     memorySize: 128 # размер памяти в мегабайтах для функции     environment:       BOT_TOKEN: ${env:BOT_TOKEN}     events:       - http:           path: /webhook           method: ANY           cors: false

Имлементация логики бота на Go

  1. Устанавливаем библиотеки telebot.v2 и aws-lambda-go

    ➜  go mod init testBot go: creating new go.mod: module testBot ➜  go get -u gopkg.in/tucnak/telebot.v2 go: gopkg.in/tucnak/telebot.v2 upgrade => v2.3.5 go: github.com/pkg/errors upgrade => v0.9.1 ➜ go get github.com/aws/aws-lambda-go go: github.com/aws/aws-lambda-go upgrade => v1.23.0

2. Создаем файл main.go с контентом

package main  import ( 	"encoding/json" 	"fmt" 	"github.com/aws/aws-lambda-go/events" 	"github.com/aws/aws-lambda-go/lambda" 	tb "gopkg.in/tucnak/telebot.v2" 	"os" )  func main() { 	settings := tb.Settings{ 		Token:       os.Getenv("BOT_TOKEN"), 		Synchronous: true, 		Verbose:     true, 	} 	tgBot, err := tb.NewBot(settings) 	if err != nil { 		fmt.Println(err) 		panic("can't create bot") 	} 	tgBot.Handle(tb.OnText, func(m *tb.Message) { 		message := m.Text 		tgBot.Send(m.Sender, message) 	}) 	lambda.Start(func(req events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) { 		var u tb.Update 		if err = json.Unmarshal([]byte(req.Body), &u); err == nil { 			tgBot.ProcessUpdate(u) 		} 		return events.APIGatewayProxyResponse{Body: "ok", StatusCode: 200}, nil  	}) }

Текущая документация в tucnak/telebot.v2 немного устарела, и если просто написать return вместо return events.APIGatewayProxyResponse{Body: "ok", StatusCode: 200}, nil, то телеграм будет повторно отправлять сообщения к боту.

Deploy бота

  • Создаем файл .env и вставляем API_TOKEN полученный от BotFather

    echo API_TOKEN={API_TOKEN_FROM_BOTFATHER} > .env
  • Проверяем serverlss конфиг с помощью команды. Не должно быть никаких ошибок.

    sls print
  • Потом собираем бинарник

    env GOOS=linux go build  -o bin/webhook main.go 
  • И выгружаем его с помощью serverless

    serverless deploy  -v

    При успешной выгрузке, мы получим в конце

    Service Information service: echoBot stage: dev region: us-west-1 stack: echoBot-dev resources: 11 api keys: None endpoints: ANY - https://y7p31bwnu1.execute-api.us-west-1.amazonaws.com/dev/webhook functions: webhook: echoBot-dev-webhook layers: None

    https://y7p31bwnu1.execute-api.us-west-1.amazonaws.com/dev/webhook => этот эндпоинт и token бота нужен нам, чтобы установить webhook

Интеграция с telegram

Осталось сообщить телеграму, какой эндпоинт дергать при получении сообщения. Делается это командой setWebhook

curl https://api.telegram.org/bot{YOUR_TOKEN}/setWebhook?url={YOUR_DEPLOYED_AWS_URL} 

Проверка что webhook установлен, происходит с помощью getWebhookInfo

➜  ~ curl https://api.telegram.org/bot1324913549:AAE1zYMH6K3hF2TOgUQoIP-E1g4rMIamck/setWebhook\?url\= https://y7p31bwnu1.execute-api.us-west-1.amazonaws.com/dev/webhook {"ok":true,"result":true,"description":"Webhook was set"} ➜  ~ curl https://api.telegram.org/bot1324913549:AAE1zYMH6K3hF2TOgUQoIP-E1g4rMIamck/getWebhookInfo {"ok":true,"result":{"url":"https://y7p31bwnu1.execute-api.us-west-1.amazonaws.com/dev/webhook","has_custom_certificate":false,"pending_update_count":0,"max_connections":40,"ip_address":"184.169.148.254"}} 

Ошибки

Если что-то пошло не так,идем в CloudWatch и смотрим логи,или же из консоли также можно посмотреть логи

sls logs -f webhook

ссылка на оригинал статьи https://habr.com/ru/post/555518/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *