From bbd51ea9c505dec175e0b50267a07d6832f00885 Mon Sep 17 00:00:00 2001 From: bel Date: Thu, 29 Jul 2021 22:24:30 -0600 Subject: [PATCH] support ledger file append --- config.go | 46 +++++++++++++++++++++++++------- upload.go | 44 +++++++++++++++++++++++++++++++ upload_test.go | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 151 insertions(+), 10 deletions(-) create mode 100644 upload_test.go diff --git a/config.go b/config.go index 47e59c4..9fb6979 100755 --- a/config.go +++ b/config.go @@ -11,6 +11,18 @@ import ( "strings" ) +type Uploader int + +const ( + UploaderTodo = Uploader(iota) + UploaderLedger +) + +var uploaders = map[string]Uploader{ + "todo": UploaderTodo, + "ledger": UploaderLedger, +} + type Config struct { EmailUser string EmailPass string @@ -19,6 +31,7 @@ type Config struct { TodoToken string TodoList string TodoTag string + Uploader Uploader Storage storage.DB } @@ -30,6 +43,9 @@ func NewConfig() Config { as.Append(args.STRING, "emailuser", "email username", "breellocaldev@gmail.com") as.Append(args.STRING, "emailpass", "email password", "ML3WQRFSqe9rQ8qNkm") as.Append(args.STRING, "emailimap", "email imap", "imap.gmail.com:993") + + as.Append(args.STRING, "uploader", "todo, ledger", "todo") + as.Append(args.STRING, "todoaddr", "todo addr", "https://todo-server.remote.blapointe.com") as.Append(args.STRING, "todopass", "todo pass", "gJtEXbbLHLf54yS9EdujtVN2n6Y") as.Append(args.STRING, "todotoken", "todo token", "") @@ -46,14 +62,10 @@ func NewConfig() Config { panic(err) } - token := as.GetString("todotoken") - if len(token) == 0 { - token = getToken(as) - } - - list := as.GetString("todolist") - if len(list) == 0 { - list = getList(as, token) + uploader := as.GetString("uploader") + ul, ok := uploaders[uploader] + if !ok { + panic("invalid uploader: " + uploader) } storage, err := storage.New(storage.TypeFromString(as.GetString("store")), as.GetString("storeaddr"), as.GetString("storeuser"), as.GetString("storepass")) @@ -66,11 +78,25 @@ func NewConfig() Config { EmailPass: as.GetString("emailpass"), EmailIMAP: as.GetString("emailimap"), TodoAddr: as.GetString("todoaddr"), - TodoToken: token, - TodoList: list, TodoTag: as.GetString("todotag"), Storage: storage, + Uploader: ul, } + + if config.Uploader == UploaderTodo { + token := as.GetString("todotoken") + if len(token) == 0 { + token = getToken(as) + } + + list := as.GetString("todolist") + if len(list) == 0 { + list = getList(as, token) + } + config.TodoToken = token + config.TodoList = list + } + return config } diff --git a/upload.go b/upload.go index 9a8b164..1e81f22 100755 --- a/upload.go +++ b/upload.go @@ -1,15 +1,31 @@ package main import ( + "errors" "fmt" "io/ioutil" "local/oauth2" + "log" "net/http" "net/url" + "os" + "strconv" "strings" + "time" ) func Upload(config Config, transaction *Transaction) error { + switch config.Uploader { + case UploaderTodo: + return uploadTodo(config, transaction) + case UploaderLedger: + return uploadLedger(config, transaction) + default: + return errors.New("not impl: uploader") + } +} + +func uploadTodo(config Config, transaction *Transaction) error { params := url.Values{ "list": {config.TodoList}, "title": {transaction.Format()}, @@ -32,3 +48,31 @@ func Upload(config Config, transaction *Transaction) error { } return nil } + +func uploadLedger(config Config, transaction *Transaction) error { + f, err := os.OpenFile(config.TodoAddr, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) + if err != nil { + return err + } + defer f.Close() + amount, _ := strconv.ParseFloat(transaction.Amount, 32) + amount *= -1 + remote := "Withdrawal:" + if amount > 0 { + remote = "Deposit:" + } + remote += strings.ReplaceAll(transaction.Account, " ", "") + fmt.Fprintf(f, "%-50s%-s\n", formatGMailDate(transaction.Date), transaction.Account) + fmt.Fprintf(f, "%-50s%-50s$%.2f\n", "", transaction.Bank, amount) + fmt.Fprintf(f, "%-50s%-s\n", "", remote) + return nil +} + +func formatGMailDate(s string) string { + time, err := time.Parse("[Mon, 2 Jan 2006 15:04:05 -0700 (MST)]", s) + if err != nil { + log.Println(s, err) + return s + } + return time.Format("2006-01-02") +} diff --git a/upload_test.go b/upload_test.go new file mode 100644 index 0000000..f27f4ad --- /dev/null +++ b/upload_test.go @@ -0,0 +1,71 @@ +package main + +import ( + "io/ioutil" + "local/storage" + "path" + "testing" + + "github.com/google/uuid" +) + +func TestUploadLedger(t *testing.T) { + cases := map[string]struct { + transaction Transaction + }{ + "simple": { + transaction: Transaction{ + ID: uuid.New().String(), + Bank: Chase, + Amount: "1.10", + Account: "account", + Date: "today", + }, + }, + } + + for name, d := range cases { + c := d + t.Run(name, func(t *testing.T) { + config := Config{ + TodoAddr: path.Join(t.TempDir(), name), + Uploader: UploaderLedger, + Storage: storage.NewMap(), + } + if err := uploadLedger(config, &c.transaction); err != nil { + t.Fatal(err) + } + b, err := ioutil.ReadFile(config.TodoAddr) + if err != nil { + t.Fatal(err) + } + t.Logf("\n%s", b) + }) + } +} + +func TestFormatGMailDate(t *testing.T) { + cases := map[string]struct { + input string + want string + }{ + "ok": { + input: "[Tue, 20 Jul 2021 23:46:00 -0400 (EDT)]", + want: "2021-07-20", + }, + "bad": { + input: "2021-07-20", + want: "2021-07-20", + }, + } + + for name, d := range cases { + c := d + t.Run(name, func(t *testing.T) { + got := formatGMailDate(c.input) + if got != c.want { + t.Fatal(c.input, c.want, got) + } + }) + } +}