/
webhook_bot.go
104 lines (96 loc) · 2.26 KB
/
webhook_bot.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
package bot
import (
"fmt"
"github.com/brambu/brambu-telegram-bot/config"
"github.com/brambu/brambu-telegram-bot/interfaces"
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api"
"github.com/rs/zerolog/log"
"net/http"
"sync"
)
const Workers int = 4
type WebhookBot struct {
Config config.BotConfiguration
BotModules []interfaces.BotModule
}
type job struct {
update tgbotapi.Update
module interfaces.BotModule
bot *tgbotapi.BotAPI
}
func (w WebhookBot) Run() error {
w.bootstrapModules()
bot, err := tgbotapi.NewBotAPI(w.Config.BotToken)
if err != nil {
log.Error().Err(err)
panic(err)
}
log.Info().Str("bot_self_user_name", bot.Self.UserName).Msg("authorized account")
_, err = bot.SetWebhook(tgbotapi.NewWebhook(w.Config.WebhookUrl + w.Config.BotToken))
if err != nil {
log.Error().Err(err)
panic(err)
}
info, err := bot.GetWebhookInfo()
if err != nil {
log.Error().Err(err)
panic(err)
}
if info.LastErrorDate != 0 {
log.Error().
Str("last_error_message", info.LastErrorMessage).
Msg("telegram callback failed")
}
updates := bot.ListenForWebhook("/" + w.Config.BotToken)
go func() {
port := fmt.Sprintf(":%s", w.Config.Port)
err = http.ListenAndServe(port, nil)
if err != nil {
log.Error().Err(err)
}
}()
ch := make(chan *job)
wg := new(sync.WaitGroup)
for i := 0; i < Workers; i++ {
wg.Add(1)
go w.worker(ch, wg)
}
for update := range updates {
for _, module := range w.BotModules {
ch <- &job{
bot: bot,
module: module,
update: update,
}
}
}
wg.Wait()
close(ch)
return nil
}
func (w *WebhookBot) bootstrapModules() {
for _, module := range w.BotModules {
module.LoadConfig(w.Config)
}
}
func (w *WebhookBot) worker(ch chan *job, wg *sync.WaitGroup) {
defer wg.Done()
for j := range ch {
runModule(j.bot, j.module, j.update)
}
}
func runModule(bot *tgbotapi.BotAPI, module interfaces.BotModule, update tgbotapi.Update) {
name := module.Name()
if module.Evaluate(update) {
if name != nil {
log.Info().
Int("from_id", update.Message.From.ID).
Str("from_user_name", update.Message.From.UserName).
Str("text", update.Message.Text).
Str("chat_title", update.Message.Chat.Title).
Str("module_name", *name).
Msg("module exec")
}
module.Execute(bot, update)
}
}