diff options
Diffstat (limited to 'worker/jmap/search.go')
-rw-r--r-- | worker/jmap/search.go | 137 |
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 } |