Improve config handling and move types to types.go

This commit is contained in:
Elara 2023-08-19 06:56:42 -07:00
parent bc91986e6c
commit 53cc18e382
3 changed files with 57 additions and 50 deletions

View File

@ -12,7 +12,7 @@ import (
"go.elara.ws/pcre"
)
type Config struct {
type ConfigFile struct {
Lemmy struct {
InstanceURL string `toml:"instanceURL"`
Account struct {
@ -28,16 +28,16 @@ type Reply struct {
Msg string `toml:"msg"`
}
var (
cfg = Config{}
compiledRegexes = map[string]*pcre.Regexp{}
compiledTmpls = map[string]*template.Template{}
)
type Config struct {
ConfigFile *ConfigFile
Regexes map[string]*pcre.Regexp
Tmpls map[string]*template.Template
}
func loadConfig(path string) error {
func loadConfig(path string) (Config, error) {
fi, err := os.Stat(path)
if err != nil {
return err
return Config{}, err
}
if fi.Mode().Perm() != 0o600 {
@ -46,24 +46,29 @@ func loadConfig(path string) error {
fl, err := os.Open(path)
if err != nil {
return err
return Config{}, err
}
err = toml.NewDecoder(fl).Decode(&cfg)
cfgFile := &ConfigFile{}
err = toml.NewDecoder(fl).Decode(cfgFile)
if err != nil {
return err
return Config{}, err
}
err = compileReplies(cfg.Replies)
compiledRegexes, compiledTmpls, err := compileReplies(cfgFile.Replies)
if err != nil {
return err
return Config{}, err
}
validateConfig()
return nil
cfg := Config{cfgFile, compiledRegexes, compiledTmpls}
validateConfig(cfg)
return cfg, nil
}
func compileReplies(replies []Reply) error {
func compileReplies(replies []Reply) (map[string]*pcre.Regexp, map[string]*template.Template, error) {
compiledRegexes := map[string]*pcre.Regexp{}
compiledTmpls := map[string]*template.Template{}
for i, reply := range replies {
if _, ok := compiledRegexes[reply.Regex]; ok {
continue
@ -71,7 +76,7 @@ func compileReplies(replies []Reply) error {
re, err := pcre.Compile(reply.Regex)
if err != nil {
return err
return nil, nil, err
}
compiledRegexes[reply.Regex] = re
@ -80,21 +85,22 @@ func compileReplies(replies []Reply) error {
Funcs(sprig.TxtFuncMap()).
Parse(reply.Msg)
if err != nil {
return err
return nil, nil, err
}
compiledTmpls[reply.Regex] = tmpl
}
return nil
return compiledRegexes, compiledTmpls, nil
}
func validateConfig() {
_, err := url.Parse(cfg.Lemmy.InstanceURL)
func validateConfig(cfg Config) {
_, err := url.Parse(cfg.ConfigFile.Lemmy.InstanceURL)
if err != nil {
log.Fatal("Lemmy instance URL is not valid").Err(err).Send()
}
for i, reply := range cfg.Replies {
re := compiledRegexes[reply.Regex]
for i, reply := range cfg.ConfigFile.Replies {
re := cfg.Regexes[reply.Regex]
if re.MatchString(reply.Msg) {
log.Fatal("Regular expression matches message. This may create an infinite loop. Refusing to start.").Int("reply-index", i).Send()

39
main.go
View File

@ -19,21 +19,6 @@ import (
_ "modernc.org/sqlite"
)
type Submatches []string
func (sm Submatches) Item(i int) string {
return sm[i]
}
type TmplContext struct {
Matches []Submatches
Type string
}
func (tc TmplContext) Match(i, j int) string {
return tc.Matches[i][j]
}
//go:embed sql/schema.sql
var schema string
@ -61,19 +46,19 @@ func main() {
ctx, cancel := signal.NotifyContext(ctx, syscall.SIGINT, syscall.SIGTERM)
defer cancel()
err := loadConfig(*configPath)
cfg, err := loadConfig(*configPath)
if err != nil {
log.Fatal("Error loading config file").Err(err).Send()
}
c, err := lemmy.New(cfg.Lemmy.InstanceURL)
c, err := lemmy.New(cfg.ConfigFile.Lemmy.InstanceURL)
if err != nil {
log.Fatal("Error creating new Lemmy API client").Err(err).Send()
}
err = c.ClientLogin(ctx, types.Login{
UsernameOrEmail: cfg.Lemmy.Account.UserOrEmail,
Password: cfg.Lemmy.Account.Password,
UsernameOrEmail: cfg.ConfigFile.Lemmy.Account.UserOrEmail,
Password: cfg.ConfigFile.Lemmy.Account.Password,
})
if err != nil {
log.Fatal("Error logging in to Lemmy instance").Err(err).Send()
@ -87,10 +72,10 @@ func main() {
go commentReplyWorker(ctx, c, replyCh)
}
commentWorker(ctx, c, replyCh)
commentWorker(ctx, c, cfg, replyCh)
}
func commentWorker(ctx context.Context, c *lemmy.Client, replyCh chan<- replyJob) {
func commentWorker(ctx context.Context, c *lemmy.Client, cfg Config, replyCh chan<- replyJob) {
db, err := sql.Open("sqlite", "replied.db")
if err != nil {
log.Fatal("Error opening reply database").Err(err).Send()
@ -128,8 +113,8 @@ func commentWorker(ctx context.Context, c *lemmy.Client, replyCh chan<- replyJob
continue
}
for i, reply := range cfg.Replies {
re := compiledRegexes[reply.Regex]
for i, reply := range cfg.ConfigFile.Replies {
re := cfg.Regexes[reply.Regex]
if !re.MatchString(c.Comment.Content) {
continue
}
@ -145,7 +130,7 @@ func commentWorker(ctx context.Context, c *lemmy.Client, replyCh chan<- replyJob
}
matches := re.FindAllStringSubmatch(c.Comment.Content, -1)
job.Content, err = executeTmpl(compiledTmpls[reply.Regex], TmplContext{
job.Content, err = executeTmpl(cfg.Tmpls[reply.Regex], TmplContext{
Matches: toSubmatches(matches),
Type: "comment",
})
@ -197,8 +182,8 @@ func commentWorker(ctx context.Context, c *lemmy.Client, replyCh chan<- replyJob
}
body := p.Post.URL.ValueOr("") + "\n\n" + p.Post.Body.ValueOr("")
for i, reply := range cfg.Replies {
re := compiledRegexes[reply.Regex]
for i, reply := range cfg.ConfigFile.Replies {
re := cfg.Regexes[reply.Regex]
if !re.MatchString(body) {
continue
}
@ -211,7 +196,7 @@ func commentWorker(ctx context.Context, c *lemmy.Client, replyCh chan<- replyJob
job := replyJob{PostID: p.Post.ID}
matches := re.FindAllStringSubmatch(body, -1)
job.Content, err = executeTmpl(compiledTmpls[reply.Regex], TmplContext{
job.Content, err = executeTmpl(cfg.Tmpls[reply.Regex], TmplContext{
Matches: toSubmatches(matches),
Type: "post",
})

16
types.go Normal file
View File

@ -0,0 +1,16 @@
package main
type Submatches []string
func (sm Submatches) Item(i int) string {
return sm[i]
}
type TmplContext struct {
Matches []Submatches
Type string
}
func (tc TmplContext) Match(i, j int) string {
return tc.Matches[i][j]
}