Browse Source

Add add verb and message subcommand

Blallo 3 years ago
parent
commit
8bd1adca82
4 changed files with 235 additions and 0 deletions
  1. 152 0
      cli/papero/add.go
  2. 4 0
      cli/papero/main.go
  3. 32 0
      cli/utils.go
  4. 47 0
      imaputils/put_message.go

+ 152 - 0
cli/papero/add.go

@@ -0,0 +1,152 @@
+package main
+
+import (
+	"bufio"
+	"bytes"
+	"flag"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"os"
+
+	"git.sr.ht/~blallo/papero/cli"
+	"git.sr.ht/~blallo/papero/imaputils"
+)
+
+var addVerbs cli.CommandMap
+
+func init() {
+	addVerbs = cli.CommandMap{
+		"message": PutMessageCmd{},
+		// "mailbox": CreateMailboxCmd{},
+	}
+}
+
+type AddCmd struct{}
+
+func (a AddCmd) Func(args []string) error {
+	flagset := flag.NewFlagSet(args[0], flag.ExitOnError)
+	flagset.Usage = func() { a.Help(os.Stdout, flagset) }
+	flagset.Parse(args[1:])
+	subArgs := flagset.Args()
+	if len(subArgs) == 0 {
+		a.Help(os.Stderr, flagset)
+		os.Exit(1)
+	}
+	cmd := subArgs[0]
+	if Session.Info.Opts.Debug {
+		Log.Debug("add verb:", cmd)
+	}
+
+	return addVerbs[cmd].Func(subArgs)
+}
+
+func (a AddCmd) Help(w io.Writer, set *flag.FlagSet) {
+	fmt.Fprintf(w, "USAGE: %s add VERB [verb opts]\n", Session.Info.Name)
+	fmt.Fprintf(w, "\nVERBS:\n")
+	for verb := range addVerbs {
+		fmt.Fprintf(w, "\t%s\n", verb)
+	}
+}
+
+// VERBS
+
+type PutMessageCmd struct{}
+
+func (pm PutMessageCmd) Func(args []string) error {
+	var opts imaputils.PutMessageOpts
+	var err error
+	var bodyReader io.Reader
+	var flagSeen, flagAnswered, flagFlagged, flagDeleted, flagDraft bool
+	var messageTime = cli.NewAbsTimeFlag()
+	if Session.Info.Opts.Debug {
+		Log.Debug("enter add message")
+	}
+
+	flagset := flag.NewFlagSet(args[0], flag.ExitOnError)
+	flagset.BoolVar(&flagSeen, "seen", false, "set the seen flag")
+	flagset.BoolVar(&flagAnswered, "answered", false, "set the answered flag")
+	flagset.BoolVar(&flagFlagged, "flagged", false, "set the flagged flag")
+	flagset.BoolVar(&flagDeleted, "deleted", false, "set the deleted flag")
+	flagset.BoolVar(&flagDraft, "draft", false, "set the draft flag")
+	flagset.Var(&messageTime, "time", "time at which the message has been sent")
+	flagset.Usage = func() {
+		pm.Help(os.Stdout, flagset)
+	}
+
+	flagset.Parse(args[1:])
+
+	subArgs := flagset.Args()
+	if len(subArgs) != 2 {
+		Log.Debugf("Too few arguments: %s\n", subArgs)
+		pm.Help(os.Stderr, flagset)
+		os.Exit(1)
+	}
+
+	opts.Debug = Session.Info.Opts.Debug
+
+	opts.Mailbox = subArgs[0]
+
+	if subArgs[1] == "-" {
+		bodyReader = os.Stdin
+	} else {
+		file, err := os.Open(subArgs[1])
+		if err != nil {
+			return err
+		}
+		bodyReader = bufio.NewReader(file)
+	}
+	opts.Body, err = readIntoBuffer(bodyReader)
+	if err != nil {
+		return err
+	}
+
+	opts.Flags = intoList(flagSeen, flagAnswered, flagFlagged, flagDeleted, flagDraft)
+
+	opts.Time = *messageTime.Time
+
+	Log.Debugf("Opts: %+v\n", opts)
+
+	imaputils.PutMessage(Session.Config, &opts)
+
+	return nil
+}
+
+func (pm PutMessageCmd) Help(w io.Writer, set *flag.FlagSet) {
+	fmt.Fprintf(w, "USAGE: %s set put MAILBOX PATH_OR_STDIN\n", Session.Info.Name)
+	fmt.Fprintln(w, "\nPATH_OR_STDIN being either a path to a file or `-` to accept input from stdin")
+	set.PrintDefaults()
+}
+
+func readIntoBuffer(r io.Reader) (*bytes.Buffer, error) {
+	var empty bytes.Buffer
+
+	b, err := ioutil.ReadAll(r)
+	if err != nil {
+		return &empty, err
+	}
+
+	Log.Debugf("content %+v\n", b)
+	buff := bytes.NewBuffer(b)
+	return buff, nil
+}
+
+func intoList(flagSeen, flagAnswered, flagFlagged, flagDeleted, flagDraft bool) []string {
+	var result []string
+	if flagSeen {
+		result = append(result, "seen")
+	}
+	if flagAnswered {
+		result = append(result, "answered")
+	}
+	if flagFlagged {
+		result = append(result, "flagged")
+	}
+	if flagDeleted {
+		result = append(result, "deleted")
+	}
+	if flagDraft {
+		result = append(result, "draft")
+	}
+	return result
+}

