set.go 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. package main
  2. import (
  3. "flag"
  4. "fmt"
  5. "io"
  6. "os"
  7. "strconv"
  8. "strings"
  9. "git.sr.ht/~blallo/papero/cli"
  10. "git.sr.ht/~blallo/papero/imaputils"
  11. "github.com/emersion/go-imap"
  12. )
  13. var setVerbs cli.CommandMap
  14. func init() {
  15. setVerbs = cli.CommandMap{
  16. "message": SetMessageCmd{},
  17. // "subscribe": SetSubscribedCmd{},
  18. // "unsubscribe": SetUnsubscribedCmd{},
  19. }
  20. }
  21. type SetCmd struct{}
  22. func (s SetCmd) Func(args []string) error {
  23. flagset := flag.NewFlagSet(args[0], flag.ExitOnError)
  24. flagset.Usage = func() { s.Help(os.Stdout, flagset) }
  25. flagset.Parse(args[1:])
  26. subArgs := flagset.Args()
  27. if len(subArgs) == 0 {
  28. s.Help(os.Stderr, flagset)
  29. os.Exit(1)
  30. }
  31. cmd := subArgs[0]
  32. if Session.Info.Opts.Debug {
  33. Log.Debug("set verb:", cmd)
  34. }
  35. return setVerbs[cmd].Func(subArgs)
  36. }
  37. func (s SetCmd) Help(w io.Writer, set *flag.FlagSet) {
  38. fmt.Fprintf(w, "USAGE: %s set VERB [verb opts]\n", Session.Info.Name)
  39. fmt.Fprintf(w, "\nVERBS:\n")
  40. for verb := range setVerbs {
  41. fmt.Fprintf(w, "\t%s\n", verb)
  42. }
  43. }
  44. // VERBS
  45. type SetMessageCmd struct{}
  46. func (sm SetMessageCmd) Func(args []string) error {
  47. if Session.Info.Opts.Debug {
  48. Log.Debug("enter set message")
  49. }
  50. flags := imaputils.NewFlagsStatus()
  51. var opts imaputils.SetFlagsOpts
  52. flagSeen := cli.NewPairFlag()
  53. flagAnswered := cli.NewPairFlag()
  54. flagFlagged := cli.NewPairFlag()
  55. flagDeleted := cli.NewPairFlag()
  56. flagDraft := cli.NewPairFlag()
  57. flagset := flag.NewFlagSet(args[0], flag.ExitOnError)
  58. flagset.Var(&flagSeen, "seen", "Set or unset `seen` flag on message")
  59. flagset.Var(&flagAnswered, "answered", "Set or unset `answered` flag on message")
  60. flagset.Var(&flagFlagged, "flagged", "Set or unset `flagged` flag on message")
  61. flagset.Var(&flagDeleted, "deleted", "Set or unset `deleted` flag on message")
  62. flagset.Var(&flagDraft, "draft", "Set or unset `draft` flag on message")
  63. flagset.Usage = func() {
  64. sm.Help(os.Stdout, flagset)
  65. }
  66. flagset.Parse(args[1:])
  67. subArgs := flagset.Args()
  68. if len(subArgs) < 2 {
  69. Log.Debugf("Too few arguments: %s\n", subArgs)
  70. sm.Help(os.Stderr, flagset)
  71. os.Exit(1)
  72. }
  73. opts.Mailbox = subArgs[0]
  74. seq := new(imap.SeqSet)
  75. for _, msgId := range subArgs[1:] {
  76. if err := parseMessageSeq(seq, msgId); err != nil {
  77. return err
  78. }
  79. }
  80. opts.MessageSeq = seq
  81. opts.Debug = Session.Info.Opts.Debug
  82. if err := assignFlag(*flagSeen.Pair, flags.SetSeen, flags.UnsetSeen); err != nil {
  83. return err
  84. }
  85. if err := assignFlag(*flagAnswered.Pair, flags.SetAnswered, flags.UnsetAnswered); err != nil {
  86. return err
  87. }
  88. if err := assignFlag(*flagFlagged.Pair, flags.SetFlagged, flags.UnsetFlagged); err != nil {
  89. return err
  90. }
  91. if err := assignFlag(*flagDeleted.Pair, flags.SetDeleted, flags.UnsetDeleted); err != nil {
  92. return err
  93. }
  94. if err := assignFlag(*flagDraft.Pair, flags.SetDraft, flags.UnsetDraft); err != nil {
  95. return err
  96. }
  97. Log.Debugf("Setting flags: %s\n", flags)
  98. opts.Flags = flags
  99. return imaputils.SetFlags(Session.Config, &opts)
  100. }
  101. func (sm SetMessageCmd) Help(w io.Writer, set *flag.FlagSet) {
  102. fmt.Fprintf(w, "USAGE: %s set message [opts] MAILBOX MESSAGE_ID_OR_RANGE [MESSAGE_ID_OR_RANGE [MESSAGE_ID_OR_RANGE ...]]\n", Session.Info.Name)
  103. fmt.Fprintln(w, "\nMESSAGE_ID_OR_RANGE being a single message id or a git-like range")
  104. fmt.Fprintln(w, "Example:")
  105. fmt.Fprintln(w, "\t12345\t- A single message")
  106. fmt.Fprintln(w, "\t123...258\t- A range from id 123 to id 258")
  107. fmt.Fprintf(w, "\nOPTS:\n")
  108. set.PrintDefaults()
  109. }
  110. func parseMessageSeq(seq *imap.SeqSet, data string) error {
  111. if strings.Contains(data, "..") {
  112. split := strings.Split(data, "..")
  113. start, err := strconv.ParseUint(split[0], 10, 0)
  114. if err != nil {
  115. return err
  116. }
  117. stop, err := strconv.ParseUint(split[2], 10, 0)
  118. if err != nil {
  119. return err
  120. }
  121. seq.AddRange(uint32(start), uint32(stop))
  122. } else {
  123. msg, err := strconv.ParseUint(data, 10, 0)
  124. if err != nil {
  125. return err
  126. }
  127. seq.AddNum(uint32(msg))
  128. }
  129. return nil
  130. }
  131. func assignFlag(flagOp cli.Pair, setCallback, unsetCallback func()) error {
  132. switch flagOp {
  133. case cli.Pair{true, false}:
  134. setCallback()
  135. case cli.Pair{false, true}:
  136. unsetCallback()
  137. default:
  138. return nil
  139. }
  140. return nil
  141. }