mirror of
https://github.com/aclindsa/ofxgo.git
synced 2024-11-14 17:20:04 -05:00
Aaron Lindsay
d8491bed1d
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.
169 lines
4.3 KiB
Go
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
|
|
}
|