can read fidel withdrawal emails

master
Bel LaPointe 2022-12-09 09:48:04 -07:00
parent f6fc366dd4
commit 8b226294a2
2 changed files with 46 additions and 13 deletions

View File

@ -219,9 +219,30 @@ func (c *uccuScraper) scrape(m *mail.Message) ([]*Transaction, error) {
} }
func (c *fidelityScraper) 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) 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) { func (c *bankOfAmericaScraper) scrape(m *mail.Message) ([]*Transaction, error) {
subject := fmt.Sprint(m.Header["Subject"]) subject := fmt.Sprint(m.Header["Subject"])
if strings.Contains(subject, "Credit card transaction") { if strings.Contains(subject, "Credit card transaction") {
@ -239,8 +260,8 @@ func (c *bankOfAmericaScraper) scrapeCharge(m *mail.Message) ([]*Transaction, er
return nil, err return nil, err
} }
amount := c.findFloatAfter(b, "Amount: $") amount := findFloatAfter(b, "Amount: $")
acc := string(c.findLineAfter(b, "Where: ")) acc := string(findLineAfter(b, "Where: "))
if amount == "" || acc == "" { if amount == "" || acc == "" {
return nil, errors.New("no amount/account found") return nil, errors.New("no amount/account found")
@ -254,7 +275,7 @@ func (c *bankOfAmericaScraper) scrapePayment(m *mail.Message) ([]*Transaction, e
if err != nil { if err != nil {
return nil, err return nil, err
} }
amount := "-" + c.findFloatAfter(b, "Payment: $") amount := "-" + findFloatAfter(b, "Payment: $")
acc := "Payment" acc := "Payment"
if amount == "" || acc == "" { if amount == "" || acc == "" {
return nil, errors.New("no amount/account found") 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 return []*Transaction{transaction}, nil
} }
func (c *bankOfAmericaScraper) findFloatAfter(b []byte, prefix string) string { func findSubstringBetween(b []byte, prefix, suffix string) (string, bool) {
amount := string(c.findLineAfter(b, prefix)) 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, " ") words := strings.Split(amount, " ")
lastword := words[len(words)-1] lastword := words[len(words)-1]
escapedfloat := strings.TrimPrefix(lastword, "$") escapedfloat := strings.TrimPrefix(lastword, "$")
@ -273,7 +306,7 @@ func (c *bankOfAmericaScraper) findFloatAfter(b []byte, prefix string) string {
return amount 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")) { for _, line := range bytes.Split(b, []byte("\n")) {
if bytes.HasPrefix(line, []byte(prefix)) { if bytes.HasPrefix(line, []byte(prefix)) {
return bytes.TrimSpace(bytes.TrimPrefix(line, []byte(prefix))) return bytes.TrimSpace(bytes.TrimPrefix(line, []byte(prefix)))

View File

@ -186,13 +186,13 @@ func TestScrapeFidelityWithdrawal(t *testing.T) {
} }
message := &mail.Message{ message := &mail.Message{
Header: map[string][]string{ 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), Body: bytes.NewReader(b),
} }
bofa := &bankOfAmericaScraper{} fidelity := &fidelityScraper{}
gots, err := bofa.scrape(message) gots, err := fidelity.scrape(message)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -203,11 +203,11 @@ func TestScrapeFidelityWithdrawal(t *testing.T) {
got := gots[0] got := gots[0]
want := Transaction{ want := Transaction{
ID: got.ID, ID: got.ID,
Bank: BankOfAmerica, Bank: Fidelity,
Amount: "75.08", Amount: "1.00",
Vendor: "PAYPAL GIBBDOGENTE MA", Vendor: "CHASE CREDIT CRD",
Date: "[]", Date: "[]",
Account: BankOfAmerica.String(), Account: Fidelity.String() + "-5576",
} }
if *got != want { if *got != want {
t.Fatalf("want:\n\t%+v, got\n\t%+v", want, *got) t.Fatalf("want:\n\t%+v, got\n\t%+v", want, *got)