Writing a telegram bot on Go and AWS Lambda

What do we do?

We will write a simple telegram bot that responds with the same message that was sent.





Why AWS Lambda?

  1. Convenience of deployment, just write sls deploy



    , and lambda is already unloaded





  2. You only pay for the time lambda is running





  3. No need to configure any servers and worry about scaling





What do you need?

  • Installed go





  • Nodejs and npm to install serverless





  • AWS account for deployment





TLDR

  • Clone the repository https://github.com/R11baka/echotgbot





  • Set a variable in the .env file BOT_TOKEN





  • Compiling the binary env GOOS=linux go build -o bin/webhook main.go







  • Unloading the lambda with sls deploy







  • Installing webhook with BOT_TOKEN





Sign up with 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





Integration with telegram

It remains to tell the telegram which endpoint to pull when receiving a message. This is done by the setWebhook command





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

      
      



Checking that the webhook is installed is done using 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"}}

      
      



Errors

If something went wrong, go to CloudWatch and look at the logs, or you can also view the logs from the console





sls logs -f webhook
      
      






All Articles