diff --git a/scrape.go b/scrape.go index f36b45a..00d0962 100755 --- a/scrape.go +++ b/scrape.go @@ -219,9 +219,30 @@ func (c *uccuScraper) scrape(m *mail.Message) ([]*Transaction, error) { } func (c *fidelityScraper) scrape(m *mail.Message) ([]*Transaction, error) { + subject := fmt.Sprint(m.Header["Subject"]) + if strings.Contains(subject, "Debit Withdrawal") { + return c.scrapeWithdrawal(m) + } panic(nil) } +func (c *fidelityScraper) scrapeWithdrawal(m *mail.Message) ([]*Transaction, error) { + b, err := ioutil.ReadAll(m.Body) + if err != nil { + return nil, err + } + + amount, amountOk := findSubstringBetween(b, "in the amount of $", " ") + fidelAcc, fidelAccOk := findSubstringBetween(b, "For account ending in ", ":") + acc, accOk := findSubstringBetween(b, "in the amount of $"+amount+" by ", ".") + + if amount == "" || acc == "" { + return nil, fmt.Errorf("no amount/account found: fidelAcc=%v,fidelAccOk=%v, acc=%v,accOk=%v, amount=%v,amountOk=%v", fidelAcc, fidelAccOk, acc, accOk, amount, amountOk) + } + transaction := NewTransaction(fmt.Sprintf("%s-%s", Fidelity, fidelAcc), amount, acc, fmt.Sprint(m.Header["Date"]), Fidelity) + return []*Transaction{transaction}, nil +} + func (c *bankOfAmericaScraper) scrape(m *mail.Message) ([]*Transaction, error) { subject := fmt.Sprint(m.Header["Subject"]) if strings.Contains(subject, "Credit card transaction") { @@ -239,8 +260,8 @@ func (c *bankOfAmericaScraper) scrapeCharge(m *mail.Message) ([]*Transaction, er return nil, err } - amount := c.findFloatAfter(b, "Amount: $") - acc := string(c.findLineAfter(b, "Where: ")) + amount := findFloatAfter(b, "Amount: $") + acc := string(findLineAfter(b, "Where: ")) if amount == "" || acc == "" { return nil, errors.New("no amount/account found") @@ -254,7 +275,7 @@ func (c *bankOfAmericaScraper) scrapePayment(m *mail.Message) ([]*Transaction, e if err != nil { return nil, err } - amount := "-" + c.findFloatAfter(b, "Payment: $") + amount := "-" + findFloatAfter(b, "Payment: $") acc := "Payment" if amount == "" || acc == "" { return nil, errors.New("no amount/account found") @@ -263,8 +284,20 @@ func (c *bankOfAmericaScraper) scrapePayment(m *mail.Message) ([]*Transaction, e return []*Transaction{transaction}, nil } -func (c *bankOfAmericaScraper) findFloatAfter(b []byte, prefix string) string { - amount := string(c.findLineAfter(b, prefix)) +func findSubstringBetween(b []byte, prefix, suffix string) (string, bool) { + byPre := bytes.Split(b, []byte(prefix)) + if len(byPre) < 2 { + return "", false + } + bySuff := bytes.Split(byPre[1], []byte(suffix)) + if len(bySuff) < 2 { + return "", false + } + return string(bySuff[0]), true +} + +func findFloatAfter(b []byte, prefix string) string { + amount := string(findLineAfter(b, prefix)) words := strings.Split(amount, " ") lastword := words[len(words)-1] escapedfloat := strings.TrimPrefix(lastword, "$") @@ -273,7 +306,7 @@ func (c *bankOfAmericaScraper) findFloatAfter(b []byte, prefix string) string { return amount } -func (c *bankOfAmericaScraper) findLineAfter(b []byte, prefix string) []byte { +func findLineAfter(b []byte, prefix string) []byte { for _, line := range bytes.Split(b, []byte("\n")) { if bytes.HasPrefix(line, []byte(prefix)) { return bytes.TrimSpace(bytes.TrimPrefix(line, []byte(prefix))) diff --git a/scrape_test.go b/scrape_test.go index 1e334e9..b8d1963 100644 --- a/scrape_test.go +++ b/scrape_test.go @@ -186,13 +186,13 @@ func TestScrapeFidelityWithdrawal(t *testing.T) { } message := &mail.Message{ Header: map[string][]string{ - "Subject": []string{"Credit card transaction exceeds alert limit you set"}, + "Subject": []string{"Fidelity Alerts - Direct Debit Withdrawal"}, }, Body: bytes.NewReader(b), } - bofa := &bankOfAmericaScraper{} + fidelity := &fidelityScraper{} - gots, err := bofa.scrape(message) + gots, err := fidelity.scrape(message) if err != nil { t.Fatal(err) } @@ -203,11 +203,11 @@ func TestScrapeFidelityWithdrawal(t *testing.T) { got := gots[0] want := Transaction{ ID: got.ID, - Bank: BankOfAmerica, - Amount: "75.08", - Vendor: "PAYPAL GIBBDOGENTE MA", + Bank: Fidelity, + Amount: "1.00", + Vendor: "CHASE CREDIT CRD", Date: "[]", - Account: BankOfAmerica.String(), + Account: Fidelity.String() + "-5576", } if *got != want { t.Fatalf("want:\n\t%+v, got\n\t%+v", want, *got)