telebot icon indicating copy to clipboard operation
telebot copied to clipboard

Provide a working example with using a Webhook

Open Berezhnyk opened this issue 3 years ago • 2 comments

It is not clear how to configure it properly. I tried the following

Here is the code from main.go

package main

import (
	"fmt"
	"os"

	tele "gopkg.in/telebot.v3"
)

func main() {
	webhookEndpoint := os.Getenv("BOT_WEBHOOK_ENDPOINT")
	if webhookEndpoint == "" {
		panic("No BOT_WEBHOOK_ENDPOINT provided")
	}

	fmt.Println("Starting a bot")

	b, err := tele.NewBot(tele.Settings{
		Token: os.Getenv("BOT_TOKEN"),
		Poller: &tele.Webhook{
			Endpoint:    &tele.WebhookEndpoint{PublicURL: webhookEndpoint},
			DropUpdates: true,
		},
		Verbose: true,
	})
	if err != nil {
		panic("Cannot start the bot: " + err.Error())
	}

	fmt.Println("Configuring handlers...")

	b.Handle("/hello", func(c tele.Context) error {
		fmt.Println("Got a hello message")
		sent := c.Send("Hello to you too!")
		if sent != nil {
			panic(sent.Error())
		}
		return sent
	})

	b.Handle(tele.OnText, func(c tele.Context) error {
		fmt.Println("Got a message")
		sent := c.Send("Hello world!")
		if sent != nil {
			panic(sent.Error())
		}
		return sent
	})
        b.Start()
}

Created a lambda by using serverless

service: myBot
useDotenv: true
configValidationMode: error 

provider:
  region: "us-west-1"
  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: My Bot
    memorySize: 128 
    environment:
      BOT_TOKEN: ${env:BOT_TOKEN}
      BOT_WEBHOOK_ENDPOINT: ${env:BOT_WEBHOOK_ENDPOINT}
    events:
      - http:
          path: /webhook
          method: ANY
          cors: false
  1. Built and deployed the project env GOOS=linux go build -o bin/webhook main.go and serverless deploy --verbose

I see Starting a bot and Configuring handlers... in the logs, but nothing from the handlers The getWebhookInfo endpoint looks fine. Here is the response (replaced the app id and IP)

{
  "ok": true,
  "result": {
    "url": "https://[my-app-id].execute-api.us-west-1.amazonaws.com/dev/webhook",
    "has_custom_certificate": false,
    "pending_update_count": 2,
    "max_connections": 40,
    "ip_address": "IP"
  }
}

Note: After calling the webhook (https://[my-app-id].execute-api.us-west-1.amazonaws.com/dev/webhook) manually I receive this:

{
  "message": "Internal server error"
}

Basically, the issue is that the webhook endpoint always responds with 502

Berezhnyk avatar Jul 06 '22 20:07 Berezhnyk

I suggest leaving serverless out of equation first and making sure that the bot itself works, this way it could be easier to troubleshoot. It appears one needs to call SetWebhook in order to set a web hook, and your example does not seem to be doing that

AndrewSav avatar Jul 15 '22 06:07 AndrewSav

Thanks @AndrewSav for the direction. The following way works fine locally '''

webhookEndpoint := os.Getenv("BOT_WEBHOOK_ENDPOINT") if webhookEndpoint == "" { panic("No BOT_WEBHOOK_ENDPOINT provided") }

b, _ := tele.NewBot(tele.Settings{
	Token: os.Getenv("BOT_TOKEN"),
	Poller: &tele.Webhook{
		Endpoint:       &tele.WebhookEndpoint{PublicURL: webhookEndpoint},
		AllowedUpdates: []string{"callback_query", "message"},
		Listen:         ":8888",
	},
	Verbose: true,
})

''' The issue I guess is that on lambda I can't listen for any port

Berezhnyk avatar Jul 15 '22 19:07 Berezhnyk

Coming here for the same request.

Here is how it is done for AWS lambda using a node base client:

https://github.com/suntong/telegram-notify-bot-serverless/blob/a38cab3c0ff37b9cb9ea50860ea92a152b166995/handler.js#L11-L27

I.e.,

module.exports.hello = async event => {
  try {
    const body = JSON.parse(event.body);
    await bot.handleUpdate(body);
    return {
      statusCode: 200,
      body: JSON.stringify(
        {
          message: 'Ok',
        })
    };

what we need is to use bot.HandleUpdate to do the same internal stuff the library is doing from the webhook to handle a single update.

suntong avatar Feb 06 '23 20:02 suntong