diff --git a/config.go b/config.go index d29ba40..e834dff 100644 --- a/config.go +++ b/config.go @@ -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() diff --git a/main.go b/main.go index 6b0f37b..d861748 100644 --- a/main.go +++ b/main.go @@ -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", }) diff --git a/types.go b/types.go new file mode 100644 index 0000000..b61fbda --- /dev/null +++ b/types.go @@ -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] +}