Rework Telegram integration
This commit is contained in:
parent
95952aae6b
commit
41e2766958
|
@ -32,6 +32,8 @@ You can configure some settings using a `config.json` file in the working direct
|
||||||
|
|
||||||
`port` (`8080`): Set the port to which KISSS should listen
|
`port` (`8080`): Set the port to which KISSS should listen
|
||||||
|
|
||||||
|
`baseUrl` (optional, required for Telegram): Set the base URL on which KISSS runs
|
||||||
|
|
||||||
`dnt` (`true`): Set whether or not KISSS should respect Do-Not-Track headers some browsers send
|
`dnt` (`true`): Set whether or not KISSS should respect Do-Not-Track headers some browsers send
|
||||||
|
|
||||||
`dbPath` (`data/kis3.db`): Set the path for the SQLite database (relative to the working directory - in the Docker container it's `/app`).
|
`dbPath` (`data/kis3.db`): Set the path for the SQLite database (relative to the working directory - in the Docker container it's `/app`).
|
||||||
|
@ -50,7 +52,7 @@ The configuration file can look like this:
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
If you specify an environment variable (`PORT`, `DNT`, `DB_PATH`, `STATS_USERNAME`, `STATS_PASSWORD`), that will override the settings from the configuration file.
|
If you specify an environment variable (`PORT`, `BASE_URL`, `DNT`, `DB_PATH`, `STATS_USERNAME`, `STATS_PASSWORD`), that will override the settings from the configuration file.
|
||||||
|
|
||||||
### Email
|
### Email
|
||||||
|
|
||||||
|
@ -68,7 +70,9 @@ To enable email integration for sending reports, you need to add some configurat
|
||||||
|
|
||||||
The Telegram integration allows sending reports via Telegram and also requesting stats via Telegram. For that the following configuration value must be set:
|
The Telegram integration allows sending reports via Telegram and also requesting stats via Telegram. For that the following configuration value must be set:
|
||||||
|
|
||||||
`tgBotToken`: Token for the Telegram bot, which you can request via the [Bot Father](https://t.me/BotFather).
|
`tgBotToken`: Token for the Telegram bot, which you can request via the [Bot Father](https://t.me/BotFather)
|
||||||
|
|
||||||
|
`tgHookSecret` (optional): Secret, so nobody (except KISSS and Telegram) knows the URL to which Telegram should send updates about new messages
|
||||||
|
|
||||||
## Add to website
|
## Add to website
|
||||||
|
|
||||||
|
|
15
config.go
15
config.go
|
@ -10,6 +10,7 @@ import (
|
||||||
|
|
||||||
type config struct {
|
type config struct {
|
||||||
Port string `json:"port"`
|
Port string `json:"port"`
|
||||||
|
BaseUrl string `json:"baseUrl"`
|
||||||
Dnt bool `json:"dnt"`
|
Dnt bool `json:"dnt"`
|
||||||
DbPath string `json:"dbPath"`
|
DbPath string `json:"dbPath"`
|
||||||
StatsUsername string `json:"statsUsername"`
|
StatsUsername string `json:"statsUsername"`
|
||||||
|
@ -19,17 +20,15 @@ type config struct {
|
||||||
SmtpPassword string `json:"smtpPassword"`
|
SmtpPassword string `json:"smtpPassword"`
|
||||||
SmtpHost string `json:"smtpHost"`
|
SmtpHost string `json:"smtpHost"`
|
||||||
TGBotToken string `json:"tgBotToken"`
|
TGBotToken string `json:"tgBotToken"`
|
||||||
|
TGHookSecret string `json:"tgHookSecret"`
|
||||||
Reports []report `json:"reports"`
|
Reports []report `json:"reports"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
appConfig = &config{
|
appConfig = &config{
|
||||||
Port: "8080",
|
Port: "8080",
|
||||||
Dnt: true,
|
Dnt: true,
|
||||||
DbPath: "data/kis3.db",
|
DbPath: "data/kis3.db",
|
||||||
StatsUsername: "",
|
|
||||||
StatsPassword: "",
|
|
||||||
TGBotToken: "",
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -58,6 +57,10 @@ func overwriteEnvVarValues(appConfig *config) {
|
||||||
if set {
|
if set {
|
||||||
appConfig.Port = port
|
appConfig.Port = port
|
||||||
}
|
}
|
||||||
|
baseUrl, set := os.LookupEnv("BASE_URL")
|
||||||
|
if set {
|
||||||
|
appConfig.BaseUrl = baseUrl
|
||||||
|
}
|
||||||
dntString, set := os.LookupEnv("DNT")
|
dntString, set := os.LookupEnv("DNT")
|
||||||
dntBool, e := strconv.ParseBool(dntString)
|
dntBool, e := strconv.ParseBool(dntString)
|
||||||
if set && e == nil {
|
if set && e == nil {
|
||||||
|
|
2
go.mod
2
go.mod
|
@ -4,7 +4,6 @@ go 1.14
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/go-sql-driver/mysql v1.5.0 // indirect
|
github.com/go-sql-driver/mysql v1.5.0 // indirect
|
||||||
github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible
|
|
||||||
github.com/gobuffalo/packr/v2 v2.8.0
|
github.com/gobuffalo/packr/v2 v2.8.0
|
||||||
github.com/google/uuid v1.1.1 // indirect
|
github.com/google/uuid v1.1.1 // indirect
|
||||||
github.com/gorilla/handlers v1.4.2
|
github.com/gorilla/handlers v1.4.2
|
||||||
|
@ -18,7 +17,6 @@ require (
|
||||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
|
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
|
||||||
github.com/rubenv/sql-migrate v0.0.0-20200401080106-baf4e4b6812c
|
github.com/rubenv/sql-migrate v0.0.0-20200401080106-baf4e4b6812c
|
||||||
github.com/sirupsen/logrus v1.5.0 // indirect
|
github.com/sirupsen/logrus v1.5.0 // indirect
|
||||||
github.com/technoweenie/multipartstreamer v1.0.1 // indirect
|
|
||||||
github.com/whiteshtef/clockwork v0.0.0-20200221012748-027e62affd84
|
github.com/whiteshtef/clockwork v0.0.0-20200221012748-027e62affd84
|
||||||
golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59 // indirect
|
golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59 // indirect
|
||||||
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a // indirect
|
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a // indirect
|
||||||
|
|
4
go.sum
4
go.sum
|
@ -36,8 +36,6 @@ github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG
|
||||||
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
|
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
|
||||||
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||||
github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible h1:2cauKuaELYAEARXRkq2LrJ0yDDv1rW7+wrTEdVL3uaU=
|
|
||||||
github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible/go.mod h1:qf9acutJ8cwBUhm1bqgz6Bei9/C/c93FPDljKWwsOgM=
|
|
||||||
github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI=
|
github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI=
|
||||||
github.com/gobuffalo/envy v1.7.1 h1:OQl5ys5MBea7OGCdvPbBJWRgnhC/fGona6QKfvFeau8=
|
github.com/gobuffalo/envy v1.7.1 h1:OQl5ys5MBea7OGCdvPbBJWRgnhC/fGona6QKfvFeau8=
|
||||||
github.com/gobuffalo/envy v1.7.1/go.mod h1:FurDp9+EDPE4aIUS3ZLyD+7/9fpx7YRt/ukY6jIHf0w=
|
github.com/gobuffalo/envy v1.7.1/go.mod h1:FurDp9+EDPE4aIUS3ZLyD+7/9fpx7YRt/ukY6jIHf0w=
|
||||||
|
@ -180,8 +178,6 @@ github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJy
|
||||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
|
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
|
||||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||||
github.com/technoweenie/multipartstreamer v1.0.1 h1:XRztA5MXiR1TIRHxH2uNxXxaIkKQDeX7m2XsSOlQEnM=
|
|
||||||
github.com/technoweenie/multipartstreamer v1.0.1/go.mod h1:jNVxdtShOxzAsukZwTSw6MDx5eUJoiEBsSvzDU9uzog=
|
|
||||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||||
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
|
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
|
||||||
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
|
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
|
||||||
|
|
21
main.go
21
main.go
|
@ -8,7 +8,6 @@ import (
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api"
|
|
||||||
"github.com/gobuffalo/packr/v2"
|
"github.com/gobuffalo/packr/v2"
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
)
|
)
|
||||||
|
@ -16,7 +15,7 @@ import (
|
||||||
type kis3 struct {
|
type kis3 struct {
|
||||||
router *mux.Router
|
router *mux.Router
|
||||||
staticBox *packr.Box
|
staticBox *packr.Box
|
||||||
tgBot *tgbotapi.BotAPI
|
telegram *telegram
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -32,12 +31,11 @@ func main() {
|
||||||
if e != nil {
|
if e != nil {
|
||||||
log.Fatal("Database setup failed:", e)
|
log.Fatal("Database setup failed:", e)
|
||||||
}
|
}
|
||||||
|
initTelegram()
|
||||||
initRouter()
|
initRouter()
|
||||||
initTelegramBot()
|
|
||||||
// Start
|
// Start
|
||||||
go startListeningToWeb()
|
go startListeningToWeb()
|
||||||
go startReports()
|
go startReports()
|
||||||
go startStatsTelegram()
|
|
||||||
// Graceful stop
|
// Graceful stop
|
||||||
var gracefulStop = make(chan os.Signal, 1)
|
var gracefulStop = make(chan os.Signal, 1)
|
||||||
signal.Notify(gracefulStop, os.Interrupt, syscall.SIGTERM)
|
signal.Notify(gracefulStop, os.Interrupt, syscall.SIGTERM)
|
||||||
|
@ -50,20 +48,9 @@ func initRouter() {
|
||||||
app.router = mux.NewRouter()
|
app.router = mux.NewRouter()
|
||||||
initStatsRouter()
|
initStatsRouter()
|
||||||
initTrackingRouter()
|
initTrackingRouter()
|
||||||
}
|
if app.telegram != nil {
|
||||||
|
initTelegramRouter()
|
||||||
func initTelegramBot() {
|
|
||||||
if appConfig.TGBotToken == "" {
|
|
||||||
fmt.Println("Telegram not configured.")
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
bot, e := tgbotapi.NewBotAPI(appConfig.TGBotToken)
|
|
||||||
if e != nil {
|
|
||||||
fmt.Println("Failed to setup Telegram:", e)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
fmt.Println("Authorized Telegram bot on account", bot.Self.UserName)
|
|
||||||
app.tgBot = bot
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func startListeningToWeb() {
|
func startListeningToWeb() {
|
||||||
|
|
|
@ -2,7 +2,6 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api"
|
|
||||||
"github.com/jordan-wright/email"
|
"github.com/jordan-wright/email"
|
||||||
"github.com/whiteshtef/clockwork"
|
"github.com/whiteshtef/clockwork"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
@ -17,7 +16,7 @@ type report struct {
|
||||||
Query string `json:"query"`
|
Query string `json:"query"`
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
To string `json:"to"`
|
To string `json:"to"`
|
||||||
TGUserId int64 `json:"tgUserId"`
|
TGUserId int `json:"tgUserId"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func startReports() {
|
func startReports() {
|
||||||
|
@ -82,12 +81,11 @@ func sendMail(r *report, content []byte) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func sendTelegram(r *report, content []byte) {
|
func sendTelegram(r *report, content []byte) {
|
||||||
if r.TGUserId == 0 || app.tgBot == nil {
|
if r.TGUserId == 0 || app.telegram == nil {
|
||||||
fmt.Println("No valid report configuration")
|
fmt.Println("No valid report configuration")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
msg := tgbotapi.NewMessage(r.TGUserId, r.Name+"\n\n"+string(content))
|
e := app.telegram.sendMessage(r.TGUserId, r.Name+"\n\n"+string(content))
|
||||||
_, e := app.tgBot.Send(msg)
|
|
||||||
if e != nil {
|
if e != nil {
|
||||||
fmt.Println("Sending report failed:", e)
|
fmt.Println("Sending report failed:", e)
|
||||||
return
|
return
|
||||||
|
|
63
stats.go
63
stats.go
|
@ -9,9 +9,7 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api"
|
|
||||||
"kis3.dev/kis3/helpers"
|
"kis3.dev/kis3/helpers"
|
||||||
"github.com/whiteshtef/clockwork"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func initStatsRouter() {
|
func initStatsRouter() {
|
||||||
|
@ -134,54 +132,31 @@ func sendChartResponse(result []*RequestResultRow, w http.ResponseWriter) {
|
||||||
_ = t.Execute(w, data)
|
_ = t.Execute(w, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
func startStatsTelegram() {
|
func respondToTelegramUpdate(u *telegramUpdate) {
|
||||||
if app.tgBot == nil {
|
if app.telegram != nil && strings.HasPrefix(u.Message.Text, "/stats") {
|
||||||
return
|
response := ""
|
||||||
}
|
fakeUrl, e := url.Parse("/stats?" + strings.TrimSpace(strings.TrimPrefix(u.Message.Text, "/stats")))
|
||||||
u := tgbotapi.NewUpdate(0)
|
if e != nil {
|
||||||
scheduler := clockwork.NewScheduler()
|
response = "Request failed"
|
||||||
scheduler.Schedule().Every(5).Seconds().Do(func() {
|
} else {
|
||||||
checkForTelegramUpdates(&u)
|
if appConfig.statsAuth() && (fakeUrl.Query().Get("username") != appConfig.StatsUsername || fakeUrl.Query().Get("password") != appConfig.StatsPassword) {
|
||||||
})
|
response = "Not authorized. Add username=yourusername&password=yourpassword to the query."
|
||||||
scheduler.Run()
|
|
||||||
}
|
|
||||||
|
|
||||||
func checkForTelegramUpdates(u *tgbotapi.UpdateConfig) {
|
|
||||||
updates, e := app.tgBot.GetUpdates(*u)
|
|
||||||
if e != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
for _, update := range updates {
|
|
||||||
if update.Message != nil && update.Message.Command() == "stats" {
|
|
||||||
response := ""
|
|
||||||
fakeUrl, e := url.Parse("/stats?" + update.Message.CommandArguments())
|
|
||||||
if e != nil {
|
|
||||||
response = "Request failed"
|
|
||||||
} else {
|
} else {
|
||||||
if appConfig.statsAuth() && (fakeUrl.Query().Get("username") != appConfig.StatsUsername || fakeUrl.Query().Get("password") != appConfig.StatsPassword) {
|
result, e := doRequest(fakeUrl.Query())
|
||||||
response = "Not authorized. Add username=yourusername&password=yourpassword to the query."
|
if e != nil {
|
||||||
|
response = "Request failed"
|
||||||
} else {
|
} else {
|
||||||
result, e := doRequest(fakeUrl.Query())
|
rowStrings := make([]string, len(result))
|
||||||
if e != nil {
|
for i, row := range result {
|
||||||
response = "Request failed"
|
rowStrings[i] = (*row).First + ": " + strconv.Itoa((*row).Second)
|
||||||
} else {
|
|
||||||
rowStrings := make([]string, len(result))
|
|
||||||
for i, row := range result {
|
|
||||||
rowStrings[i] = (*row).First + ": " + strconv.Itoa((*row).Second)
|
|
||||||
}
|
|
||||||
response = strings.Join(rowStrings, "\n")
|
|
||||||
}
|
}
|
||||||
|
response = strings.Join(rowStrings, "\n")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
msg := tgbotapi.NewMessage(update.Message.Chat.ID, response)
|
|
||||||
msg.ReplyToMessageID = update.Message.MessageID
|
|
||||||
_, e = app.tgBot.Send(msg)
|
|
||||||
if e != nil {
|
|
||||||
fmt.Println("Failed to send message:", e)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if update.UpdateID >= u.Offset {
|
e = app.telegram.replyToMessage(u.Message.Chat.Id, response, u.Message.Id)
|
||||||
u.Offset = update.UpdateID + 1
|
if e != nil {
|
||||||
|
fmt.Println("Failed to send message:", e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,143 @@
|
||||||
|
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
|
||||||
|
}
|
Reference in New Issue