Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Telegram Bot API Webhooks with Go, GoLang on Heroku

I use go-telegram-bot-api for building a Telegram Bot and deploying it on Heroku.

I need to set Webhooks as I used to do in Python like in this Python case.

Can't understand how to set Webhooks in go-telegram-bot-api without providing certificate files.

The main example contains such lines:

If you need to use webhooks (if you wish to run on Google App Engine), you may use a slightly different method.

package main

import (
    "gopkg.in/telegram-bot-api.v4"
    "log"
    "net/http"
)

func main() {
    bot, err := tgbotapi.NewBotAPI("MyAwesomeBotToken")
    if err != nil {
        log.Fatal(err)
    }

    bot.Debug = true

    log.Printf("Authorized on account %s", bot.Self.UserName)

    _, err = bot.SetWebhook(tgbotapi.NewWebhookWithCert("https://www.google.com:8443/"+bot.Token, "cert.pem"))
    if err != nil {
        log.Fatal(err)
    }

    updates := bot.ListenForWebhook("/" + bot.Token)
    go http.ListenAndServeTLS("0.0.0.0:8443", "cert.pem", "key.pem", nil)

    for update := range updates {
        log.Printf("%+v\n", update)
    }
}

But using Heroku for deploying how could I listen to Webhooks without providing pem certificate files?

like image 432
Ilya Rusin Avatar asked Nov 10 '17 17:11

Ilya Rusin


2 Answers

Following this https://devcenter.heroku.com/articles/getting-started-with-go to get the starter code.

initTelegram() and webhookHandler() are functions to study.

Once code is deployed to Heroku, run:

heroku logs --tail -a <YOUR-APP-NAME>

send some messages to the bot, you should see messages logged.

UPDATE 1

Check your app URL is the same as baseURL variable in your code -- run heroku info -a <YOUR-APP-NAME> -- your URL should be equal to what Web URL is.

UPDATE 2

In order to check your Telegram API Webhooks response ping this address in your browser: https://api.telegram.org/bot<YOUR BOT TOKEN GOES HERE>/getWebhookInfo where you should concatenate string bot and your actual Telegram Bot Token in that address string.

Optionally if you run your code not on Heroku, running curl from terminal could be an option according to Official Telegram API Reference:

$ curl -F "url=https://your.domain.or.ip.com" -F "certificate=@/etc/ssl/certs/bot.pem" https://api.telegram.org/bot<YOUR BOT TOKEN GOES HERE>/setWebhook

THE CODE:

package main

import (
    "encoding/json"
    "io"
    "io/ioutil"
    "log"
    "os"

    "github.com/gin-gonic/gin"
    "gopkg.in/telegram-bot-api.v4"

    _ "github.com/heroku/x/hmetrics/onload"
    _ "github.com/lib/pq"
)

var (
    bot      *tgbotapi.BotAPI
    botToken = "<YOUR BOT TOKEN GOES HERE>"
    baseURL  = "https://<YOUR-APP-NAME>.herokuapp.com/"
)

func initTelegram() {
    var err error

    bot, err = tgbotapi.NewBotAPI(botToken)
    if err != nil {
        log.Println(err)
        return
    }

    // this perhaps should be conditional on GetWebhookInfo()
    // only set webhook if it is not set properly
    url := baseURL + bot.Token
    _, err = bot.SetWebhook(tgbotapi.NewWebhook(url))
    if err != nil {
        log.Println(err)
    } 
}

func webhookHandler(c *gin.Context) {
    defer c.Request.Body.Close()

    bytes, err := ioutil.ReadAll(c.Request.Body)
    if err != nil {
        log.Println(err)
        return
    }

    var update tgbotapi.Update
    err = json.Unmarshal(bytes, &update)
    if err != nil {
        log.Println(err)
        return
    }

    // to monitor changes run: heroku logs --tail
    log.Printf("From: %+v Text: %+v\n", update.Message.From, update.Message.Text)
}

func main() {
    port := os.Getenv("PORT")

    if port == "" {
        log.Fatal("$PORT must be set")
    }

    // gin router
    router := gin.New()
    router.Use(gin.Logger())

    // telegram
    initTelegram()
    router.POST("/" + bot.Token, webhookHandler)

    err := router.Run(":" + port)
    if err != nil {
        log.Println(err)
    }
}

Good luck and have fun!

like image 184
k1m190r Avatar answered Oct 18 '22 06:10

k1m190r


If you are using Heroku for your bot, You don't need certificates. Heroku provides free SSL certificates. So, You put the URL of your app with https scheme and listen with a HTTP Server on the PORT that heroku sets for your application. See the example below to understand better.

func main() {
    // Create bot instance
    u := fetchUpdates(bot)

    go http.ListenAndServe(":" + PORT, nil)
}

func fetchUpdates(bot *tgbotapi.BotAPI) tgbotapi.UpdatesChannel {
    _, err = bot.SetWebhook(tgbotapi.NewWebhook("https://dry-hamlet-60060.herokuapp.com/instagram_profile_bot/" + bot.Token))
    if err != nil {
        fmt.Fatalln("Problem in setting Webhook", err.Error())
    }

    updates := bot.ListenForWebhook("/instagram_profile_bot/" + bot.Token)

    return updates
}
like image 36
Ishan Jain Avatar answered Oct 18 '22 06:10

Ishan Jain