aboutsummaryrefslogtreecommitdiffstats
path: root/worker/jmap/search.go
diff options
context:
space:
mode:
Diffstat (limited to 'worker/jmap/search.go')
-rw-r--r--worker/jmap/search.go137
1 files changed, 86 insertions, 51 deletions
diff --git a/worker/jmap/search.go b/worker/jmap/search.go
index 17b5ca11..0101ce9b 100644
--- a/worker/jmap/search.go
+++ b/worker/jmap/search.go
@@ -1,63 +1,98 @@
package jmap
import (
- "strings"
-
- "git.sr.ht/~rjarry/aerc/lib/parse"
- "git.sr.ht/~rjarry/aerc/log"
+ "git.sr.ht/~rjarry/aerc/worker/types"
+ "git.sr.ht/~rockorager/go-jmap"
"git.sr.ht/~rockorager/go-jmap/mail/email"
- "git.sr.ht/~sircmpwn/getopt"
+ "git.sr.ht/~rockorager/go-jmap/mail/mailbox"
)
-func parseSearch(args []string) (*email.FilterCondition, error) {
- f := new(email.FilterCondition)
- if len(args) == 0 {
- return f, nil
- }
-
- opts, optind, err := getopt.Getopts(args, "rubax:X:t:H:f:c:d:")
- if err != nil {
- return nil, err
- }
- body := false
- text := false
- for _, opt := range opts {
- switch opt.Option {
- case 'r':
- f.HasKeyword = "$seen"
- case 'u':
- f.NotKeyword = "$seen"
- case 'f':
- f.From = opt.Value
- case 't':
- f.To = opt.Value
- case 'c':
- f.Cc = opt.Value
- case 'b':
- body = true
- case 'a':
- text = true
- case 'd':
- start, end, err := parse.DateRange(opt.Value)
- if err != nil {
- log.Errorf("failed to parse start date: %v", err)
- continue
- }
- if !start.IsZero() {
- f.After = &start
- }
- if !end.IsZero() {
- f.Before = &end
- }
+func (w *JMAPWorker) translateSearch(
+ mbox jmap.ID, criteria *types.SearchCriteria,
+) email.Filter {
+ cond := new(email.FilterCondition)
+
+ if mbox == "" {
+ // all mail virtual folder: display all but trash and spam
+ var mboxes []jmap.ID
+ if id, ok := w.roles[mailbox.RoleJunk]; ok {
+ mboxes = append(mboxes, id)
+ }
+ if id, ok := w.roles[mailbox.RoleTrash]; ok {
+ mboxes = append(mboxes, id)
}
+ cond.InMailboxOtherThan = mboxes
+ } else {
+ cond.InMailbox = mbox
+ }
+ if criteria == nil {
+ return cond
+ }
+
+ // dates
+ if !criteria.StartDate.IsZero() {
+ cond.After = &criteria.StartDate
}
+ if !criteria.EndDate.IsZero() {
+ cond.Before = &criteria.EndDate
+ }
+
+ // general search terms
switch {
- case text:
- f.Text = strings.Join(args[optind:], " ")
- case body:
- f.Body = strings.Join(args[optind:], " ")
+ case criteria.SearchAll:
+ cond.Text = criteria.Terms
+ case criteria.SearchBody:
+ cond.Body = criteria.Terms
default:
- f.Subject = strings.Join(args[optind:], " ")
+ cond.Subject = criteria.Terms
+ }
+
+ filter := &email.FilterOperator{Operator: jmap.OperatorAND}
+ filter.Conditions = append(filter.Conditions, cond)
+
+ // keywords/flags
+ for kw := range flagsToKeywords(criteria.WithFlags) {
+ filter.Conditions = append(filter.Conditions,
+ &email.FilterCondition{HasKeyword: kw})
+ }
+ for kw := range flagsToKeywords(criteria.WithoutFlags) {
+ filter.Conditions = append(filter.Conditions,
+ &email.FilterCondition{NotKeyword: kw})
}
- return f, nil
+
+ // recipients
+ addrs := &email.FilterOperator{
+ Operator: jmap.OperatorOR,
+ }
+ for _, from := range criteria.From {
+ addrs.Conditions = append(addrs.Conditions,
+ &email.FilterCondition{From: from})
+ }
+ for _, to := range criteria.To {
+ addrs.Conditions = append(addrs.Conditions,
+ &email.FilterCondition{To: to})
+ }
+ for _, cc := range criteria.Cc {
+ addrs.Conditions = append(addrs.Conditions,
+ &email.FilterCondition{Cc: cc})
+ }
+ if len(addrs.Conditions) > 0 {
+ filter.Conditions = append(filter.Conditions, addrs)
+ }
+
+ // specific headers
+ headers := &email.FilterOperator{
+ Operator: jmap.OperatorAND,
+ }
+ for h, values := range criteria.Headers {
+ for _, v := range values {
+ headers.Conditions = append(headers.Conditions,
+ &email.FilterCondition{Header: []string{h, v}})
+ }
+ }
+ if len(headers.Conditions) > 0 {
+ filter.Conditions = append(filter.Conditions, headers)
+ }
+
+ return filter
}