diff options
Diffstat (limited to 'worker')
-rw-r--r-- | worker/imap/checkmail.go | 40 | ||||
-rw-r--r-- | worker/imap/worker.go | 2 | ||||
-rw-r--r-- | worker/maildir/worker.go | 53 | ||||
-rw-r--r-- | worker/notmuch/worker.go | 26 | ||||
-rw-r--r-- | worker/types/messages.go | 10 |
5 files changed, 119 insertions, 12 deletions
diff --git a/worker/imap/checkmail.go b/worker/imap/checkmail.go new file mode 100644 index 00000000..d9dcfd33 --- /dev/null +++ b/worker/imap/checkmail.go @@ -0,0 +1,40 @@ +package imap + +import ( + "git.sr.ht/~rjarry/aerc/models" + "git.sr.ht/~rjarry/aerc/worker/types" + "github.com/emersion/go-imap" +) + +func (w *IMAPWorker) handleCheckMailMessage(msg *types.CheckMail) { + items := []imap.StatusItem{ + imap.StatusMessages, + imap.StatusRecent, + imap.StatusUnseen, + } + for _, dir := range msg.Directories { + w.worker.Logger.Printf("Getting status of directory %s", dir) + status, err := w.client.Status(dir, items) + if err != nil { + w.worker.PostMessage(&types.Error{ + Message: types.RespondTo(msg), + Error: err, + }, nil) + } else { + w.worker.PostMessage(&types.DirectoryInfo{ + Info: &models.DirectoryInfo{ + Flags: status.Flags, + Name: status.Name, + ReadOnly: status.ReadOnly, + AccurateCounts: true, + + Exists: int(status.Messages), + Recent: int(status.Recent), + Unseen: int(status.Unseen), + }, + SkipSort: true, + }, nil) + } + } + w.worker.PostMessage(&types.Done{Message: types.RespondTo(msg)}, nil) +} diff --git a/worker/imap/worker.go b/worker/imap/worker.go index eabaae02..da0716e1 100644 --- a/worker/imap/worker.go +++ b/worker/imap/worker.go @@ -190,6 +190,8 @@ func (w *IMAPWorker) handleMessage(msg types.WorkerMessage) error { w.handleAppendMessage(msg) case *types.SearchDirectory: w.handleSearchDirectory(msg) + case *types.CheckMail: + w.handleCheckMailMessage(msg) default: reterr = errUnsupported } diff --git a/worker/maildir/worker.go b/worker/maildir/worker.go index 4a2a19b8..d3de8447 100644 --- a/worker/maildir/worker.go +++ b/worker/maildir/worker.go @@ -2,12 +2,14 @@ package maildir import ( "bytes" + "context" "errors" "fmt" "io" "io/ioutil" "net/url" "os" + "os/exec" "path/filepath" "sort" "strings" @@ -60,17 +62,25 @@ func (w *Worker) Run() { func (w *Worker) handleAction(action types.WorkerMessage) { msg := w.worker.ProcessAction(action) - if err := w.handleMessage(msg); err == errUnsupported { - w.worker.PostMessage(&types.Unsupported{ - Message: types.RespondTo(msg), - }, nil) - } else if err != nil { - w.worker.PostMessage(&types.Error{ - Message: types.RespondTo(msg), - Error: err, - }, nil) - } else { - w.done(msg) + switch msg := msg.(type) { + // Explicitly handle all asynchronous actions. Async actions are + // responsible for posting their own Done message + case *types.CheckMail: + go w.handleCheckMail(msg) + default: + // Default handling, will be performed synchronously + if err := w.handleMessage(msg); err == errUnsupported { + w.worker.PostMessage(&types.Unsupported{ + Message: types.RespondTo(msg), + }, nil) + } else if err != nil { + w.worker.PostMessage(&types.Error{ + Message: types.RespondTo(msg), + Error: err, + }, nil) + } else { + w.done(msg) + } } } @@ -672,3 +682,24 @@ func (w *Worker) msgInfoFromUid(uid uint32) (*models.MessageInfo, error) { } return info, nil } + +func (w *Worker) handleCheckMail(msg *types.CheckMail) { + ctx, cancel := context.WithTimeout(context.Background(), msg.Timeout) + defer cancel() + cmd := exec.CommandContext(ctx, "sh", "-c", msg.Command) + ch := make(chan error) + go func() { + err := cmd.Run() + ch <- err + }() + select { + case <-ctx.Done(): + w.err(msg, fmt.Errorf("checkmail: timed out")) + case err := <-ch: + if err != nil { + w.err(msg, fmt.Errorf("checkmail: error running command: %v", err)) + } else { + w.done(msg) + } + } +} diff --git a/worker/notmuch/worker.go b/worker/notmuch/worker.go index 4091ea43..c1426f28 100644 --- a/worker/notmuch/worker.go +++ b/worker/notmuch/worker.go @@ -6,10 +6,12 @@ package notmuch import ( "bufio" "bytes" + "context" "fmt" "io/ioutil" "net/url" "os" + "os/exec" "path/filepath" "strings" "time" @@ -128,6 +130,9 @@ func (w *worker) handleMessage(msg types.WorkerMessage) error { return w.handleSearchDirectory(msg) case *types.ModifyLabels: return w.handleModifyLabels(msg) + case *types.CheckMail: + go w.handleCheckMail(msg) + return nil // not implemented, they are generally not used // in a notmuch based workflow @@ -616,3 +621,24 @@ func (w *worker) sort(uids []uint32, } return sortedUids, nil } + +func (w *worker) handleCheckMail(msg *types.CheckMail) { + ctx, cancel := context.WithTimeout(context.Background(), msg.Timeout) + defer cancel() + cmd := exec.CommandContext(ctx, "sh", "-c", msg.Command) + ch := make(chan error) + go func() { + err := cmd.Run() + ch <- err + }() + select { + case <-ctx.Done(): + w.err(msg, fmt.Errorf("checkmail: timed out")) + case err := <-ch: + if err != nil { + w.err(msg, fmt.Errorf("checkmail: error running command: %v", err)) + } else { + w.done(msg) + } + } +} diff --git a/worker/types/messages.go b/worker/types/messages.go index d8f1f568..5cd3768c 100644 --- a/worker/types/messages.go +++ b/worker/types/messages.go @@ -167,6 +167,13 @@ type AppendMessage struct { Length int } +type CheckMail struct { + Message + Directories []string + Command string + Timeout time.Duration +} + // Messages type Directory struct { @@ -176,7 +183,8 @@ type Directory struct { type DirectoryInfo struct { Message - Info *models.DirectoryInfo + Info *models.DirectoryInfo + SkipSort bool } type DirectoryContents struct { |