/
reply_message.go
141 lines (124 loc) · 3.66 KB
/
reply_message.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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
package handlers
import (
"context"
"github.com/g4s8/openbots/internal/bot/data"
"github.com/g4s8/openbots/pkg/api"
"github.com/g4s8/openbots/pkg/state"
"github.com/g4s8/openbots/pkg/types"
telegram "github.com/go-telegram-bot-api/telegram-bot-api/v5"
"github.com/pkg/errors"
"github.com/rs/zerolog"
)
type (
// MessageModifier apply custom modifications to telegram message reply.
MessageModifier func(*telegram.MessageConfig)
)
var (
_ types.Handler = (*MessageReply)(nil)
_ api.Handler = (*MessageReply)(nil)
)
// MessageReply handler processes telegram updates and reply message to them.
type MessageReply struct {
bot *telegram.BotAPI
sp types.StateProvider
secrets types.Secrets
template Template
modifiers []MessageModifier
logger zerolog.Logger
}
// NewMessageReply from repliers funcs.
func NewMessageReply(
bot *telegram.BotAPI,
sp types.StateProvider, secrets types.Secrets,
template Template, logger zerolog.Logger, modifiers ...MessageModifier,
) *MessageReply {
return &MessageReply{
bot: bot,
sp: sp,
secrets: secrets,
template: template,
modifiers: modifiers,
logger: logger.With().Str("handler", "reply_message").Logger(),
}
}
func (h *MessageReply) Handle(ctx context.Context, upd *telegram.Update, _ *telegram.BotAPI) error {
state := state.NewUserState()
defer state.Close()
chatID := ChatID(upd)
if err := h.sp.Load(ctx, chatID, state); err != nil {
return errors.Wrap(err, "load state")
}
secretMap, err := h.secrets.Get(ctx)
if err != nil {
return errors.Wrap(err, "get secrets")
}
data := data.FromCtx(ctx)
response, err := h.template.Format(newTemplateContext(upd, state, secretMap, data.Get()))
if err != nil {
return errors.Wrap(err, "format template")
}
msg := telegram.NewMessage(int64(chatID), response)
for _, modifier := range h.modifiers {
modifier(&msg)
}
if _, err := h.bot.Send(msg); err != nil {
return errors.Wrap(err, "reply message")
}
return nil
}
func (h *MessageReply) Call(ctx context.Context, req api.Request) error {
state := state.NewUserState()
defer state.Close()
secretMap, err := h.secrets.Get(ctx)
if err != nil {
return errors.Wrap(err, "get secrets")
}
data := data.FromApiRequest(&req)
response, err := h.template.Format(newTemplateContext(nil, state, secretMap, data.Get()))
if err != nil {
return errors.Wrap(err, "format template")
}
msg := telegram.NewMessage(int64(req.ChatID), response)
for _, modifier := range h.modifiers {
modifier(&msg)
}
if _, err := h.bot.Send(msg); err != nil {
return errors.Wrap(err, "send message")
}
return nil
}
// MessageWithKeyboard creates new message modifier to add
// custom keyboard to message.
func MessageWithKeyboard(keyboard [][]string) MessageModifier {
return func(msg *telegram.MessageConfig) {
if len(keyboard) == 0 {
return
}
buttons := make([][]telegram.KeyboardButton, len(keyboard))
for i, row := range keyboard {
buttonRow := make([]telegram.KeyboardButton, len(row))
for j, btn := range row {
buttonRow[j] = telegram.NewKeyboardButton(btn)
}
buttons[i] = buttonRow
}
msg.ReplyMarkup = telegram.NewReplyKeyboard(buttons...)
}
}
// MessageWithInlineKeyboard creates new message modifier to add
// custom inline keyboard to message.
func MessageWithInlineKeyboard(keyboard InlineKeyboard) MessageModifier {
return func(msg *telegram.MessageConfig) {
if len(keyboard) == 0 {
return
}
msg.ReplyMarkup = keyboard.telegramMarkup()
}
}
// MessageWithParseMode creates new message modifier to set
// custom parse mode for message.
func MessageWithParseMode(mode string) MessageModifier {
return func(msg *telegram.MessageConfig) {
msg.ParseMode = mode
}
}