layout: implement NewFromFS

pull/671/head v3.3.1-beta
Demian 2 months ago
parent 9eb53434a0
commit 35d5dd372a

@ -1,6 +1,6 @@
module gopkg.in/telebot.v3 module gopkg.in/telebot.v3
go 1.13 go 1.16
require ( require (
github.com/goccy/go-yaml v1.9.5 github.com/goccy/go-yaml v1.9.5

@ -3,8 +3,9 @@ package layout
import ( import (
"bytes" "bytes"
"encoding/json" "encoding/json"
"io/ioutil" "io/fs"
"log" "log"
"os"
"strings" "strings"
"sync" "sync"
"text/template" "text/template"
@ -69,7 +70,13 @@ type (
// New parses the given layout file. // New parses the given layout file.
func New(path string, funcs ...template.FuncMap) (*Layout, error) { func New(path string, funcs ...template.FuncMap) (*Layout, error) {
data, err := ioutil.ReadFile(path) return NewFromFS(os.DirFS("."), path, funcs...)
}
// NewFromFS parses the layout from the given fs.FS. It allows to read layout
// from the go:embed filesystem.
func NewFromFS(fsys fs.FS, path string, funcs ...template.FuncMap) (*Layout, error) {
data, err := fs.ReadFile(fsys, path)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -121,10 +128,10 @@ var builtinFuncs = template.FuncMap{
// webhook: (or webhook settings) // webhook: (or webhook settings)
// //
// Usage: // Usage:
//
// lt, err := layout.New("bot.yml") // lt, err := layout.New("bot.yml")
// b, err := tele.NewBot(lt.Settings()) // b, err := tele.NewBot(lt.Settings())
// // That's all! // // That's all!
//
func (lt *Layout) Settings() tele.Settings { func (lt *Layout) Settings() tele.Settings {
if lt.pref == nil { if lt.pref == nil {
panic("telebot/layout: settings is empty") panic("telebot/layout: settings is empty")
@ -183,16 +190,20 @@ func (lt *Layout) Commands() (cmds []tele.Command) {
// used in b.SetCommands later. // used in b.SetCommands later.
// //
// Example of bot.yml: // Example of bot.yml:
//
// commands: // commands:
// /start: '{{ text `cmdStart` }}' // /start: '{{ text `cmdStart` }}'
// //
// en.yml: // en.yml:
//
// cmdStart: Start the bot // cmdStart: Start the bot
// //
// ru.yml: // ru.yml:
//
// cmdStart: Запуск бота // cmdStart: Запуск бота
// //
// Usage: // Usage:
//
// b.SetCommands(lt.CommandsLocale("en"), "en") // b.SetCommands(lt.CommandsLocale("en"), "en")
// b.SetCommands(lt.CommandsLocale("ru"), "ru") // b.SetCommands(lt.CommandsLocale("ru"), "ru")
func (lt *Layout) CommandsLocale(locale string, args ...interface{}) (cmds []tele.Command) { func (lt *Layout) CommandsLocale(locale string, args ...interface{}) (cmds []tele.Command) {
@ -226,13 +237,14 @@ func (lt *Layout) CommandsLocale(locale string, args ...interface{}) (cmds []tel
// The given optional argument will be passed to the template engine. // The given optional argument will be passed to the template engine.
// //
// Example of en.yml: // Example of en.yml:
//
// start: Hi, {{.FirstName}}! // start: Hi, {{.FirstName}}!
// //
// Usage: // Usage:
//
// func onStart(c tele.Context) error { // func onStart(c tele.Context) error {
// return c.Send(lt.Text(c, "start", c.Sender())) // return c.Send(lt.Text(c, "start", c.Sender()))
// } // }
//
func (lt *Layout) Text(c tele.Context, k string, args ...interface{}) string { func (lt *Layout) Text(c tele.Context, k string, args ...interface{}) string {
locale, ok := lt.Locale(c) locale, ok := lt.Locale(c)
if !ok { if !ok {
@ -266,9 +278,9 @@ func (lt *Layout) TextLocale(locale, k string, args ...interface{}) string {
// Callback returns a callback endpoint used to handle buttons. // Callback returns a callback endpoint used to handle buttons.
// //
// Example: // Example:
//
// // Handling settings button // // Handling settings button
// b.Handle(lt.Callback("settings"), onSettings) // b.Handle(lt.Callback("settings"), onSettings)
//
func (lt *Layout) Callback(k string) tele.CallbackEndpoint { func (lt *Layout) Callback(k string) tele.CallbackEndpoint {
btn, ok := lt.buttons[k] btn, ok := lt.buttons[k]
if !ok { if !ok {
@ -287,6 +299,7 @@ func (lt *Layout) Callback(k string) tele.CallbackEndpoint {
// text: Item #{{.Number}} // text: Item #{{.Number}}
// //
// Usage: // Usage:
//
// btns := make([]tele.Btn, len(items)) // btns := make([]tele.Btn, len(items))
// for i, item := range items { // for i, item := range items {
// btns[i] = lt.Button(c, "item", struct { // btns[i] = lt.Button(c, "item", struct {
@ -301,7 +314,6 @@ func (lt *Layout) Callback(k string) tele.CallbackEndpoint {
// m := b.NewMarkup() // m := b.NewMarkup()
// m.Inline(m.Row(btns...)) // m.Inline(m.Row(btns...))
// // Your generated markup is ready. // // Your generated markup is ready.
//
func (lt *Layout) Button(c tele.Context, k string, args ...interface{}) *tele.Btn { func (lt *Layout) Button(c tele.Context, k string, args ...interface{}) *tele.Btn {
locale, ok := lt.Locale(c) locale, ok := lt.Locale(c)
if !ok { if !ok {
@ -360,13 +372,13 @@ func (lt *Layout) ButtonLocale(locale, k string, args ...interface{}) *tele.Btn
// - [settings] // - [settings]
// //
// Usage: // Usage:
//
// func onStart(c tele.Context) error { // func onStart(c tele.Context) error {
// return c.Send( // return c.Send(
// lt.Text(c, "start"), // lt.Text(c, "start"),
// lt.Markup(c, "menu"), // lt.Markup(c, "menu"),
// ) // )
// } // }
//
func (lt *Layout) Markup(c tele.Context, k string, args ...interface{}) *tele.ReplyMarkup { func (lt *Layout) Markup(c tele.Context, k string, args ...interface{}) *tele.ReplyMarkup {
locale, ok := lt.Locale(c) locale, ok := lt.Locale(c)
if !ok { if !ok {
@ -427,6 +439,7 @@ func (lt *Layout) MarkupLocale(locale, k string, args ...interface{}) *tele.Repl
// thumb_url: '{{ .PreviewURL }}' // thumb_url: '{{ .PreviewURL }}'
// //
// Usage: // Usage:
//
// func onQuery(c tele.Context) error { // func onQuery(c tele.Context) error {
// results := make(tele.Results, len(articles)) // results := make(tele.Results, len(articles))
// for i, article := range articles { // for i, article := range articles {
@ -437,7 +450,6 @@ func (lt *Layout) MarkupLocale(locale, k string, args ...interface{}) *tele.Repl
// CacheTime: 100, // CacheTime: 100,
// }) // })
// } // }
//
func (lt *Layout) Result(c tele.Context, k string, args ...interface{}) tele.Result { func (lt *Layout) Result(c tele.Context, k string, args ...interface{}) tele.Result {
locale, ok := lt.Locale(c) locale, ok := lt.Locale(c)
if !ok { if !ok {

@ -1,6 +1,7 @@
package layout package layout
import ( import (
"embed"
"os" "os"
"testing" "testing"
"time" "time"
@ -9,6 +10,9 @@ import (
tele "gopkg.in/telebot.v3" tele "gopkg.in/telebot.v3"
) )
//go:embed *
var fsys embed.FS
func TestLayout(t *testing.T) { func TestLayout(t *testing.T) {
os.Setenv("TOKEN", "TEST") os.Setenv("TOKEN", "TEST")
@ -17,10 +21,16 @@ func TestLayout(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
ltfs, err := NewFromFS(fsys, "example.yml")
if err != nil {
t.Fatal(err)
}
pref := lt.Settings() pref := lt.Settings()
assert.Equal(t, "TEST", pref.Token) assert.Equal(t, "TEST", pref.Token)
assert.Equal(t, "html", pref.ParseMode) assert.Equal(t, "html", pref.ParseMode)
assert.Equal(t, &tele.LongPoller{}, pref.Poller) assert.Equal(t, &tele.LongPoller{}, pref.Poller)
assert.Equal(t, pref, ltfs.Settings())
assert.ElementsMatch(t, []tele.Command{{ assert.ElementsMatch(t, []tele.Command{{
Text: "start", Text: "start",

Loading…
Cancel
Save