aboutsummaryrefslogtreecommitdiffstats
path: root/worker
diff options
context:
space:
mode:
Diffstat (limited to 'worker')
-rw-r--r--worker/imap/checkmail.go40
-rw-r--r--worker/imap/worker.go2
-rw-r--r--worker/maildir/worker.go53
-rw-r--r--worker/notmuch/worker.go26
-rw-r--r--worker/types/messages.go10
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 {