plumas iff -banks=plumas
parent
d794a4db52
commit
b920ea80c8
3
bank.go
3
bank.go
|
|
@ -9,6 +9,7 @@ const (
|
||||||
BankOfAmerica
|
BankOfAmerica
|
||||||
Fidelity
|
Fidelity
|
||||||
Amex
|
Amex
|
||||||
|
Plumas
|
||||||
)
|
)
|
||||||
|
|
||||||
func (b Bank) String() string {
|
func (b Bank) String() string {
|
||||||
|
|
@ -25,6 +26,8 @@ func (b Bank) String() string {
|
||||||
return "UCCU"
|
return "UCCU"
|
||||||
case Amex:
|
case Amex:
|
||||||
return "AmericanExpress"
|
return "AmericanExpress"
|
||||||
|
case Plumas:
|
||||||
|
return "Plumas"
|
||||||
}
|
}
|
||||||
return "?"
|
return "?"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -96,6 +96,7 @@ func NewConfig() Config {
|
||||||
UCCU: strings.Contains(strings.ToLower(as.GetString("banks")), strings.ToLower(UCCU.String())),
|
UCCU: strings.Contains(strings.ToLower(as.GetString("banks")), strings.ToLower(UCCU.String())),
|
||||||
Fidelity: strings.Contains(strings.ToLower(as.GetString("banks")), strings.ToLower(Fidelity.String())),
|
Fidelity: strings.Contains(strings.ToLower(as.GetString("banks")), strings.ToLower(Fidelity.String())),
|
||||||
Amex: strings.Contains(strings.ToLower(as.GetString("banks")), strings.ToLower(Amex.String())),
|
Amex: strings.Contains(strings.ToLower(as.GetString("banks")), strings.ToLower(Amex.String())),
|
||||||
|
Plumas: strings.Contains(strings.ToLower(as.GetString("banks")), strings.ToLower(Plumas.String())),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
log.Printf("config: %+v", config)
|
log.Printf("config: %+v", config)
|
||||||
|
|
|
||||||
58
scrape.go
58
scrape.go
|
|
@ -23,6 +23,7 @@ type chaseScraper struct{}
|
||||||
type citiScraper struct{}
|
type citiScraper struct{}
|
||||||
type uccuScraper struct{}
|
type uccuScraper struct{}
|
||||||
type amexScraper struct{}
|
type amexScraper struct{}
|
||||||
|
type plumasScraper struct{}
|
||||||
|
|
||||||
func Scrape(m *mail.Message, banks map[Bank]bool) ([]*Transaction, error) {
|
func Scrape(m *mail.Message, banks map[Bank]bool) ([]*Transaction, error) {
|
||||||
scraper, err := buildScraper(m, banks)
|
scraper, err := buildScraper(m, banks)
|
||||||
|
|
@ -53,6 +54,9 @@ func buildScraper(m *mail.Message, banks map[Bank]bool) (scraper, error) {
|
||||||
if strings.Contains(from, "Notifications@uccu.com") && banks[UCCU] {
|
if strings.Contains(from, "Notifications@uccu.com") && banks[UCCU] {
|
||||||
return newUCCUScraper(), nil
|
return newUCCUScraper(), nil
|
||||||
}
|
}
|
||||||
|
if strings.Contains(from, "Notifications@plumasbank.com") && banks[Plumas] {
|
||||||
|
return newPlumasScraper(), nil
|
||||||
|
}
|
||||||
if strings.Contains(strings.ToLower(from), strings.ToLower("AmericanExpress")) && banks[Amex] {
|
if strings.Contains(strings.ToLower(from), strings.ToLower("AmericanExpress")) && banks[Amex] {
|
||||||
return newAmexScraper(), nil
|
return newAmexScraper(), nil
|
||||||
}
|
}
|
||||||
|
|
@ -83,6 +87,10 @@ func newAmexScraper() scraper {
|
||||||
return &amexScraper{}
|
return &amexScraper{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func newPlumasScraper() scraper {
|
||||||
|
return &plumasScraper{}
|
||||||
|
}
|
||||||
|
|
||||||
func containsAny(a string, b ...string) bool {
|
func containsAny(a string, b ...string) bool {
|
||||||
for i := range b {
|
for i := range b {
|
||||||
if strings.Contains(a, b[i]) {
|
if strings.Contains(a, b[i]) {
|
||||||
|
|
@ -531,6 +539,56 @@ func (c *bankOfAmericaScraper) scrapePayment(m *mail.Message) ([]*Transaction, e
|
||||||
return []*Transaction{transaction}, nil
|
return []*Transaction{transaction}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *plumasScraper) scrape(m *mail.Message) ([]*Transaction, error) {
|
||||||
|
b, err := ioutil.ReadAll(m.Body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if bytes.Contains(b, []byte(`alance alert`)) {
|
||||||
|
return c.scrapeBalance(m, b)
|
||||||
|
}
|
||||||
|
regexp := regexp.MustCompile(`\$([0-9]+,?)+\.[0-9][0-9]`)
|
||||||
|
match := regexp.Find(b)
|
||||||
|
if len(match) == 0 {
|
||||||
|
return nil, fmt.Errorf("no matches found")
|
||||||
|
}
|
||||||
|
match = match[1:]
|
||||||
|
match = bytes.ReplaceAll(match, []byte(","), []byte{})
|
||||||
|
f, err := strconv.ParseFloat(string(match), 10)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if !bytes.Contains(b, []byte("credit")) {
|
||||||
|
f *= -1.0
|
||||||
|
}
|
||||||
|
transaction := NewTransaction(Plumas.String(), fmt.Sprintf("%.2f", f), "?", fmt.Sprint(m.Header["Date"]), Plumas)
|
||||||
|
return []*Transaction{transaction}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *plumasScraper) scrapeBalance(m *mail.Message, b []byte) ([]*Transaction, error) {
|
||||||
|
re := regexp.MustCompile(`is \$([0-9]+,?)+\.[0-9][0-9]`)
|
||||||
|
match := re.Find(b)
|
||||||
|
if len(match) == 0 {
|
||||||
|
return nil, fmt.Errorf("no matches found")
|
||||||
|
}
|
||||||
|
match = match[4:]
|
||||||
|
match = bytes.ReplaceAll(match, []byte(","), []byte{})
|
||||||
|
f, err := strconv.ParseFloat(string(match), 10)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
acc := Plumas.String()
|
||||||
|
re = regexp.MustCompile(`ending in [0-9]*`)
|
||||||
|
match = re.Find(b)
|
||||||
|
if len(match) > 0 {
|
||||||
|
acc = fmt.Sprintf("%s-%s", acc, match[len(`ending in `):])
|
||||||
|
}
|
||||||
|
|
||||||
|
transaction := NewTransaction(acc, fmt.Sprintf("=%.2f", f), "*", fmt.Sprint(m.Header["Date"]), Plumas)
|
||||||
|
return []*Transaction{transaction}, nil
|
||||||
|
}
|
||||||
|
|
||||||
func findSubstringBetween(b []byte, prefix, suffix string) (string, bool) {
|
func findSubstringBetween(b []byte, prefix, suffix string) (string, bool) {
|
||||||
byPre := bytes.Split(b, []byte(prefix))
|
byPre := bytes.Split(b, []byte(prefix))
|
||||||
if len(byPre) < 2 {
|
if len(byPre) < 2 {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue