From f6688ecec44b9988308831caf50cb6fc944fa226 Mon Sep 17 00:00:00 2001 From: Rauno Ots Date: Sun, 15 Apr 2018 18:25:41 +0200 Subject: [PATCH 1/2] enable the use of API as an external package export public methods move CLI to a separate package --- README.md | 4 ++-- api.go | 28 +++++++++++++++++----------- n26.go => cmd/n26/n26.go | 25 +++++++++++++------------ 3 files changed, 32 insertions(+), 25 deletions(-) rename n26.go => cmd/n26/n26.go (90%) diff --git a/README.md b/README.md index 5244a02..6f6b6ba 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,11 @@ # n26 -CLI to get information of your N26 account +Go API and CLI to get information of your N26 account # Installation - macOS: Available via Homebrew. Just run `brew install guitmz/n26/n26` - Linux: You can manually build this project or download a binary release. -You can also install with `go get -u github.com/guitmz/n26` (make sure you have your Go env setup correctly) +You can also install with `go get -u github.com/guitmz/n26/cmd/n26` (make sure you have your Go env setup correctly) # Usage ``` diff --git a/api.go b/api.go index 7cab466..a2843da 100644 --- a/api.go +++ b/api.go @@ -1,4 +1,4 @@ -package main +package n26 import ( "encoding/json" @@ -224,7 +224,7 @@ func (auth Auth) n26Request(endpoint string) []byte { return body } -func (auth Auth) getBalance(retType string) (string, *Balance) { +func (auth Auth) GetBalance(retType string) (string, *Balance) { body := auth.n26Request("/api/accounts") balance := &Balance{} check(json.Unmarshal(body, &balance)) @@ -235,7 +235,7 @@ func (auth Auth) getBalance(retType string) (string, *Balance) { return "", balance } -func (auth Auth) getInfo(retType string) (string, *PersonalInfo) { +func (auth Auth) GetInfo(retType string) (string, *PersonalInfo) { body := auth.n26Request("/api/me") info := &PersonalInfo{} check(json.Unmarshal(body, &info)) @@ -246,7 +246,7 @@ func (auth Auth) getInfo(retType string) (string, *PersonalInfo) { return "", info } -func (auth Auth) getStatus(retType string) (string, *Statuses) { +func (auth Auth) GetStatus(retType string) (string, *Statuses) { body := auth.n26Request("/api/me/statuses") status := &Statuses{} check(json.Unmarshal(body, &status)) @@ -257,7 +257,7 @@ func (auth Auth) getStatus(retType string) (string, *Statuses) { return "", status } -func (auth Auth) getAddresses(retType string) (string, *Addresses) { +func (auth Auth) GetAddresses(retType string) (string, *Addresses) { body := auth.n26Request("/api/addresses") addresses := &Addresses{} check(json.Unmarshal(body, &addresses)) @@ -268,7 +268,7 @@ func (auth Auth) getAddresses(retType string) (string, *Addresses) { return "", addresses } -func (auth Auth) getCards(retType string) (string, *Cards) { +func (auth Auth) GetCards(retType string) (string, *Cards) { body := auth.n26Request("/api/v2/cards") cards := &Cards{} check(json.Unmarshal(body, &cards)) @@ -279,7 +279,7 @@ func (auth Auth) getCards(retType string) (string, *Cards) { return "", cards } -func (auth Auth) getLimits(retType string) (string, *Limits) { +func (auth Auth) GetLimits(retType string) (string, *Limits) { body := auth.n26Request("/api/settings/account/limits") limits := &Limits{} check(json.Unmarshal(body, &limits)) @@ -290,7 +290,7 @@ func (auth Auth) getLimits(retType string) (string, *Limits) { return "", limits } -func (auth Auth) getContacts(retType string) (string, *Contacts) { +func (auth Auth) GetContacts(retType string) (string, *Contacts) { body := auth.n26Request("/api/smrt/contacts") contacts := &Contacts{} check(json.Unmarshal(body, &contacts)) @@ -301,7 +301,7 @@ func (auth Auth) getContacts(retType string) (string, *Contacts) { return "", contacts } -func (auth Auth) getTransactions(retType string) (string, *Transactions) { +func (auth Auth) GetTransactions(retType string) (string, *Transactions) { body := auth.n26Request("/api/smrt/transactions") transactions := &Transactions{} check(json.Unmarshal(body, &transactions)) @@ -312,7 +312,7 @@ func (auth Auth) getTransactions(retType string) (string, *Transactions) { return "", transactions } -func (auth Auth) getStatements(retType string) (string, *Statements) { +func (auth Auth) GetStatements(retType string) (string, *Statements) { body := auth.n26Request("/api/statements") statements := &Statements{} check(json.Unmarshal(body, &statements)) @@ -323,7 +323,7 @@ func (auth Auth) getStatements(retType string) (string, *Statements) { return "", statements } -func (auth Auth) getStatementPDF(ID string) { +func (auth Auth) GetStatementPDF(ID string) { body := auth.n26Request(fmt.Sprintf("%s%s", "/api/statements/", ID)) ioutil.WriteFile( fmt.Sprintf("%s.pdf", ID), @@ -331,3 +331,9 @@ func (auth Auth) getStatementPDF(ID string) { 0750, ) } + +func check(e error) { + if e != nil { + panic(e) + } +} diff --git a/n26.go b/cmd/n26/n26.go similarity index 90% rename from n26.go rename to cmd/n26/n26.go index b51eaad..ed9fda0 100644 --- a/n26.go +++ b/cmd/n26/n26.go @@ -9,6 +9,7 @@ import ( "regexp" + "github.com/guitmz/n26" "github.com/howeyc/gopass" "github.com/olekukonko/tablewriter" "github.com/urfave/cli" @@ -20,7 +21,7 @@ func check(e error) { } } -func authentication() *Auth { +func authentication() *n26.Auth { username := os.Getenv("N26_USERNAME") if username == "" { fmt.Print("N26 username: ") @@ -33,7 +34,7 @@ func authentication() *Auth { check(err) password = string(maskedPass) } - return &Auth{username, password} + return &n26.Auth{username, password} } func main() { @@ -51,7 +52,7 @@ func main() { Usage: "your balance information", Action: func(c *cli.Context) error { API := authentication() - prettyJSON, balance := API.getBalance(c.Args().First()) + prettyJSON, balance := API.GetBalance(c.Args().First()) if prettyJSON != "" { fmt.Println(prettyJSON) } else { @@ -70,7 +71,7 @@ func main() { Usage: "personal information", Action: func(c *cli.Context) error { API := authentication() - prettyJSON, info := API.getInfo(c.Args().First()) + prettyJSON, info := API.GetInfo(c.Args().First()) if prettyJSON != "" { fmt.Println(prettyJSON) } else { @@ -87,7 +88,7 @@ func main() { Usage: "general status of your account", Action: func(c *cli.Context) error { API := authentication() - prettyJSON, status := API.getStatus(c.Args().First()) + prettyJSON, status := API.GetStatus(c.Args().First()) if prettyJSON != "" { fmt.Println(prettyJSON) } else { @@ -108,7 +109,7 @@ func main() { Usage: "addresses linked to your account", Action: func(c *cli.Context) error { API := authentication() - prettyJSON, addresses := API.getAddresses(c.Args().First()) + prettyJSON, addresses := API.GetAddresses(c.Args().First()) if prettyJSON != "" { fmt.Println(prettyJSON) } else { @@ -144,7 +145,7 @@ func main() { Usage: "list your cards information", Action: func(c *cli.Context) error { API := authentication() - prettyJSON, cards := API.getCards(c.Args().First()) + prettyJSON, cards := API.GetCards(c.Args().First()) if prettyJSON != "" { fmt.Println(prettyJSON) } else { @@ -171,7 +172,7 @@ func main() { Usage: "your account limits", Action: func(c *cli.Context) error { API := authentication() - prettyJSON, limits := API.getLimits(c.Args().First()) + prettyJSON, limits := API.GetLimits(c.Args().First()) if prettyJSON != "" { fmt.Println(prettyJSON) } else { @@ -197,7 +198,7 @@ func main() { Usage: "your saved contacts", Action: func(c *cli.Context) error { API := authentication() - prettyJSON, contacts := API.getContacts(c.Args().First()) + prettyJSON, contacts := API.GetContacts(c.Args().First()) if prettyJSON != "" { fmt.Println(prettyJSON) } else { @@ -224,7 +225,7 @@ func main() { Usage: "your past transactions", Action: func(c *cli.Context) error { API := authentication() - prettyJSON, transactions := API.getTransactions(c.Args().First()) + prettyJSON, transactions := API.GetTransactions(c.Args().First()) if prettyJSON != "" { fmt.Println(prettyJSON) } else { @@ -258,10 +259,10 @@ func main() { argument := c.Args().First() switch { case dateRegex.MatchString(argument): - API.getStatementPDF(argument) + API.GetStatementPDF(argument) fmt.Println(fmt.Sprintf("[+] PDF file %s.pdf downloaded!", argument)) default: - prettyJSON, statements := API.getStatements(argument) + prettyJSON, statements := API.GetStatements(argument) if prettyJSON != "" { fmt.Println(prettyJSON) } else { From 3f23f7f0e20a5ce112167b0515b725b6917fee43 Mon Sep 17 00:00:00 2001 From: Rauno Ots Date: Sun, 15 Apr 2018 19:35:34 +0200 Subject: [PATCH 2/2] add merchant and location to the CLI transactions output --- cmd/n26/n26.go | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/cmd/n26/n26.go b/cmd/n26/n26.go index ed9fda0..63fb8fa 100644 --- a/cmd/n26/n26.go +++ b/cmd/n26/n26.go @@ -232,18 +232,30 @@ func main() { data := [][]string{} for _, transaction := range *transactions { amount := strconv.FormatFloat(transaction.Amount, 'f', -1, 64) + var location string + if transaction.MerchantCity != "" { + location = transaction.MerchantCity + if transaction.MerchantCountry != 0 { + location += ", " + } + } + if transaction.MerchantCountry != 0 { + location += "Country Code: " + fmt.Sprint(transaction.MerchantCountry) + } data = append(data, []string{ transaction.PartnerName, transaction.PartnerIban, transaction.PartnerBic, + transaction.MerchantName, + location, amount, transaction.CurrencyCode, transaction.Type, }, ) } - table.SetHeader([]string{"Name", "IBAN", "BIC", "Amount", "Currency", "Type"}) + table.SetHeader([]string{"Name", "IBAN", "BIC", "Merchant", "Location", "Amount", "Currency", "Type"}) table.AppendBulk(data) table.Render() }