mirror of
https://github.com/Luzifer/twitch-bot.git
synced 2025-01-04 10:46:02 +00:00
Extract template functions into registry
Signed-off-by: Knut Ahlers <knut@ahlers.me>
This commit is contained in:
parent
29fd5f25f5
commit
024980ee14
5 changed files with 155 additions and 71 deletions
64
functions.go
Normal file
64
functions.go
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
"text/template"
|
||||||
|
|
||||||
|
korvike "github.com/Luzifer/korvike/functions"
|
||||||
|
"github.com/go-irc/irc"
|
||||||
|
)
|
||||||
|
|
||||||
|
var tplFuncs = newTemplateFuncProvider()
|
||||||
|
|
||||||
|
type (
|
||||||
|
templateFuncGetter func(*irc.Message, *rule, map[string]interface{}) interface{}
|
||||||
|
templateFuncProvider struct {
|
||||||
|
funcs map[string]templateFuncGetter
|
||||||
|
lock *sync.RWMutex
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func newTemplateFuncProvider() *templateFuncProvider {
|
||||||
|
out := &templateFuncProvider{
|
||||||
|
funcs: map[string]templateFuncGetter{},
|
||||||
|
lock: new(sync.RWMutex),
|
||||||
|
}
|
||||||
|
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *templateFuncProvider) GetFuncMap(m *irc.Message, r *rule, fields map[string]interface{}) template.FuncMap {
|
||||||
|
t.lock.RLock()
|
||||||
|
defer t.lock.RUnlock()
|
||||||
|
|
||||||
|
out := make(template.FuncMap)
|
||||||
|
|
||||||
|
for n, fg := range t.funcs {
|
||||||
|
out[n] = fg(m, r, fields)
|
||||||
|
}
|
||||||
|
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *templateFuncProvider) Register(name string, fg templateFuncGetter) {
|
||||||
|
t.lock.Lock()
|
||||||
|
defer t.lock.Unlock()
|
||||||
|
|
||||||
|
t.funcs[name] = fg
|
||||||
|
}
|
||||||
|
|
||||||
|
func genericTemplateFunctionGetter(f interface{}) templateFuncGetter {
|
||||||
|
return func(*irc.Message, *rule, map[string]interface{}) interface{} { return f }
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
// Register Korvike functions
|
||||||
|
for n, f := range korvike.GetFunctionMap() {
|
||||||
|
tplFuncs.Register(n, genericTemplateFunctionGetter(f))
|
||||||
|
}
|
||||||
|
|
||||||
|
tplFuncs.Register("toLower", genericTemplateFunctionGetter(strings.ToLower))
|
||||||
|
tplFuncs.Register("toUpper", genericTemplateFunctionGetter(strings.ToUpper))
|
||||||
|
tplFuncs.Register("followDate", genericTemplateFunctionGetter(twitch.GetFollowDate))
|
||||||
|
}
|
25
functions_counter.go
Normal file
25
functions_counter.go
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/go-irc/irc"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
tplFuncs.Register("channelCounter", func(m *irc.Message, r *rule, fields map[string]interface{}) interface{} {
|
||||||
|
return func(name string) (string, error) {
|
||||||
|
channel, ok := fields["channel"].(string)
|
||||||
|
if !ok {
|
||||||
|
return "", errors.New("channel not available")
|
||||||
|
}
|
||||||
|
|
||||||
|
return strings.Join([]string{channel, name}, ":"), nil
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
tplFuncs.Register("counterValue", genericTemplateFunctionGetter(func(name string, _ ...string) int64 {
|
||||||
|
return store.GetCounterValue(name)
|
||||||
|
}))
|
||||||
|
}
|
41
functions_irc.go
Normal file
41
functions_irc.go
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/go-irc/irc"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
tplFuncs.Register("arg", func(m *irc.Message, r *rule, fields map[string]interface{}) interface{} {
|
||||||
|
return func(arg int) (string, error) {
|
||||||
|
msgParts := strings.Split(m.Trailing(), " ")
|
||||||
|
if len(msgParts) <= arg {
|
||||||
|
return "", errors.New("argument not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
return msgParts[arg], nil
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
tplFuncs.Register("fixUsername", genericTemplateFunctionGetter(func(username string) string { return strings.TrimLeft(username, "@#") }))
|
||||||
|
|
||||||
|
tplFuncs.Register("group", func(m *irc.Message, r *rule, fields map[string]interface{}) interface{} {
|
||||||
|
return func(idx int) (string, error) {
|
||||||
|
fields := r.matchMessage.FindStringSubmatch(m.Trailing())
|
||||||
|
if len(fields) <= idx {
|
||||||
|
return "", errors.New("group not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
return fields[idx], nil
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
tplFuncs.Register("tag", func(m *irc.Message, r *rule, fields map[string]interface{}) interface{} {
|
||||||
|
return func(tag string) string {
|
||||||
|
s, _ := m.GetTag(tag)
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
16
functions_twitch.go
Normal file
16
functions_twitch.go
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
tplFuncs.Register("recentGame", genericTemplateFunctionGetter(func(username string, v ...string) (string, error) {
|
||||||
|
game, _, err := twitch.GetRecentStreamInfo(strings.TrimLeft(username, "#"))
|
||||||
|
if err != nil && len(v) > 0 {
|
||||||
|
return v[0], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return game, err
|
||||||
|
}))
|
||||||
|
}
|
|
@ -2,85 +2,14 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"strings"
|
|
||||||
"text/template"
|
"text/template"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
korvike "github.com/Luzifer/korvike/functions"
|
|
||||||
|
|
||||||
"github.com/go-irc/irc"
|
"github.com/go-irc/irc"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
func formatMessage(tplString string, m *irc.Message, r *rule, fields map[string]interface{}) (string, error) {
|
func formatMessage(tplString string, m *irc.Message, r *rule, fields map[string]interface{}) (string, error) {
|
||||||
// Create anonymous functions in current context in order to access function variables
|
|
||||||
messageFunctions := make(template.FuncMap)
|
|
||||||
for n, f := range korvike.GetFunctionMap() {
|
|
||||||
messageFunctions[n] = f
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generic functions
|
|
||||||
messageFunctions["toLower"] = strings.ToLower
|
|
||||||
messageFunctions["toUpper"] = strings.ToUpper
|
|
||||||
messageFunctions["followDate"] = twitch.GetFollowDate
|
|
||||||
|
|
||||||
// Message specific functions
|
|
||||||
messageFunctions["arg"] = func(arg int) (string, error) {
|
|
||||||
msgParts := strings.Split(m.Trailing(), " ")
|
|
||||||
if len(msgParts) <= arg {
|
|
||||||
return "", errors.New("argument not found")
|
|
||||||
}
|
|
||||||
|
|
||||||
return msgParts[arg], nil
|
|
||||||
}
|
|
||||||
|
|
||||||
messageFunctions["channelCounter"] = func(name string) (string, error) {
|
|
||||||
channel, ok := fields["channel"].(string)
|
|
||||||
if !ok {
|
|
||||||
return "", errors.New("channel not available")
|
|
||||||
}
|
|
||||||
|
|
||||||
return strings.Join([]string{channel, name}, ":"), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
messageFunctions["counterValue"] = func(name string, _ ...string) int64 {
|
|
||||||
return store.GetCounterValue(name)
|
|
||||||
}
|
|
||||||
|
|
||||||
messageFunctions["fixUsername"] = func(username string) string { return strings.TrimLeft(username, "@#") }
|
|
||||||
|
|
||||||
messageFunctions["group"] = func(idx int) (string, error) {
|
|
||||||
fields := r.matchMessage.FindStringSubmatch(m.Trailing())
|
|
||||||
if len(fields) <= idx {
|
|
||||||
return "", errors.New("group not found")
|
|
||||||
}
|
|
||||||
|
|
||||||
return fields[idx], nil
|
|
||||||
}
|
|
||||||
|
|
||||||
messageFunctions["recentGame"] = func(username string, v ...string) (string, error) {
|
|
||||||
game, _, err := twitch.GetRecentStreamInfo(strings.TrimLeft(username, "#"))
|
|
||||||
if err != nil && len(v) > 0 {
|
|
||||||
return v[0], nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return game, err
|
|
||||||
}
|
|
||||||
|
|
||||||
messageFunctions["tag"] = func(tag string) string {
|
|
||||||
s, _ := m.GetTag(tag)
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse and execute template
|
|
||||||
tpl, err := template.
|
|
||||||
New(tplString).
|
|
||||||
Funcs(messageFunctions).
|
|
||||||
Parse(tplString)
|
|
||||||
if err != nil {
|
|
||||||
return "", errors.Wrap(err, "parse template")
|
|
||||||
}
|
|
||||||
|
|
||||||
if fields == nil {
|
if fields == nil {
|
||||||
fields = map[string]interface{}{}
|
fields = map[string]interface{}{}
|
||||||
}
|
}
|
||||||
|
@ -93,6 +22,15 @@ func formatMessage(tplString string, m *irc.Message, r *rule, fields map[string]
|
||||||
fields["channel"] = m.Params[0]
|
fields["channel"] = m.Params[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Parse and execute template
|
||||||
|
tpl, err := template.
|
||||||
|
New(tplString).
|
||||||
|
Funcs(tplFuncs.GetFuncMap(m, r, fields)).
|
||||||
|
Parse(tplString)
|
||||||
|
if err != nil {
|
||||||
|
return "", errors.Wrap(err, "parse template")
|
||||||
|
}
|
||||||
|
|
||||||
buf := new(bytes.Buffer)
|
buf := new(bytes.Buffer)
|
||||||
err = tpl.Execute(buf, fields)
|
err = tpl.Execute(buf, fields)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue