2021-04-21 20:43:33 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2021-10-13 12:30:45 +00:00
|
|
|
"fmt"
|
2021-04-21 20:43:33 +00:00
|
|
|
"strings"
|
|
|
|
"sync"
|
|
|
|
"text/template"
|
2021-08-19 13:33:56 +00:00
|
|
|
"time"
|
2021-04-21 20:43:33 +00:00
|
|
|
|
2022-10-02 13:13:49 +00:00
|
|
|
"github.com/Masterminds/sprig/v3"
|
2021-04-21 20:43:33 +00:00
|
|
|
"github.com/go-irc/irc"
|
2021-08-19 14:40:34 +00:00
|
|
|
log "github.com/sirupsen/logrus"
|
2021-11-25 22:48:16 +00:00
|
|
|
|
2022-10-02 13:13:49 +00:00
|
|
|
"github.com/Luzifer/go_helpers/v2/str"
|
2021-11-25 22:48:16 +00:00
|
|
|
korvike "github.com/Luzifer/korvike/functions"
|
2022-11-02 21:38:14 +00:00
|
|
|
"github.com/Luzifer/twitch-bot/v3/plugins"
|
2021-04-21 20:43:33 +00:00
|
|
|
)
|
|
|
|
|
2022-10-02 13:13:49 +00:00
|
|
|
var (
|
|
|
|
korvikeBlacklist = []string{"now"}
|
|
|
|
sprigBlacklist = []string{"env"}
|
|
|
|
tplFuncs = newTemplateFuncProvider()
|
|
|
|
)
|
2021-04-21 20:43:33 +00:00
|
|
|
|
2021-08-19 14:40:34 +00:00
|
|
|
type templateFuncProvider struct {
|
|
|
|
funcs map[string]plugins.TemplateFuncGetter
|
|
|
|
lock *sync.RWMutex
|
|
|
|
}
|
2021-04-21 20:43:33 +00:00
|
|
|
|
|
|
|
func newTemplateFuncProvider() *templateFuncProvider {
|
|
|
|
out := &templateFuncProvider{
|
2021-08-19 14:40:34 +00:00
|
|
|
funcs: map[string]plugins.TemplateFuncGetter{},
|
2021-04-21 20:43:33 +00:00
|
|
|
lock: new(sync.RWMutex),
|
|
|
|
}
|
|
|
|
|
|
|
|
return out
|
|
|
|
}
|
|
|
|
|
2021-11-11 13:59:08 +00:00
|
|
|
func (t *templateFuncProvider) GetFuncMap(m *irc.Message, r *plugins.Rule, fields *plugins.FieldCollection) template.FuncMap {
|
2021-04-21 20:43:33 +00:00
|
|
|
t.lock.RLock()
|
|
|
|
defer t.lock.RUnlock()
|
|
|
|
|
|
|
|
out := make(template.FuncMap)
|
|
|
|
|
2022-10-02 13:13:49 +00:00
|
|
|
for n, fn := range sprig.TxtFuncMap() {
|
|
|
|
if str.StringInSlice(n, sprigBlacklist) {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
if out[n] != nil {
|
|
|
|
panic(fmt.Sprintf("duplicate function: %s (add in sprig)", n))
|
|
|
|
}
|
|
|
|
out[n] = fn
|
|
|
|
}
|
|
|
|
|
2021-04-21 20:43:33 +00:00
|
|
|
for n, fg := range t.funcs {
|
2022-10-02 13:13:49 +00:00
|
|
|
if out[n] != nil {
|
|
|
|
panic(fmt.Sprintf("duplicate function: %s (add in registration)", n))
|
|
|
|
}
|
2021-04-21 20:43:33 +00:00
|
|
|
out[n] = fg(m, r, fields)
|
|
|
|
}
|
|
|
|
|
|
|
|
return out
|
|
|
|
}
|
|
|
|
|
2021-12-06 16:25:19 +00:00
|
|
|
func (t *templateFuncProvider) GetFuncNames() []string {
|
|
|
|
var out []string
|
|
|
|
|
2022-10-23 00:30:14 +00:00
|
|
|
for n := range t.GetFuncMap(nil, nil, nil) {
|
2021-12-06 16:25:19 +00:00
|
|
|
out = append(out, n)
|
|
|
|
}
|
|
|
|
|
|
|
|
return out
|
|
|
|
}
|
|
|
|
|
2021-08-19 14:40:34 +00:00
|
|
|
func (t *templateFuncProvider) Register(name string, fg plugins.TemplateFuncGetter) {
|
2021-04-21 20:43:33 +00:00
|
|
|
t.lock.Lock()
|
|
|
|
defer t.lock.Unlock()
|
|
|
|
|
2021-08-19 14:40:34 +00:00
|
|
|
if _, ok := t.funcs[name]; ok {
|
2021-08-19 15:27:47 +00:00
|
|
|
log.Fatalf("Duplicate registration of %q template function", name) //nolint:gocritic // Yeah, the unlock will not run but the process will end
|
2021-08-19 14:40:34 +00:00
|
|
|
}
|
2021-04-21 20:43:33 +00:00
|
|
|
|
2021-08-19 14:40:34 +00:00
|
|
|
t.funcs[name] = fg
|
2021-04-21 20:43:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func init() {
|
|
|
|
// Register Korvike functions
|
|
|
|
for n, f := range korvike.GetFunctionMap() {
|
2022-10-02 13:13:49 +00:00
|
|
|
if str.StringInSlice(n, korvikeBlacklist) {
|
|
|
|
continue
|
|
|
|
}
|
2021-08-19 14:40:34 +00:00
|
|
|
tplFuncs.Register(n, plugins.GenericTemplateFunctionGetter(f))
|
2021-04-21 20:43:33 +00:00
|
|
|
}
|
|
|
|
|
2021-10-13 12:30:45 +00:00
|
|
|
tplFuncs.Register("formatDuration", plugins.GenericTemplateFunctionGetter(func(dur time.Duration, units ...string) string {
|
|
|
|
dLeft := dur
|
|
|
|
|
|
|
|
if len(units) == 0 {
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
|
|
|
|
var parts []string
|
|
|
|
for idx, div := range []time.Duration{time.Hour, time.Minute, time.Second} {
|
|
|
|
part := dLeft / div
|
|
|
|
dLeft -= part * div
|
|
|
|
|
|
|
|
if len(units) <= idx || units[idx] == "" {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
parts = append(parts, fmt.Sprintf("%d %s", part, units[idx]))
|
|
|
|
}
|
|
|
|
|
|
|
|
return strings.Join(parts, ", ")
|
|
|
|
}))
|
2021-04-21 20:43:33 +00:00
|
|
|
}
|