Telegram Bot API 使用 Go 的 Webhooks,Heroku 上的 GoLang

Telegram Bot API Webhooks with Go, GoLang on Heroku

我使用 go-telegram-bot-api 构建 Telegram Bot 并将其部署在 Heroku 上。

我需要像在 Python 中那样设置 Webhooks,例如 in this Python case

在不提供证书文件的情况下无法理解如何在 go-telegram-bot-api 中设置 Webhooks。

主要示例包含这样几行:

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)
    }
}

但是使用 Heroku 进行部署 我如何在不提供 pem 证书文件的情况下监听 Webhooks?

如果您的机器人使用 Heroku,则不需要证书。 Heroku 提供免费的 SSL 证书。因此,您将应用程序的 URL 设置为 https 方案,并在 heroku 为您的应用程序设置的 PORT 上使用 HTTP 服务器进行监听。请参阅下面的示例以更好地理解。

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
}

按照此 https://devcenter.heroku.com/articles/getting-started-with-go 获取启动代码。

initTelegram()webhookHandler()是要研究的函数

代码部署到 Heroku 后,运行:

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

向机器人发送一些消息,您应该会看到已记录的消息。

更新 1

检查您的应用 URL 是否与代码中的 baseURL 变量相同 -- 运行 heroku info -a <YOUR-APP-NAME> - - 你的 URL 应该等于 Web URL 是什么。

更新 2

为了检查您的 Telegram API Webhooks 响应在您的浏览器中 ping 这个地址:https://api.telegram.org/bot<YOUR BOT TOKEN GOES HERE>/getWebhookInfo 您应该在该地址字符串中连接字符串 bot 和您的实际 Telegram Bot Token .

可选地,如果您 运行 您的代码不在 Heroku 上,运行ning curl 来自终端可能是一个选项,根据 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

代码:

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)
    }
}

祝你好运,玩得开心!