support ledger file append
parent
f32fb5aad1
commit
bbd51ea9c5
46
config.go
46
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
|
||||
}
|
||||
|
||||
|
|
|
|||
44
upload.go
44
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")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue