tg/button.go

135 lines
2.8 KiB
Go
Raw Normal View History

2023-08-19 09:12:26 +03:00
package tg
2023-07-09 01:28:59 +03:00
import (
apix "github.com/go-telegram-bot-api/telegram-bot-api/v5"
2023-12-12 19:32:30 +03:00
"fmt"
"crypto/rand"
"encoding/base64"
2023-07-09 01:28:59 +03:00
)
// The type wraps Telegram API's button to provide Action functionality.
type Button struct {
Text string
Data string
Url string
SendLocation bool
Action Action
2024-03-29 14:30:48 +03:00
// Used to skip buttons in generating by functions.
Valid bool
2023-07-09 01:28:59 +03:00
}
type ButtonMap map[string]Button
2023-07-09 01:28:59 +03:00
2024-03-29 14:30:48 +03:00
// Returns the only location button in the map and if it is there at all.
// The location map must be the ONLY one.
func (btnMap ButtonMap) LocationButton() (Button, bool) {
2023-09-19 15:21:33 +03:00
for _, btn := range btnMap {
if btn.SendLocation {
2024-03-29 14:30:48 +03:00
return btn, true
2023-09-19 15:21:33 +03:00
}
}
2024-03-29 14:30:48 +03:00
return Button{}, false
2023-09-19 15:21:33 +03:00
}
2023-07-09 01:28:59 +03:00
// Represents the reply button row.
2024-03-29 14:30:48 +03:00
type ButtonRow []Button
2023-07-09 01:28:59 +03:00
// Returns new button with the specified text and no action.
func Buttonf(format string, v ...any) Button {
2024-03-29 14:30:48 +03:00
return Button{
2023-12-12 19:32:30 +03:00
Text: fmt.Sprintf(format, v...),
2024-03-29 14:30:48 +03:00
Valid: true,
}
}
2023-12-12 19:32:30 +03:00
// Randomize buttons data to make the key unique.
2024-03-29 14:30:48 +03:00
// No guaranties about collisions though.
func (btn Button) Rand() Button {
2023-12-12 19:32:30 +03:00
rData := make([]byte, 8)
rand.Read(rData)
data := make([]byte, base64.StdEncoding.EncodedLen(len(rData)))
base64.StdEncoding.Encode(data, rData)
btn.Data = string(data)
return btn
}
// Set the URL for the button. Only for inline buttons.
func (btn Button) WithUrl(format string, v ...any) Button {
2023-12-12 23:47:32 +03:00
btn.Url = fmt.Sprintf(format, v...)
return btn
}
// Set the action when pressing the button.
// By default is nil and does nothing.
func (btn Button) WithAction(a Action) Button {
btn.Action = a
return btn
}
func (btn Button) WithData(dat string) Button {
2023-08-15 16:02:14 +03:00
btn.Data = dat
return btn
}
// Sets whether the button must send owner's location.
func (btn Button) WithSendLocation(ok bool) Button {
btn.SendLocation = ok
return btn
}
func (btn Button) Go(pth Widget) Button {
return btn.WithAction(WidgetGo{
2024-03-29 14:30:48 +03:00
Path: pth,
})
}
func (btn Button) GoWithArg(pth Widget, arg any) Button {
return btn.WithAction(WidgetGo{
Path: pth,
2024-03-29 14:30:48 +03:00
Arg: arg,
})
2023-07-09 01:28:59 +03:00
}
func (btn Button) ToTelegram() apix.KeyboardButton {
ret := apix.NewKeyboardButton(btn.Text)
if btn.SendLocation {
ret.RequestLocation = true
}
return ret
}
func (btn Button) ToTelegramInline() apix.InlineKeyboardButton {
if btn.Data != "" {
2024-03-29 14:30:48 +03:00
return apix.NewInlineKeyboardButtonData(
btn.Text,
btn.Data,
)
}
if btn.Url != "" {
2024-03-29 14:30:48 +03:00
return apix.NewInlineKeyboardButtonURL(
btn.Text,
btn.Url,
)
}
// If no match then return the data one with data the same as the text.
return apix.NewInlineKeyboardButtonData(btn.Text, btn.Text)
}
2023-07-12 14:06:05 +03:00
// Return the key of the button to identify it by messages and callbacks.
func (btn Button) Key() string {
2023-07-12 14:06:05 +03:00
if btn.Data != "" {
return btn.Data
}
2023-07-12 14:06:05 +03:00
// If no match then return the data one with data the same as the text.
return btn.Text
}
2024-03-29 14:30:48 +03:00
func NewButtonRow(btns ...Button) ButtonRow {
2023-07-09 01:28:59 +03:00
return btns
}
2024-03-29 14:30:48 +03:00