telebot/layout/settings.go

218 lines
4.4 KiB
Go
Raw Normal View History

2020-09-05 22:29:24 +00:00
package layout
import (
2020-09-26 15:48:49 +00:00
"fmt"
2020-09-05 22:29:24 +00:00
"io/ioutil"
"os"
"path/filepath"
2020-09-15 16:24:29 +00:00
"strings"
2020-09-05 22:29:24 +00:00
"text/template"
"github.com/goccy/go-yaml"
tele "gopkg.in/tucnak/telebot.v3"
)
2020-10-08 19:37:57 +00:00
type Settings struct {
URL string
Token string
Updates int
2020-09-05 22:29:24 +00:00
2020-10-08 19:37:57 +00:00
LocalesDir string `json:"locales_dir"`
TokenEnv string `json:"token_env"`
ParseMode string `json:"parse_mode"`
2020-09-05 22:29:24 +00:00
2020-10-08 19:37:57 +00:00
Webhook *tele.Webhook `json:"webhook"`
LongPoller *tele.LongPoller `json:"long_poller"`
}
2020-09-05 22:29:24 +00:00
func (lt *Layout) UnmarshalYAML(data []byte) error {
var aux struct {
Settings *Settings
Config map[string]interface{}
2020-09-26 15:48:49 +00:00
Buttons yaml.MapSlice
2020-09-05 22:29:24 +00:00
Markups yaml.MapSlice
Locales map[string]map[string]string
}
if err := yaml.Unmarshal(data, &aux); err != nil {
return err
}
2020-10-08 19:37:57 +00:00
lt.Config = &Config{
v: aux.Config,
}
2020-09-05 22:29:24 +00:00
if pref := aux.Settings; pref != nil {
lt.pref = &tele.Settings{
URL: pref.URL,
Token: pref.Token,
Updates: pref.Updates,
ParseMode: pref.ParseMode,
}
if pref.TokenEnv != "" {
lt.pref.Token = os.Getenv(pref.TokenEnv)
}
if pref.Webhook != nil {
lt.pref.Poller = pref.Webhook
} else if pref.LongPoller != nil {
lt.pref.Poller = pref.LongPoller
}
}
2020-09-26 15:48:49 +00:00
lt.buttons = make(map[string]Button, len(aux.Buttons))
for _, item := range aux.Buttons {
2020-09-05 22:29:24 +00:00
k, v := item.Key.(string), item.Value
2020-09-26 15:48:49 +00:00
// 1. Shortened reply button
if v, ok := v.(string); ok {
lt.buttons[k] = Button{Text: v}
continue
}
// 2. Extended reply or inline button
2020-09-05 22:29:24 +00:00
data, err := yaml.Marshal(v)
if err != nil {
return err
}
2020-09-26 15:48:49 +00:00
var btn Button
if err := yaml.Unmarshal(data, &btn); err != nil {
return err
2020-09-05 22:29:24 +00:00
}
2020-09-26 15:48:49 +00:00
lt.buttons[k] = btn
}
2020-09-05 22:29:24 +00:00
2020-09-26 15:48:49 +00:00
lt.markups = make(map[string]Markup, len(aux.Markups))
for _, item := range aux.Markups {
k, v := item.Key.(string), item.Value
2020-09-05 22:29:24 +00:00
2020-09-26 15:48:49 +00:00
data, err := yaml.Marshal(v)
if err != nil {
return err
2020-09-05 22:29:24 +00:00
}
2020-09-26 15:48:49 +00:00
var shortenedMarkup [][]string
if yaml.Unmarshal(data, &shortenedMarkup) == nil {
// 1. Shortened reply or inline markup
2020-09-05 22:29:24 +00:00
2020-09-26 15:48:49 +00:00
kb := make([][]Button, len(shortenedMarkup))
for i, btns := range shortenedMarkup {
row := make([]Button, len(btns))
2020-09-05 22:29:24 +00:00
for j, btn := range btns {
2020-09-26 15:48:49 +00:00
b, ok := lt.buttons[btn]
if !ok {
return fmt.Errorf("telebot/layout: no %s button for %s markup", btn, k)
}
row[j] = b
2020-09-05 22:29:24 +00:00
}
kb[i] = row
}
data, err := yaml.Marshal(kb)
if err != nil {
return err
}
2020-09-25 20:17:49 +00:00
tmpl, err := template.New(k).Funcs(lt.funcs).Parse(string(data))
2020-09-05 22:29:24 +00:00
if err != nil {
return err
}
2020-09-25 20:17:49 +00:00
markup := Markup{keyboard: tmpl}
2020-09-26 15:48:49 +00:00
for _, row := range kb {
for _, btn := range row {
inline := btn.Unique != ""
if markup.inline == nil {
markup.inline = &inline
} else if *markup.inline != inline {
return fmt.Errorf("telebot/layout: mixed reply and inline buttons in %s markup", k)
}
}
}
2020-09-25 20:17:49 +00:00
lt.markups[k] = markup
2020-09-26 15:48:49 +00:00
} else {
// 2. Extended reply markup
2020-09-05 22:29:24 +00:00
2020-09-26 15:48:49 +00:00
var markup struct {
Markup `yaml:",inline"`
Keyboard [][]string `json:"keyboard"`
}
if err := yaml.Unmarshal(data, &markup); err != nil {
return err
}
2020-09-05 22:29:24 +00:00
2020-09-26 15:48:49 +00:00
kb := make([][]tele.ReplyButton, len(markup.Keyboard))
for i, btns := range markup.Keyboard {
row := make([]tele.ReplyButton, len(btns))
for j, btn := range btns {
row[j] = *lt.buttons[btn].Reply()
}
kb[i] = row
}
data, err := yaml.Marshal(kb)
2020-09-05 22:29:24 +00:00
if err != nil {
return err
}
2020-09-26 15:48:49 +00:00
tmpl, err := template.New(k).Funcs(lt.funcs).Parse(string(data))
if err != nil {
return err
2020-09-05 22:29:24 +00:00
}
2020-09-26 15:48:49 +00:00
markup.inline = new(bool)
markup.Markup.keyboard = tmpl
lt.markups[k] = markup.Markup
2020-09-05 22:29:24 +00:00
}
}
if aux.Locales == nil {
if aux.Settings.LocalesDir == "" {
aux.Settings.LocalesDir = "locales"
}
2020-09-05 22:29:24 +00:00
return lt.parseLocales(aux.Settings.LocalesDir)
}
return nil
}
func (lt *Layout) parseLocales(dir string) error {
2020-09-25 20:17:49 +00:00
lt.locales = make(map[string]*template.Template)
2020-09-15 10:31:54 +00:00
2020-09-05 22:29:24 +00:00
return filepath.Walk(dir, func(path string, fi os.FileInfo, _ error) error {
if fi == nil || fi.IsDir() {
return nil
}
data, err := ioutil.ReadFile(path)
if err != nil {
return err
}
var texts map[string]string
if err := yaml.Unmarshal(data, &texts); err != nil {
return err
}
2020-09-15 16:24:29 +00:00
name := fi.Name()
name = strings.TrimSuffix(name, filepath.Ext(name))
2020-09-05 22:29:24 +00:00
2020-09-15 16:24:29 +00:00
tmpl := template.New(name)
2020-09-15 16:42:15 +00:00
for key, text := range texts {
text = strings.Trim(text, "\r\n")
2020-09-25 20:17:49 +00:00
tmpl, err = tmpl.New(key).Funcs(lt.funcs).Parse(text)
2020-09-05 22:29:24 +00:00
if err != nil {
return err
}
}
2020-09-25 20:17:49 +00:00
lt.locales[name] = tmpl
2020-09-05 22:29:24 +00:00
return nil
})
}