summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShivesh Mandalia <mail@shivesh.org>2021-10-23 18:37:06 +0100
committerShivesh Mandalia <mail@shivesh.org>2021-10-23 18:37:06 +0100
commit5c7d4873908f28dde33013d10543e4cf1417525b (patch)
tree50c381fd5ab776d2dbecfc8e590fd224e0f3c044
parent57292f268a961e559618d0b5007dbda4df33f00c (diff)
downloadaerc-5c7d4873908f28dde33013d10543e4cf1417525b.tar.gz
aerc-5c7d4873908f28dde33013d10543e4cf1417525b.zip
Implement interface for my custom IMAP flags
-rw-r--r--commands/msg/read.go25
-rw-r--r--doc/aerc-search.1.scd32
-rw-r--r--doc/aerc.1.scd16
-rw-r--r--lib/format/format.go35
-rw-r--r--lib/msgstore.go73
-rw-r--r--models/models.go10
-rw-r--r--worker/imap/flags.go257
-rw-r--r--worker/imap/imap.go18
-rw-r--r--worker/imap/search.go17
-rw-r--r--worker/imap/worker.go17
-rw-r--r--worker/types/messages.go49
11 files changed, 548 insertions, 1 deletions
diff --git a/commands/msg/read.go b/commands/msg/read.go
index 95becf7..2b7537b 100644
--- a/commands/msg/read.go
+++ b/commands/msg/read.go
@@ -96,6 +96,31 @@ func (FlagMsg) Execute(aerc *widgets.Aerc, args []string) error {
case "Flagged":
flag = models.FlaggedFlag
flagName = "flagged"
+ // NOTE(shivesh): my custom flags
+ case "important":
+ flag = models.ImportantFlag
+ flagName = "important"
+ case "list":
+ flag = models.ListFlag
+ flagName = "list"
+ case "food":
+ flag = models.FoodFlag
+ flagName = "food"
+ case "personal":
+ flag = models.PersonalFlag
+ flagName = "personal"
+ case "work":
+ flag = models.WorkFlag
+ flagName = "work"
+ case "physics":
+ flag = models.PhysicsFlag
+ flagName = "physics"
+ case "todo":
+ flag = models.TodoFlag
+ flagName = "todo"
+ case "later":
+ flag = models.LaterFlag
+ flagName = "later"
default:
return fmt.Errorf("Unknown / Prohibited flag \"%v\"", opt.Value)
}
diff --git a/doc/aerc-search.1.scd b/doc/aerc-search.1.scd
index b90a934..35b0026 100644
--- a/doc/aerc-search.1.scd
+++ b/doc/aerc-search.1.scd
@@ -30,6 +30,22 @@ aerc-search(1)
Flagged
Flagged messages
+ important
+
+ list
+
+ food
+
+ personal
+
+ work
+
+ physics
+
+ todo
+
+ later
+
*-b*: Search in the body of the messages
*-a*: Search in the entire text of the messages
@@ -70,6 +86,22 @@ aerc-search(1)
Flagged
Flagged messages
+ important
+
+ list
+
+ food
+
+ personal
+
+ work
+
+ physics
+
+ todo
+
+ later
+
*-b*: Search in the body of the messages
*-a*: Search in the entire text of the messages
diff --git a/doc/aerc.1.scd b/doc/aerc.1.scd
index f678a0a..03dcadd 100644
--- a/doc/aerc.1.scd
+++ b/doc/aerc.1.scd
@@ -181,6 +181,22 @@ message list, the message in the message viewer, etc).
Flagged
Message is flagged for urgent/special attention
+ important
+
+ list
+
+ food
+
+ personal
+
+ work
+
+ physics
+
+ todo
+
+ later
+
*unflag* [-t] <flag>
Operates exactly like *flag*, defaulting to unsetting (disabling) flags.
diff --git a/lib/format/format.go b/lib/format/format.go
index 30e8be7..96a19b9 100644
--- a/lib/format/format.go
+++ b/lib/format/format.go
@@ -297,6 +297,15 @@ func ParseMessageFormat(format string, timeFmt string, ctx Ctx) (string,
seen := false
recent := false
answered := false
+ // NOTE(shivesh): my custom flags
+ var importantFlag = ""
+ var listFlag = ""
+ var foodFlag = ""
+ var personalFlag = ""
+ var workFlag = ""
+ var physicsFlag = ""
+ var todoFlag = ""
+ var laterFlag = ""
for _, flag := range ctx.MsgInfo.Flags {
if flag == models.SeenFlag {
seen = true
@@ -305,6 +314,30 @@ func ParseMessageFormat(format string, timeFmt string, ctx Ctx) (string,
} else if flag == models.AnsweredFlag {
answered = true
}
+ if flag == models.ImportantFlag {
+ importantFlag = "I"
+ }
+ if flag == models.ListFlag {
+ listFlag = "l"
+ }
+ if flag == models.FoodFlag {
+ foodFlag = "F"
+ }
+ if flag == models.PersonalFlag {
+ personalFlag = "P"
+ }
+ if flag == models.WorkFlag {
+ workFlag = "W"
+ }
+ if flag == models.PhysicsFlag {
+ physicsFlag = "X"
+ }
+ if flag == models.TodoFlag {
+ todoFlag = "T"
+ }
+ if flag == models.LaterFlag {
+ laterFlag = "L"
+ }
if flag == models.DeletedFlag {
delFlag = "D"
// TODO: check if attachments
@@ -329,7 +362,7 @@ func ParseMessageFormat(format string, timeFmt string, ctx Ctx) (string,
markedFlag = "*"
}
retval = append(retval, '4', 's')
- args = append(args, readReplyFlag+delFlag+flaggedFlag+markedFlag)
+ args = append(args, readReplyFlag+delFlag+flaggedFlag+markedFlag+importantFlag+listFlag+foodFlag+personalFlag+workFlag+physicsFlag+todoFlag+laterFlag)
// Move the below cases to proper alphabetical positions once
// implemented
diff --git a/lib/msgstore.go b/lib/msgstore.go
index 7af9fd2..222c9fc 100644
--- a/lib/msgstore.go
+++ b/lib/msgstore.go
@@ -361,6 +361,79 @@ func (store *MessageStore) Answered(uids []uint32, answered bool,
}, cb)
}
+// NOTE(shivesh): my custom flags
+func (store *MessageStore) Important(uids []uint32, important bool,
+ cb func(msg types.WorkerMessage)) {
+
+ store.worker.PostAction(&types.ImportantMessages{
+ Important: important,
+ Uids: uids,
+ }, cb)
+}
+
+func (store *MessageStore) List(uids []uint32, list bool,
+ cb func(msg types.WorkerMessage)) {
+
+ store.worker.PostAction(&types.ListMessages{
+ List: list,
+ Uids: uids,
+ }, cb)
+}
+
+func (store *MessageStore) Food(uids []uint32, food bool,
+ cb func(msg types.WorkerMessage)) {
+
+ store.worker.PostAction(&types.FoodMessages{
+ Food: food,
+ Uids: uids,
+ }, cb)
+}
+
+func (store *MessageStore) Personal(uids []uint32, personal bool,
+ cb func(msg types.WorkerMessage)) {
+
+ store.worker.PostAction(&types.PersonalMessages{
+ Personal: personal,
+ Uids: uids,
+ }, cb)
+}
+
+func (store *MessageStore) Work(uids []uint32, work bool,
+ cb func(msg types.WorkerMessage)) {
+
+ store.worker.PostAction(&types.WorkMessages{
+ Work: work,
+ Uids: uids,
+ }, cb)
+}
+
+func (store *MessageStore) Physics(uids []uint32, physics bool,
+ cb func(msg types.WorkerMessage)) {
+
+ store.worker.PostAction(&types.PhysicsMessages{
+ Physics: physics,
+ Uids: uids,
+ }, cb)
+}
+
+func (store *MessageStore) Todo(uids []uint32, todo bool,
+ cb func(msg types.WorkerMessage)) {
+
+ store.worker.PostAction(&types.TodoMessages{
+ Todo: todo,
+ Uids: uids,
+ }, cb)
+}
+
+func (store *MessageStore) Later(uids []uint32, later bool,
+ cb func(msg types.WorkerMessage)) {
+
+ store.worker.PostAction(&types.LaterMessages{
+ Later: later,
+ Uids: uids,
+ }, cb)
+}
+
func (store *MessageStore) Uids() []uint32 {
if store.filter {
return store.results
diff --git a/models/models.go b/models/models.go
index 45f3b9d..dabb00b 100644
--- a/models/models.go
+++ b/models/models.go
@@ -27,6 +27,16 @@ const (
// FlaggedFlag marks a message with a user flag
FlaggedFlag
+
+ // NOTE(shivesh): my custom flags
+ ImportantFlag
+ ListFlag
+ FoodFlag
+ PersonalFlag
+ WorkFlag
+ PhysicsFlag
+ TodoFlag
+ LaterFlag
)
type Directory struct {
diff --git a/worker/imap/flags.go b/worker/imap/flags.go
index aef1019..d71e3bb 100644
--- a/worker/imap/flags.go
+++ b/worker/imap/flags.go
@@ -76,6 +76,263 @@ func (imapw *IMAPWorker) handleAnsweredMessages(msg *types.AnsweredMessages) {
})
}
+// NOTE(shivesh): my custom flags
+func (imapw *IMAPWorker) handleImportantMessages(msg *types.ImportantMessages) {
+ item := imap.FormatFlagsOp(imap.AddFlags, true)
+ flags := []interface{}{"important"}
+ if !msg.Important {
+ item = imap.FormatFlagsOp(imap.RemoveFlags, true)
+ flags = []interface{}{"important"}
+ }
+ uids := toSeqSet(msg.Uids)
+ emitErr := func(err error) {
+ imapw.worker.PostMessage(&types.Error{
+ Message: types.RespondTo(msg),
+ Error: err,
+ }, nil)
+ }
+ if err := imapw.client.UidStore(uids, item, flags, nil); err != nil {
+ emitErr(err)
+ return
+ }
+ imapw.worker.PostAction(&types.FetchMessageHeaders{
+ Uids: msg.Uids,
+ }, func(_msg types.WorkerMessage) {
+ switch m := _msg.(type) {
+ case *types.Error:
+ err := fmt.Errorf("handleImportantMessages: %v", m.Error)
+ imapw.worker.Logger.Printf("could not fetch headers: %s", err)
+ emitErr(err)
+ case *types.Done:
+ imapw.worker.PostMessage(&types.Done{types.RespondTo(msg)}, nil)
+ }
+ })
+}
+
+func (imapw *IMAPWorker) handleListMessages(msg *types.ListMessages) {
+ item := imap.FormatFlagsOp(imap.AddFlags, true)
+ flags := []interface{}{"list"}
+ if !msg.List {
+ item = imap.FormatFlagsOp(imap.RemoveFlags, true)
+ flags = []interface{}{"list"}
+ }
+ uids := toSeqSet(msg.Uids)
+ emitErr := func(err error) {
+ imapw.worker.PostMessage(&types.Error{
+ Message: types.RespondTo(msg),
+ Error: err,
+ }, nil)
+ }
+ if err := imapw.client.UidStore(uids, item, flags, nil); err != nil {
+ emitErr(err)
+ return
+ }
+ imapw.worker.PostAction(&types.FetchMessageHeaders{
+ Uids: msg.Uids,
+ }, func(_msg types.WorkerMessage) {
+ switch m := _msg.(type) {
+ case *types.Error:
+ err := fmt.Errorf("handleListMessages: %v", m.Error)
+ imapw.worker.Logger.Printf("could not fetch headers: %s", err)
+ emitErr(err)
+ case *types.Done:
+ imapw.worker.PostMessage(&types.Done{types.RespondTo(msg)}, nil)
+ }
+ })
+}
+
+func (imapw *IMAPWorker) handleFoodMessages(msg *types.FoodMessages) {
+ item := imap.FormatFlagsOp(imap.AddFlags, true)
+ flags := []interface{}{"food"}
+ if !msg.Food {
+ item = imap.FormatFlagsOp(imap.RemoveFlags, true)
+ flags = []interface{}{"food"}
+ }
+ uids := toSeqSet(msg.Uids)
+ emitErr := func(err error) {
+ imapw.worker.PostMessage(&types.Error{
+ Message: types.RespondTo(msg),
+ Error: err,
+ }, nil)
+ }
+ if err := imapw.client.UidStore(uids, item, flags, nil); err != nil {
+ emitErr(err)
+ return
+ }
+ imapw.worker.PostAction(&types.FetchMessageHeaders{
+ Uids: msg.Uids,
+ }, func(_msg types.WorkerMessage) {
+ switch m := _msg.(type) {
+ case *types.Error:
+ err := fmt.Errorf("handleFoodMessages: %v", m.Error)
+ imapw.worker.Logger.Printf("could not fetch headers: %s", err)
+ emitErr(err)
+ case *types.Done:
+ imapw.worker.PostMessage(&types.Done{types.RespondTo(msg)}, nil)
+ }
+ })
+}
+
+func (imapw *IMAPWorker) handlePersonalMessages(msg *types.PersonalMessages) {
+ item := imap.FormatFlagsOp(imap.AddFlags, true)
+ flags := []interface{}{"personal"}
+ if !msg.Personal {
+ item = imap.FormatFlagsOp(imap.RemoveFlags, true)
+ flags = []interface{}{"personal"}
+ }
+ uids := toSeqSet(msg.Uids)
+ emitErr := func(err error) {
+ imapw.worker.PostMessage(&types.Error{
+ Message: types.RespondTo(msg),
+ Error: err,
+ }, nil)
+ }
+ if err := imapw.client.UidStore(uids, item, flags, nil); err != nil {
+ emitErr(err)
+ return
+ }
+ imapw.worker.PostAction(&types.FetchMessageHeaders{
+ Uids: msg.Uids,
+ }, func(_msg types.WorkerMessage) {
+ switch m := _msg.(type) {
+ case *types.Error:
+ err := fmt.Errorf("handlePersonalMessages: %v", m.Error)
+ imapw.worker.Logger.Printf("could not fetch headers: %s", err)
+ emitErr(err)
+ case *types.Done:
+ imapw.worker.PostMessage(&types.Done{types.RespondTo(msg)}, nil)
+ }
+ })
+}
+
+func (imapw *IMAPWorker) handleWorkMessages(msg *types.WorkMessages) {
+ item := imap.FormatFlagsOp(imap.AddFlags, true)
+ flags := []interface{}{"work"}
+ if !msg.Work {
+ item = imap.FormatFlagsOp(imap.RemoveFlags, true)
+ flags = []interface{}{"work"}
+ }
+ uids := toSeqSet(msg.Uids)
+ emitErr := func(err error) {
+ imapw.worker.PostMessage(&types.Error{
+ Message: types.RespondTo(msg),
+ Error: err,
+ }, nil)
+ }
+ if err := imapw.client.UidStore(uids, item, flags, nil); err != nil {
+ emitErr(err)
+ return
+ }
+ imapw.worker.PostAction(&types.FetchMessageHeaders{
+ Uids: msg.Uids,
+ }, func(_msg types.WorkerMessage) {
+ switch m := _msg.(type) {
+ case *types.Error:
+ err := fmt.Errorf("handleWorkMessages: %v", m.Error)
+ imapw.worker.Logger.Printf("could not fetch headers: %s", err)
+ emitErr(err)
+ case *types.Done:
+ imapw.worker.PostMessage(&types.Done{types.RespondTo(msg)}, nil)
+ }
+ })
+}
+
+func (imapw *IMAPWorker) handlePhysicsMessages(msg *types.PhysicsMessages) {
+ item := imap.FormatFlagsOp(imap.AddFlags, true)
+ flags := []interface{}{"physics"}
+ if !msg.Physics {
+ item = imap.FormatFlagsOp(imap.RemoveFlags, true)
+ flags = []interface{}{"physics"}
+ }
+ uids := toSeqSet(msg.Uids)
+ emitErr := func(err error) {
+ imapw.worker.PostMessage(&types.Error{
+ Message: types.RespondTo(msg),
+ Error: err,
+ }, nil)
+ }
+ if err := imapw.client.UidStore(uids, item, flags, nil); err != nil {
+ emitErr(err)
+ return
+ }
+ imapw.worker.PostAction(&types.FetchMessageHeaders{
+ Uids: msg.Uids,
+ }, func(_msg types.WorkerMessage) {
+ switch m := _msg.(type) {
+ case *types.Error:
+ err := fmt.Errorf("handlePhysicsMessages: %v", m.Error)
+ imapw.worker.Logger.Printf("could not fetch headers: %s", err)
+ emitErr(err)
+ case *types.Done:
+ imapw.worker.PostMessage(&types.Done{types.RespondTo(msg)}, nil)
+ }
+ })
+}
+
+func (imapw *IMAPWorker) handleTodoMessages(msg *types.TodoMessages) {
+ item := imap.FormatFlagsOp(imap.AddFlags, true)
+ flags := []interface{}{"todo"}
+ if !msg.Todo {
+ item = imap.FormatFlagsOp(imap.RemoveFlags, true)
+ flags = []interface{}{"todo"}
+ }
+ uids := toSeqSet(msg.Uids)
+ emitErr := func(err error) {
+ imapw.worker.PostMessage(&types.Error{
+ Message: types.RespondTo(msg),
+ Error: err,
+ }, nil)
+ }
+ if err := imapw.client.UidStore(uids, item, flags, nil); err != nil {
+ emitErr(err)
+ return
+ }
+ imapw.worker.PostAction(&types.FetchMessageHeaders{
+ Uids: msg.Uids,
+ }, func(_msg types.WorkerMessage) {
+ switch m := _msg.(type) {
+ case *types.Error:
+ err := fmt.Errorf("handleTodoMessages: %v", m.Error)
+ imapw.worker.Logger.Printf("could not fetch headers: %s", err)
+ emitErr(err)
+ case *types.Done:
+ imapw.worker.PostMessage(&types.Done{types.RespondTo(msg)}, nil)
+ }
+ })
+}
+
+func (imapw *IMAPWorker) handleLaterMessages(msg *types.LaterMessages) {
+ item := imap.FormatFlagsOp(imap.AddFlags, true)
+ flags := []interface{}{"later"}
+ if !msg.Later {
+ item = imap.FormatFlagsOp(imap.RemoveFlags, true)
+ flags = []interface{}{"later"}
+ }
+ uids := toSeqSet(msg.Uids)
+ emitErr := func(err error) {
+ imapw.worker.PostMessage(&types.Error{
+ Message: types.RespondTo(msg),
+ Error: err,
+ }, nil)
+ }
+ if err := imapw.client.UidStore(uids, item, flags, nil); err != nil {
+ emitErr(err)
+ return
+ }
+ imapw.worker.PostAction(&types.FetchMessageHeaders{
+ Uids: msg.Uids,
+ }, func(_msg types.WorkerMessage) {
+ switch m := _msg.(type) {
+ case *types.Error:
+ err := fmt.Errorf("handleLaterMessages: %v", m.Error)
+ imapw.worker.Logger.Printf("could not fetch headers: %s", err)
+ emitErr(err)
+ case *types.Done:
+ imapw.worker.PostMessage(&types.Done{types.RespondTo(msg)}, nil)
+ }
+ })
+}
+
func (imapw *IMAPWorker) handleFlagMessages(msg *types.FlagMessages) {
flags := []interface{}{flagToImap[msg.Flag]}
item := imap.FormatFlagsOp(imap.AddFlags, true)
diff --git a/worker/imap/imap.go b/worker/imap/imap.go
index 29dbc10..e625374 100644
--- a/worker/imap/imap.go
+++ b/worker/imap/imap.go
@@ -85,6 +85,15 @@ var imapToFlag = map[string]models.Flag{
imap.AnsweredFlag: models.AnsweredFlag,
imap.DeletedFlag: models.DeletedFlag,
imap.FlaggedFlag: models.FlaggedFlag,
+ // NOTE(shivesh): my custom flags
+ "important": models.ImportantFlag,
+ "list": models.ListFlag,
+ "food": models.FoodFlag,
+ "personal": models.PersonalFlag,
+ "work": models.WorkFlag,
+ "physics": models.PhysicsFlag,
+ "todo": models.TodoFlag,
+ "later": models.LaterFlag,
}
var flagToImap = map[models.Flag]string{
@@ -93,6 +102,15 @@ var flagToImap = map[models.Flag]string{
models.AnsweredFlag: imap.AnsweredFlag,
models.DeletedFlag: imap.DeletedFlag,
models.FlaggedFlag: imap.FlaggedFlag,
+ // NOTE(shivesh): my custom flags
+ models.ImportantFlag: "important",
+ models.ListFlag: "list",
+ models.FoodFlag: "food",
+ models.PersonalFlag: "personal",
+ models.WorkFlag: "work",
+ models.PhysicsFlag: "physics",
+ models.TodoFlag: "todo",
+ models.LaterFlag: "later",
}
func translateImapFlags(imapFlags []string) []models.Flag {
diff --git a/worker/imap/search.go b/worker/imap/search.go
index f866b1c..d27648b 100644
--- a/worker/imap/search.go
+++ b/worker/imap/search.go
@@ -66,6 +66,23 @@ func getParsedFlag(name string) (string, error) {
return imap.FlaggedFlag, nil
case "answered":
return imap.AnsweredFlag, nil
+ // NOTE(shivesh): my custom flags
+ case "important":
+ return name, nil
+ case "list":
+ return name, nil
+ case "food":
+ return name, nil
+ case "personal":
+ return name, nil
+ case "work":
+ return name, nil
+ case "physics":
+ return name, nil
+ case "todo":
+ return name, nil
+ case "later":
+ return name, nil
}
return imap.FlaggedFlag, errors.New("Flag not suppored")
}
diff --git a/worker/imap/worker.go b/worker/imap/worker.go
index dab0afb..d5d4421 100644
--- a/worker/imap/worker.go
+++ b/worker/imap/worker.go
@@ -181,6 +181,23 @@ func (w *IMAPWorker) handleMessage(msg types.WorkerMessage) error {
w.handleFlagMessages(msg)
case *types.AnsweredMessages:
w.handleAnsweredMessages(msg)
+ // NOTE(shivesh): my custom flags
+ case *types.ImportantMessages:
+ w.handleImportantMessages(msg)
+ case *types.ListMessages:
+ w.handleListMessages(msg)
+ case *types.FoodMessages:
+ w.handleFoodMessages(msg)
+ case *types.PersonalMessages:
+ w.handlePersonalMessages(msg)
+ case *types.WorkMessages:
+ w.handleWorkMessages(msg)
+ case *types.PhysicsMessages:
+ w.handlePhysicsMessages(msg)
+ case *types.TodoMessages:
+ w.handleTodoMessages(msg)
+ case *types.LaterMessages:
+ w.handleLaterMessages(msg)
case *types.CopyMessages:
w.handleCopyMessages(msg)
case *types.AppendMessage:
diff --git a/worker/types/messages.go b/worker/types/messages.go
index ab0e545..ea61211 100644
--- a/worker/types/messages.go
+++ b/worker/types/messages.go
@@ -133,6 +133,55 @@ type AnsweredMessages struct {
Uids []uint32
}
+// NOTE(shivesh): my custom flags
+type ImportantMessages struct {
+ Message
+ Important bool
+ Uids []uint32
+}
+
+type ListMessages struct {
+ Message
+ List bool
+ Uids []uint32
+}
+
+type FoodMessages struct {
+ Message
+ Food bool
+ Uids []uint32
+}
+
+type PersonalMessages struct {
+ Message
+ Personal bool
+ Uids []uint32
+}
+
+type WorkMessages struct {
+ Message
+ Work bool
+ Uids []uint32
+}
+
+type PhysicsMessages struct {
+ Message
+ Physics bool
+ Uids []uint32
+}
+
+type TodoMessages struct {
+ Message
+ Todo bool
+ Uids []uint32
+}
+
+type LaterMessages struct {
+ Message
+ Later bool
+ Uids []uint32
+}
+
type CopyMessages struct {
Message
Destination string