diff --git a/config.go b/config.go index 536660b..09ad0d7 100644 --- a/config.go +++ b/config.go @@ -1,7 +1,10 @@ package main import ( + "fmt" + "io" "os" + "path" "time" "github.com/go-irc/irc" @@ -15,7 +18,10 @@ type configFile struct { Channels []string `yaml:"channels"` PermitAllowModerator bool `yaml:"permit_allow_moderator"` PermitTimeout time.Duration `yaml:"permit_timeout"` + RawLog string `yaml:"raw_log"` Rules []*rule `yaml:"rules"` + + rawLogWriter io.WriteCloser } func newConfigFile() configFile { @@ -82,10 +88,40 @@ func loadConfig(filename string) error { configLock.Lock() defer configLock.Unlock() + switch { + case config != nil && config.RawLog == tmpConfig.RawLog: + tmpConfig.rawLogWriter = config.rawLogWriter + + case tmpConfig.RawLog == "": + if err = config.CloseRawMessageWriter(); err != nil { + return errors.Wrap(err, "closing old raw log writer") + } + + tmpConfig.rawLogWriter = writeNoOpCloser{io.Discard} + + default: + if err = config.CloseRawMessageWriter(); err != nil { + return errors.Wrap(err, "closing old raw log writer") + } + if err = os.MkdirAll(path.Dir(tmpConfig.RawLog), 0o755); err != nil { + return errors.Wrap(err, "creating directories for raw log") + } + if tmpConfig.rawLogWriter, err = os.OpenFile(tmpConfig.RawLog, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0o644); err != nil { + return errors.Wrap(err, "opening raw log for appending") + } + } + config = &tmpConfig return nil } +func (c *configFile) CloseRawMessageWriter() error { + if c == nil || c.rawLogWriter == nil { + return nil + } + return c.rawLogWriter.Close() +} + func (c configFile) GetMatchingRules(m *irc.Message, event *string) []*rule { configLock.RLock() defer configLock.RUnlock() @@ -100,3 +136,8 @@ func (c configFile) GetMatchingRules(m *irc.Message, event *string) []*rule { return out } + +func (c configFile) LogRawMessage(m *irc.Message) error { + _, err := fmt.Fprintln(c.rawLogWriter, m.String()) + return errors.Wrap(err, "writing raw log message") +} diff --git a/irc.go b/irc.go index 0e69eca..696f67b 100644 --- a/irc.go +++ b/irc.go @@ -70,6 +70,15 @@ func (i ircHandler) ExecuteJoins(channels []string) { } func (i ircHandler) Handle(c *irc.Client, m *irc.Message) { + go func(m *irc.Message) { + configLock.RLock() + defer configLock.RUnlock() + + if err := config.LogRawMessage(m); err != nil { + log.WithError(err).Error("Unable to log raw message") + } + }(m) + switch m.Command { case "001": // 001 is a welcome event, so we join channels there diff --git a/main.go b/main.go index 709e6cd..276d538 100644 --- a/main.go +++ b/main.go @@ -75,6 +75,7 @@ func main() { if err = loadConfig(cfg.Config); err != nil { log.WithError(err).Fatal("Initial config load failed") } + defer func() { config.CloseRawMessageWriter() }() fswatch, err := fsnotify.NewWatcher() if err != nil { diff --git a/wrNoOpCloser.go b/wrNoOpCloser.go new file mode 100644 index 0000000..5d65415 --- /dev/null +++ b/wrNoOpCloser.go @@ -0,0 +1,7 @@ +package main + +import "io" + +type writeNoOpCloser struct{ io.Writer } + +func (writeNoOpCloser) Close() error { return nil }