144 lines
3.8 KiB
Go
144 lines
3.8 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"net/http"
|
|
"net/url"
|
|
"path"
|
|
"strconv"
|
|
)
|
|
|
|
type telegram struct {
|
|
botToken string
|
|
}
|
|
|
|
type telegramUpdate struct {
|
|
Message struct {
|
|
Chat struct {
|
|
Id int `json:"id"`
|
|
} `json:"chat"`
|
|
Id int `json:"message_id"`
|
|
Text string `json:"text"`
|
|
} `json:"message"`
|
|
}
|
|
|
|
func initTelegram() {
|
|
if appConfig.TGBotToken == "" {
|
|
fmt.Println("Telegram not configured.")
|
|
return
|
|
}
|
|
tg := &telegram{
|
|
botToken: appConfig.TGBotToken,
|
|
}
|
|
username, err := tg.getBotUsername()
|
|
if err != nil {
|
|
fmt.Println("Failed to setup Telegram:", err)
|
|
return
|
|
}
|
|
err = tg.setTelegramHook()
|
|
if err != nil {
|
|
fmt.Println("Failed to setup Telegram webhook:", err)
|
|
return
|
|
}
|
|
fmt.Println("Authorized Telegram bot on account", username)
|
|
app.telegram = tg
|
|
}
|
|
|
|
func initTelegramRouter() {
|
|
app.router.HandleFunc(path.Join("/telegramHook", appConfig.TGHookSecret), TelegramHookHandler)
|
|
}
|
|
|
|
func TelegramHookHandler(w http.ResponseWriter, r *http.Request) {
|
|
tgUpdate := &telegramUpdate{}
|
|
err := json.NewDecoder(r.Body).Decode(tgUpdate)
|
|
if err != nil {
|
|
http.Error(w, "Failed to decode body", http.StatusBadRequest)
|
|
return
|
|
}
|
|
go respondToTelegramUpdate(tgUpdate)
|
|
return
|
|
}
|
|
|
|
var telegramBaseUrl = "https://api.telegram.org/bot"
|
|
|
|
func (t *telegram) getBotUsername() (string, error) {
|
|
tgUrl, err := url.Parse(telegramBaseUrl + t.botToken + "/getMe")
|
|
if err != nil {
|
|
return "", errors.New("failed to create Telegram request")
|
|
}
|
|
req, _ := http.NewRequest(http.MethodPost, tgUrl.String(), nil)
|
|
resp, err := http.DefaultClient.Do(req)
|
|
if err != nil || resp.StatusCode != 200 {
|
|
return "", errors.New("failed to get Telegram bot info")
|
|
}
|
|
tgBotInfo := &struct {
|
|
Ok bool `json:"ok"`
|
|
Result struct {
|
|
Id int `json:"id"`
|
|
Username string `json:"username"`
|
|
} `json:"result"`
|
|
}{}
|
|
err = json.NewDecoder(resp.Body).Decode(tgBotInfo)
|
|
_ = resp.Body.Close()
|
|
if err != nil || !tgBotInfo.Ok {
|
|
return "", errors.New("failed to parse Telegram bot info")
|
|
}
|
|
// If getMe returns no username, but only an ID for whatever reason
|
|
if len(tgBotInfo.Result.Username) == 0 {
|
|
tgBotInfo.Result.Username = strconv.Itoa(tgBotInfo.Result.Id)
|
|
}
|
|
return tgBotInfo.Result.Username, nil
|
|
}
|
|
|
|
func (t *telegram) setTelegramHook() error {
|
|
if len(appConfig.BaseUrl) < 1 {
|
|
return errors.New("base URL not configured")
|
|
}
|
|
hookUrl, e := url.Parse(appConfig.BaseUrl)
|
|
if e != nil {
|
|
return errors.New("failed to parse base URL")
|
|
}
|
|
hookUrl.Path = path.Join(hookUrl.Path, path.Join("telegramHook", appConfig.TGHookSecret))
|
|
params := url.Values{}
|
|
params.Add("url", hookUrl.String())
|
|
params.Add("allowed_updates", "[\"message\"]")
|
|
tgUrl, err := url.Parse(telegramBaseUrl + t.botToken + "/setWebhook")
|
|
if err != nil {
|
|
return errors.New("failed to create Telegram request")
|
|
}
|
|
tgUrl.RawQuery = params.Encode()
|
|
req, _ := http.NewRequest(http.MethodPost, tgUrl.String(), nil)
|
|
resp, err := http.DefaultClient.Do(req)
|
|
if err != nil || resp.StatusCode != 200 {
|
|
return errors.New("failed to set Telegram webhook")
|
|
}
|
|
fmt.Println("Telegram webhook URL:", hookUrl.String())
|
|
return nil
|
|
}
|
|
|
|
func (t *telegram) sendMessage(chat int, message string) error {
|
|
return t.replyToMessage(chat, message, 0)
|
|
}
|
|
|
|
func (t *telegram) replyToMessage(chat int, message string, replyTo int) error {
|
|
params := url.Values{}
|
|
params.Add("chat_id", strconv.Itoa(chat))
|
|
if replyTo != 0 {
|
|
params.Add("reply_to_message_id", strconv.Itoa(replyTo))
|
|
}
|
|
params.Add("text", message)
|
|
tgUrl, err := url.Parse(telegramBaseUrl + t.botToken + "/sendMessage")
|
|
if err != nil {
|
|
return errors.New("failed to create Telegram request")
|
|
}
|
|
tgUrl.RawQuery = params.Encode()
|
|
req, _ := http.NewRequest(http.MethodPost, tgUrl.String(), nil)
|
|
resp, err := http.DefaultClient.Do(req)
|
|
if err != nil || resp.StatusCode != 200 {
|
|
return errors.New("failed to send Telegram message")
|
|
}
|
|
return nil
|
|
}
|