+ 4 - 0
cli/papero/main.go

@@ -18,9 +18,13 @@ var Log *log.Logger
 func init() {
 	get := GetCmd{}
 	set := SetCmd{}
+	add := AddCmd{}
+	// del := DelCmd{}
 	Session.Info.Commands = cli.CommandMap{
 		"get": get,
 		"set": set,
+		"add": add,
+		// "del": del,
 	}
 	Session.Info.Name = "papero"
 	flag.Usage = func() { cli.Usage(os.Stdout, Session.Info) }

+ 32 - 0
cli/utils.go

@@ -5,6 +5,7 @@ import (
 	"flag"
 	"fmt"
 	"io"
+	"time"
 )
 
 type GlobalOpts struct {
@@ -84,3 +85,34 @@ func (pf PairFlag) Set(s string) error {
 }
 
 var ErrAllowedPairFlagValues = errors.New("only `set` or `unset` are allowed")
+
+type AbsTimeFlag struct {
+	*time.Time
+}
+
+func NewAbsTimeFlag() AbsTimeFlag {
+	return AbsTimeFlag{
+		Time: &time.Time{},
+	}
+}
+
+func (t AbsTimeFlag) String() string {
+	return fmt.Sprint(t.Time)
+}
+
+func (t AbsTimeFlag) Set(s string) error {
+	const layout = "2006-01-02T15:04:05"
+	var parsedTime time.Time
+	var err error
+	if s == "" {
+		t.Time = &parsedTime
+		return nil
+	}
+	parsedTime, err = time.Parse(layout, s)
+	if err != nil {
+		return err
+	}
+
+	t.Time = &parsedTime
+	return nil
+}

+ 47 - 0
imaputils/put_message.go

@@ -0,0 +1,47 @@
+package imaputils
+
+import (
+	"bytes"
+	"time"
+
+	"git.sr.ht/~blallo/papero/config"
+)
+
+var zeroTime = time.Time{}
+
+type PutMessageOpts struct {
+	Debug   bool
+	Mailbox string
+	Body    *bytes.Buffer
+	Flags   []string
+	Time    time.Time
+}
+
+func PutMessage(conf *config.AccountData, opts *PutMessageOpts) error {
+	conn := NewConnection(conf)
+
+	err := conn.Start(opts.Debug)
+	if err != nil {
+		return err
+	}
+	defer conn.Close()
+
+	return PutMessageInSession(conn, opts)
+}
+
+func PutMessageInSession(conn *IMAPConnection, opts *PutMessageOpts) error {
+	var err error
+	var msgTime time.Time
+
+	_, err = conn.client.Select(opts.Mailbox, false)
+	if err != nil {
+		return err
+	}
+
+	if opts.Time == zeroTime {
+		msgTime = time.Now()
+	} else {
+		msgTime = opts.Time
+	}
+	return conn.client.Append(opts.Mailbox, opts.Flags, msgTime, opts.Body)
+}