From 2216b2a929f1d3d68c35beca22586979a1112555 Mon Sep 17 00:00:00 2001 From: Carlo Strub Date: Mon, 5 Jun 2017 16:20:03 +0000 Subject: [PATCH] Implement automatic learning after predefined duration --- mail.go | 22 ++++++++++----- sisyphus/sisyphus.go | 64 +++++++++++++++++++++++++++++++++----------- 2 files changed, 64 insertions(+), 22 deletions(-) diff --git a/mail.go b/mail.go index 844dc92..6cc60bd 100644 --- a/mail.go +++ b/mail.go @@ -250,18 +250,12 @@ func (m *Mail) cleanWordlist() (w []string, err error) { return w, err } -// LoadMails creates missing directories and then loads all mails from a given -// slice of Maildirs +// LoadMails loads all mails from a given slice of Maildirs func LoadMails(d []Maildir) (mails map[Maildir][]*Mail, err error) { mails = make(map[Maildir][]*Mail) // create missing directories and write index for _, val := range d { - err := val.CreateDirs() - if err != nil { - return mails, err - } - var m []*Mail m, err = val.Index() if err != nil { @@ -273,3 +267,17 @@ func LoadMails(d []Maildir) (mails map[Maildir][]*Mail, err error) { return mails, nil } + +// LoadMaildirs creates Maildirs and required directories, if missing +func LoadMaildirs(d []Maildir) (err error) { + + // create missing directories and write index + for _, val := range d { + err := val.CreateDirs() + if err != nil { + return err + } + } + + return nil +} diff --git a/sisyphus/sisyphus.go b/sisyphus/sisyphus.go index fc70b0e..dc7271a 100644 --- a/sisyphus/sisyphus.go +++ b/sisyphus/sisyphus.go @@ -6,7 +6,9 @@ import ( "os/signal" "strings" "syscall" + "time" + "github.com/boltdb/bolt" "github.com/fsnotify/fsnotify" log "github.com/sirupsen/logrus" @@ -45,6 +47,9 @@ func main() { var pidfile *string pidfile = new(string) + var learnafter *string + learnafter = new(string) + app.Flags = []cli.Flag{ cli.StringSliceFlag{ @@ -60,6 +65,13 @@ func main() { Usage: "Location of PID file", Destination: pidfile, }, + cli.StringFlag{ + Name: "learn", + Value: "12h", + EnvVar: "SISYPHUS_DURATION", + Usage: "Time interval between to learn cycles", + Destination: learnafter, + }, } app.Commands = []cli.Command{ @@ -122,12 +134,12 @@ func main() { maildirs = append(maildirs, sisyphus.Maildir(val)) } - // Load all mails - mails, err := sisyphus.LoadMails(maildirs) + // Create missing Maildirs + err := sisyphus.LoadMaildirs(maildirs) if err != nil { log.WithFields(log.Fields{ "err": err, - }).Fatal("Cannot load mails") + }).Fatal("Cannot load maildirs") } // Open all databases @@ -139,21 +151,18 @@ func main() { } defer sisyphus.CloseDatabases(dbs) - // Learn at startup - for _, d := range maildirs { - db := dbs[d] - m := mails[d] - for _, val := range m { - err := val.Learn(db, d) + // Learn at startup and regular intervals + go func() { + for { + duration, err := time.ParseDuration(*learnafter) if err != nil { - log.WithFields(log.Fields{ - "err": err, - "mail": val.Key, - }).Warning("Cannot learn mail") + log.Fatal("Cannot parse duration for learning intervals.") } + + learn(maildirs, dbs) + time.Sleep(duration) } - } - log.Info("All mails learned") + }() // Classify whenever a mail arrives in "new" watcher, err := fsnotify.NewWatcher() @@ -253,3 +262,28 @@ func main() { app.Run(os.Args) } + +func learn(maildirs []sisyphus.Maildir, dbs map[sisyphus.Maildir]*bolt.DB) { + mails, err := sisyphus.LoadMails(maildirs) + if err != nil { + log.WithFields(log.Fields{ + "err": err, + }).Fatal("Cannot load mails") + } + for _, d := range maildirs { + db := dbs[d] + m := mails[d] + for _, val := range m { + err := val.Learn(db, d) + if err != nil { + log.WithFields(log.Fields{ + "err": err, + "mail": val.Key, + }).Warning("Cannot learn mail") + } + } + } + log.Info("All mails learned") + + return +}