From ad5b753f50d2254c537ae17671ff7d4781a24ba6 Mon Sep 17 00:00:00 2001 From: Elara Musayelyan Date: Mon, 9 Jan 2023 16:10:05 -0800 Subject: [PATCH] Switch from variable expansion to templates --- config.go | 20 +++++++++++++++++--- go.mod | 10 +++++++++- go.sum | 16 ++++++++++++++++ main.go | 38 +++++++++++--------------------------- tmpl.go | 24 ++++++++++++++++++++++++ 5 files changed, 77 insertions(+), 31 deletions(-) create mode 100644 tmpl.go diff --git a/config.go b/config.go index d9c24bb..c1def07 100644 --- a/config.go +++ b/config.go @@ -3,7 +3,10 @@ package main import ( "net/url" "os" + "strconv" + "text/template" + "github.com/Masterminds/sprig" "github.com/pelletier/go-toml/v2" "go.arsenm.dev/logger/log" "go.arsenm.dev/pcre" @@ -28,6 +31,7 @@ type Reply struct { var ( cfg = Config{} compiledRegexes = map[string]*pcre.Regexp{} + compiledTmpls = map[string]*template.Template{} ) func loadConfig(path string) error { @@ -50,7 +54,7 @@ func loadConfig(path string) error { return err } - err = compileRegexes(cfg.Replies) + err = compileReplies(cfg.Replies) if err != nil { return err } @@ -59,8 +63,8 @@ func loadConfig(path string) error { return nil } -func compileRegexes(replies []Reply) error { - for _, reply := range replies { +func compileReplies(replies []Reply) error { + for i, reply := range replies { if _, ok := compiledRegexes[reply.Regex]; ok { continue } @@ -70,6 +74,16 @@ func compileRegexes(replies []Reply) error { return err } compiledRegexes[reply.Regex] = re + + tmpl, err := template. + New(strconv.Itoa(i)). + Funcs(tmplFuncs). + Funcs(sprig.TxtFuncMap()). + Parse(reply.Msg) + if err != nil { + return err + } + compiledTmpls[reply.Regex] = tmpl } return nil } diff --git a/go.mod b/go.mod index 1e8e128..943d566 100644 --- a/go.mod +++ b/go.mod @@ -2,9 +2,10 @@ module go.arsenm.dev/lemmy-reply-bot go 1.19 -replace go.arsenm.dev/go-lemmy => /home/arsen/Code/go-lemmy +//replace go.arsenm.dev/go-lemmy => /home/arsen/Code/go-lemmy require ( + github.com/Masterminds/sprig v2.22.0+incompatible github.com/pelletier/go-toml/v2 v2.0.6 github.com/spf13/pflag v1.0.5 github.com/vmihailenco/msgpack/v5 v5.3.5 @@ -14,15 +15,22 @@ require ( ) require ( + github.com/Masterminds/goutils v1.1.1 // indirect + github.com/Masterminds/semver v1.5.0 // indirect github.com/cenkalti/backoff/v4 v4.2.0 // indirect github.com/google/go-querystring v1.1.0 // indirect github.com/google/uuid v1.3.0 // indirect github.com/gookit/color v1.5.1 // indirect github.com/gorilla/websocket v1.4.2 // indirect + github.com/huandu/xstrings v1.4.0 // indirect + github.com/imdario/mergo v0.3.13 // indirect github.com/mattn/go-isatty v0.0.14 // indirect + github.com/mitchellh/copystructure v1.2.0 // indirect + github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 // indirect + golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 // indirect golang.org/x/sys v0.1.0 // indirect modernc.org/libc v1.16.8 // indirect modernc.org/mathutil v1.4.1 // indirect diff --git a/go.sum b/go.sum index 33a427e..357b868 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,9 @@ +github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= +github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= +github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= +github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= +github.com/Masterminds/sprig v2.22.0+incompatible h1:z4yfnGrZ7netVz+0EDJ0Wi+5VZCSYp4Z0m2dk6cEM60= +github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= github.com/cenkalti/backoff/v4 v4.2.0 h1:HN5dHm3WBOgndBH6E8V0q2jIYIR3s9yglV8k/+MN3u4= github.com/cenkalti/backoff/v4 v4.2.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -15,10 +21,18 @@ github.com/gookit/color v1.5.1 h1:Vjg2VEcdHpwq+oY63s/ksHrgJYCTo0bwWvmmYWdE9fQ= github.com/gookit/color v1.5.1/go.mod h1:wZFzea4X8qN6vHOSP2apMb4/+w/orMznEzYsIHPaqKM= github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/huandu/xstrings v1.4.0 h1:D17IlohoQq4UcpqD7fDk80P7l+lwAmlFaBHgOipl2FU= +github.com/huandu/xstrings v1.4.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= +github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk= +github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= +github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= +github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= +github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/pelletier/go-toml/v2 v2.0.6 h1:nrzqCb7j9cDFj2coyLNLaZuJTLjWjlaz6nvTvIwycIU= github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= @@ -49,6 +63,7 @@ go.arsenm.dev/pcre v0.0.0-20220530205550-74594f6c8b0e h1:4XwLmFDvAKt7ZvS3E3hD2R+ go.arsenm.dev/pcre v0.0.0-20220530205550-74594f6c8b0e/go.mod h1:c/E0D60A6rRLoDLh6mLUdFV9gxyth+CnXnqGHos2CAQ= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -76,6 +91,7 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= lukechampine.com/uint128 v1.1.1/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= diff --git a/main.go b/main.go index b5b78e1..45f5cd1 100644 --- a/main.go +++ b/main.go @@ -2,12 +2,11 @@ package main import ( "context" - "fmt" "os" "os/signal" - "strconv" "strings" "syscall" + "text/template" "github.com/spf13/pflag" "github.com/vmihailenco/msgpack/v5" @@ -104,22 +103,12 @@ func commentWorker(ctx context.Context, c *lemmy.WSClient, replyCh chan<- replyJ PostID: cr.CommentView.Comment.PostID, } - matches := re.FindStringSubmatch(cr.CommentView.Comment.Content) - job.Content = expandStr(reply.Msg, func(s string) string { - i, err := strconv.Atoi(s) - if err != nil { - log.Debug("Message variable is not an integer, returning empty string").Str("var", s).Send() - return "" - } - - if i+1 > len(matches) { - log.Debug("Message variable exceeds match length").Int("length", len(matches)).Int("var", i).Send() - return "" - } - - log.Debug("Message variable found, returning").Int("var", i).Str("found", matches[i]).Send() - return matches[i] - }) + matches := re.FindAllStringSubmatch(cr.CommentView.Comment.Content, -1) + job.Content, err = executeTmpl(compiledTmpls[reply.Regex], matches) + if err != nil { + log.Warn("Error while executing template").Err(err).Send() + continue + } replyCh <- job @@ -127,7 +116,6 @@ func commentWorker(ctx context.Context, c *lemmy.WSClient, replyCh chan<- replyJ } } case err := <-c.Errors(): - fmt.Printf("%T\n", err) log.Warn("Lemmy client error").Err(err).Send() case <-ctx.Done(): repliedStore, err := os.Create("replied.bin") @@ -176,14 +164,10 @@ func commentReplyWorker(ctx context.Context, c *lemmy.WSClient, ch <-chan replyJ } } -func expandStr(s string, mapping func(string) string) string { - s = strings.ReplaceAll(s, "$$", "${_escaped_dollar_symbol}") - return os.Expand(s, func(s string) string { - if s == "_escaped_dollar_symbol" { - return "$" - } - return mapping(s) - }) +func executeTmpl(tmpl *template.Template, matches [][]string) (string, error) { + sb := &strings.Builder{} + err := tmpl.Execute(sb, matches) + return sb.String(), err } func joinAll(c *lemmy.WSClient) { diff --git a/tmpl.go b/tmpl.go new file mode 100644 index 0000000..3151f24 --- /dev/null +++ b/tmpl.go @@ -0,0 +1,24 @@ +package main + +import "text/template" + +var tmplFuncs = template.FuncMap{ + "match": func(matches [][]string, i int, j int) string { + if len(matches) <= i { + return "" + } + + if len(matches[i]) <= j { + return "" + } + + return matches[i][j] + }, + "item": func(items []string, i int) string { + if len(items) <= i { + return "" + } + + return items[i] + }, +}