1
0
mirror of https://github.com/aclindsa/ofxgo.git synced 2024-11-14 17:20:04 -05:00
ofxgo/cmd/ofx/detect_settings.go
Aaron Lindsay d8491bed1d Make Client an interface instead of a struct
This makes it easier to maintain per-institution hacks that start
interacting with each other if you try to do them all in the same client
code. This commit also breaks out the existing Vanguard hack into its
own Client implementation.
2018-10-03 10:18:54 -04:00

169 lines
4.3 KiB
Go

package main
import (
"flag"
"fmt"
"github.com/aclindsa/ofxgo"
"os"
"time"
)
var detectSettingsCommand = command{
Name: "detect-settings",
Description: "Attempt to guess client settings needed for a particular financial institution",
Flags: flag.NewFlagSet("detect-settings", flag.ExitOnError),
CheckFlags: checkServerFlags,
Do: detectSettings,
}
var delay uint64
func init() {
detectSettingsCommand.Flags.StringVar(&serverURL, "url", "", "Financial institution's OFX Server URL (see ofxhome.com if you don't know it)")
detectSettingsCommand.Flags.StringVar(&username, "username", "", "Your username at financial institution")
detectSettingsCommand.Flags.StringVar(&password, "password", "", "Your password at financial institution")
detectSettingsCommand.Flags.StringVar(&org, "org", "", "'ORG' for your financial institution")
detectSettingsCommand.Flags.StringVar(&fid, "fid", "", "'FID' for your financial institution")
detectSettingsCommand.Flags.Uint64Var(&delay, "delay", 500, "How long to delay between two subsequent requests, in milliseconds")
}
// We keep a separate list of APPIDs to preserve the ordering (ordering isn't
// guaranteed in maps). We want to try them in order from 'best' and most
// likely to work to 'worse' and least likely to work
var appIDs = []string{
"OFXGO", // ofxgo (this library)
"QWIN", // Intuit Quicken Windows
"QMOFX", // Intuit Quicken Mac
"QB", // Intuit QuickBooks Windows
"Money", // Microsoft Money 2007
}
var appVersions = map[string][]string{
"OFXGO": { // ofxgo (this library)
"0001",
},
"QWIN": { // Intuit Quicken Windows
"2400", // 2015
"2300", // 2014
"2200", // 2013
"2100", // 2012
"2000", // 2011
"1900", // 2010
"1800", // 2009
"1700", // 2008
"1600", // 2007
"1500", // 2006
"1400", // 2005
},
"QMOFX": { // Intuit Quicken Mac
"1700", // 2008
"1600", // 2007
"1500", // 2006
"1400", // 2005
},
"QB": { // Intuit QuickBooks Windows
"1800", // 2008
"1700", // 2007
"1600", // 2006
"1500", // 2005
},
"Money": { // Microsoft Money 2007
"1600", // 2007
"1500", // 2006
"1400", // 2005
"1200", // 2004
"1100", // 2003
},
}
var versions = []string{
"203",
"103",
"200",
"201",
"202",
"210",
"211",
"102",
"151",
"160",
"220",
}
func detectSettings() {
var attempts uint
for _, appID := range appIDs {
for _, appVer := range appVersions[appID] {
for _, version := range versions {
for _, noIndent := range []bool{false, true} {
if tryProfile(appID, appVer, version, noIndent) {
fmt.Println("The following settings were found to work:")
fmt.Printf("AppID: %s\n", appID)
fmt.Printf("AppVer: %s\n", appVer)
fmt.Printf("OFX Version: %s\n", version)
fmt.Printf("noindent: %t\n", noIndent)
os.Exit(0)
} else {
attempts++
var noIndentString string
if noIndent {
noIndentString = " noindent"
}
fmt.Printf("Attempt %d failed (%s %s %s%s), trying again after %dms...\n", attempts, appID, appVer, version, noIndentString, delay)
time.Sleep(time.Duration(delay) * time.Millisecond)
}
}
}
}
}
}
const anonymous = "anonymous00000000000000000000000"
func tryProfile(appID, appVer, version string, noindent bool) bool {
ver, err := ofxgo.NewOfxVersion(version)
if err != nil {
fmt.Println("Error creating new OfxVersion enum:", err)
os.Exit(1)
}
var client = ofxgo.GetClient(serverURL,
&ofxgo.BasicClient{
AppID: appID,
AppVer: appVer,
SpecVersion: ver,
NoIndent: noindent,
})
var query ofxgo.Request
query.URL = serverURL
query.Signon.ClientUID = ofxgo.UID(clientUID)
query.Signon.UserID = ofxgo.String(username)
query.Signon.UserPass = ofxgo.String(password)
query.Signon.Org = ofxgo.String(org)
query.Signon.Fid = ofxgo.String(fid)
uid, err := ofxgo.RandomUID()
if err != nil {
fmt.Println("Error creating uid for transaction:", err)
os.Exit(1)
}
profileRequest := ofxgo.ProfileRequest{
TrnUID: *uid,
DtProfUp: ofxgo.Date{Time: time.Unix(0, 0)},
}
query.Prof = append(query.Prof, &profileRequest)
_, err = client.Request(&query)
if err == nil {
return true
}
// try again with anonymous logins
query.Signon.UserID = ofxgo.String(anonymous)
query.Signon.UserPass = ofxgo.String(anonymous)
_, err = client.Request(&query)
return err == nil
}