Updated config file and config struct
All checks were successful
Golan Testing / testing (1.24.x, ubuntu-latest) (push) Successful in 23s
All checks were successful
Golan Testing / testing (1.24.x, ubuntu-latest) (push) Successful in 23s
This commit is contained in:
395
client.go
395
client.go
@ -13,19 +13,9 @@ import (
|
||||
"resty.dev/v3"
|
||||
)
|
||||
|
||||
// credentials .
|
||||
type credentials struct {
|
||||
username string
|
||||
password string
|
||||
pin string
|
||||
deviceId string
|
||||
deviceName string
|
||||
}
|
||||
|
||||
// Client .
|
||||
type Client struct {
|
||||
baseURL string
|
||||
credentials credentials
|
||||
credentials config.Credentials
|
||||
httpClient *resty.Client
|
||||
country string // USA | CA
|
||||
updateInterval int // 7200
|
||||
@ -38,125 +28,14 @@ type Client struct {
|
||||
sync.RWMutex
|
||||
}
|
||||
|
||||
// Option .
|
||||
type Option func(*Client) error
|
||||
|
||||
// BaseURL allows overriding of API client baseURL for testing
|
||||
func BaseURL(baseURL string) Option {
|
||||
return func(c *Client) error {
|
||||
c.baseURL = baseURL
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// Username .
|
||||
func Username(username string) Option {
|
||||
return func(c *Client) error {
|
||||
c.credentials.username = username
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// Password .
|
||||
func Password(password string) Option {
|
||||
return func(c *Client) error {
|
||||
c.credentials.password = password
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// auth .
|
||||
func (c *Client) auth() []byte {
|
||||
// {
|
||||
// "success": true,
|
||||
// "errorCode": null,
|
||||
// "dataName": "sessionData",
|
||||
// "data": {
|
||||
// "sessionChanged": false,
|
||||
// "vehicleInactivated": false,
|
||||
// "account": {
|
||||
// "marketId": 1,
|
||||
// "createdDate": 1476984644000,
|
||||
// "firstName": "Tatiana",
|
||||
// "lastName": "Savin",
|
||||
// "zipCode": "07974",
|
||||
// "accountKey": 765268,
|
||||
// "lastLoginDate": 1640539132000,
|
||||
// "zipCode5": "07974"
|
||||
// },
|
||||
// "resetPassword": false,
|
||||
// "deviceId": "JddMBQXvAkgutSmEP6uFsThbq4QgEBBQ",
|
||||
// "sessionId": "010A2C0C25A5D35AC3776DB6B7900A3B",
|
||||
// "deviceRegistered": true,
|
||||
// "passwordToken": null,
|
||||
// "vehicles": [
|
||||
// {
|
||||
// "customer": {
|
||||
// "sessionCustomer": null,
|
||||
// "email": null,
|
||||
// "firstName": null,
|
||||
// "lastName": null,
|
||||
// "zip": null,
|
||||
// "oemCustId": null,
|
||||
// "phone": null
|
||||
// },
|
||||
// "stolenVehicle": false,
|
||||
// "vehicleName": "Subaru Outback LXT",
|
||||
// "features": null,
|
||||
// "vin": "4S4BTGND8L3137058",
|
||||
// "modelYear": null,
|
||||
// "modelCode": null,
|
||||
// "engineSize": null,
|
||||
// "nickname": "Subaru Outback LXT",
|
||||
// "vehicleKey": 3832950,
|
||||
// "active": true,
|
||||
// "licensePlate": "",
|
||||
// "licensePlateState": "",
|
||||
// "email": null,
|
||||
// "firstName": null,
|
||||
// "lastName": null,
|
||||
// "subscriptionFeatures": null,
|
||||
// "accessLevel": -1,
|
||||
// "zip": null,
|
||||
// "oemCustId": "CRM-631-HQN48K",
|
||||
// "vehicleMileage": null,
|
||||
// "phone": null,
|
||||
// "userOemCustId": "CRM-631-HQN48K",
|
||||
// "subscriptionStatus": null,
|
||||
// "authorizedVehicle": false,
|
||||
// "preferredDealer": null,
|
||||
// "cachedStateCode": "NJ",
|
||||
// "subscriptionPlans": [],
|
||||
// "needMileagePrompt": false,
|
||||
// "phev": null,
|
||||
// "remoteServicePinExist": true,
|
||||
// "needEmergencyContactPrompt": false,
|
||||
// "vehicleGeoPosition": null,
|
||||
// "extDescrip": null,
|
||||
// "intDescrip": null,
|
||||
// "modelName": null,
|
||||
// "transCode": null,
|
||||
// "provisioned": true,
|
||||
// "timeZone": "America/New_York"
|
||||
// }
|
||||
// ],
|
||||
// "currentVehicleIndex": 0,
|
||||
// "handoffToken": "$2a$08$99me3RRpB00MNMSFxrG7AOg1T5BaDVacqXhbdTii0eRXoEoeFvEPy$1640540934344",
|
||||
// "enableXtime": true,
|
||||
// "termsAndConditionsAccepted": true,
|
||||
// "digitalGlobeConnectId": "0572e32b-2fcf-4bc8-abe0-1e3da8767132",
|
||||
// "digitalGlobeImageTileService": "https://earthwatch.digitalglobe.com/earthservice/tmsaccess/tms/1.0.0/DigitalGlobe:ImageryTileService@EPSG:3857@png/{z}/{x}/{y}.png?connectId=0572e32b-2fcf-4bc8-abe0-1e3da8767132",
|
||||
// "digitalGlobeTransparentTileService": "https://earthwatch.digitalglobe.com/earthservice/tmsaccess/tms/1.0.0/Digitalglobe:OSMTransparentTMSTileService@EPSG:3857@png/{z}/{x}/{-y}.png/?connectId=0572e32b-2fcf-4bc8-abe0-1e3da8767132",
|
||||
// "tomtomKey": "DHH9SwEQ4MW55Hj2TfqMeldbsDjTdgAs",
|
||||
// "satelliteViewEnabled": true
|
||||
// }
|
||||
// }
|
||||
params := map[string]string{
|
||||
"env": "cloudprod",
|
||||
"deviceType": "android",
|
||||
"loginUsername": c.credentials.username,
|
||||
"password": c.credentials.password,
|
||||
"deviceId": c.credentials.deviceId,
|
||||
"loginUsername": c.credentials.Username,
|
||||
"password": c.credentials.Password,
|
||||
"deviceId": c.credentials.DeviceID,
|
||||
"passwordToken": "",
|
||||
"selectedVin": "",
|
||||
"pushToken": ""}
|
||||
@ -195,9 +74,9 @@ func (c *Client) registerDevice() bool {
|
||||
// }).
|
||||
// Post(apiURLs["WEB_API_LOGIN"])
|
||||
params := map[string]string{
|
||||
"username": c.credentials.username,
|
||||
"password": c.credentials.password,
|
||||
"deviceId": c.credentials.deviceId}
|
||||
"username": c.credentials.Username,
|
||||
"password": c.credentials.Password,
|
||||
"deviceId": c.credentials.DeviceID}
|
||||
reqURL := WEB_API_SERVER[c.country] + apiURLs["WEB_API_LOGIN"]
|
||||
c.execute(reqURL, POST, params, "", true)
|
||||
|
||||
@ -210,7 +89,7 @@ func (c *Client) registerDevice() bool {
|
||||
// }).
|
||||
// Get(apiURLs["WEB_API_AUTHORIZE_DEVICE"])
|
||||
params = map[string]string{
|
||||
"deviceId": c.credentials.deviceId}
|
||||
"deviceId": c.credentials.DeviceID}
|
||||
reqURL = WEB_API_SERVER[c.country] + apiURLs["WEB_API_AUTHORIZE_DEVICE"]
|
||||
c.execute(reqURL, GET, params, "", false)
|
||||
|
||||
@ -220,8 +99,8 @@ func (c *Client) registerDevice() bool {
|
||||
// setDeviceName .
|
||||
func (c *Client) setDeviceName() bool {
|
||||
params := map[string]string{
|
||||
"deviceId": c.credentials.deviceId,
|
||||
"deviceName": c.credentials.deviceName}
|
||||
"deviceId": c.credentials.DeviceID,
|
||||
"deviceName": c.credentials.DeviceName}
|
||||
reqURL := WEB_API_SERVER[c.country] + apiURLs["WEB_API_NAME_DEVICE"]
|
||||
c.execute(reqURL, GET, params, "", false)
|
||||
|
||||
@ -315,111 +194,76 @@ func (c *Client) validateSession() bool {
|
||||
// if await self._select_vehicle(vin):
|
||||
// result = True
|
||||
|
||||
c.log.Debug("[DEBUG] Validate Session", "body", string([]byte(resp)))
|
||||
c.log.Debug("session validation", "body", string([]byte(resp)))
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (c *Client) SelectVehicle(vin string) VehicleData {
|
||||
// {
|
||||
// "success": true,
|
||||
// "errorCode": null,
|
||||
// "dataName": "vehicle",
|
||||
// "data": {
|
||||
// "customer": {
|
||||
// "sessionCustomer": null,
|
||||
// "email": null,
|
||||
// "firstName": null,
|
||||
// "lastName": null,
|
||||
// "zip": null,
|
||||
// "oemCustId": null,
|
||||
// "phone": null
|
||||
// },
|
||||
// "stolenVehicle": false,
|
||||
// "vehicleName": "Subaru Outback LXT",
|
||||
// "features": [
|
||||
// "ATF_MIL",
|
||||
// "11.6MMAN",
|
||||
// "ABS_MIL",
|
||||
// "CEL_MIL",
|
||||
// "ACCS",
|
||||
// "RCC",
|
||||
// "REARBRK",
|
||||
// "TEL_MIL",
|
||||
// "VDC_MIL",
|
||||
// "TPMS_MIL",
|
||||
// "WASH_MIL",
|
||||
// "BSDRCT_MIL",
|
||||
// "OPL_MIL",
|
||||
// "EYESIGHT",
|
||||
// "RAB_MIL",
|
||||
// "SRS_MIL",
|
||||
// "ESS_MIL",
|
||||
// "RESCC",
|
||||
// "EOL_MIL",
|
||||
// "BSD",
|
||||
// "EBD_MIL",
|
||||
// "EPB_MIL",
|
||||
// "RES",
|
||||
// "RHSF",
|
||||
// "AWD_MIL",
|
||||
// "NAV_TOMTOM",
|
||||
// "ISS_MIL",
|
||||
// "RPOIA",
|
||||
// "EPAS_MIL",
|
||||
// "RPOI",
|
||||
// "AHBL_MIL",
|
||||
// "SRH_MIL",
|
||||
// "g2"
|
||||
// ],
|
||||
// "vin": "4S4BTGND8L3137058",
|
||||
// "modelYear": "2020",
|
||||
// "modelCode": "LDJ",
|
||||
// "engineSize": 2.4,
|
||||
// "nickname": "Subaru Outback LXT",
|
||||
// "vehicleKey": 3832950,
|
||||
// "active": true,
|
||||
// "licensePlate": "8KV8",
|
||||
// "licensePlateState": "NJ",
|
||||
// "email": null,
|
||||
// "firstName": null,
|
||||
// "lastName": null,
|
||||
// "subscriptionFeatures": [
|
||||
// "REMOTE",
|
||||
// "SAFETY",
|
||||
// "Retail"
|
||||
// ],
|
||||
// "accessLevel": -1,
|
||||
// "zip": null,
|
||||
// "oemCustId": "CRM-631-HQN48K",
|
||||
// "vehicleMileage": null,
|
||||
// "phone": null,
|
||||
// "userOemCustId": "CRM-631-HQN48K",
|
||||
// "subscriptionStatus": "ACTIVE",
|
||||
// "authorizedVehicle": false,
|
||||
// "preferredDealer": null,
|
||||
// "cachedStateCode": "NJ",
|
||||
// "subscriptionPlans": [],
|
||||
// "needMileagePrompt": false,
|
||||
// "phev": null,
|
||||
// "remoteServicePinExist": true,
|
||||
// "needEmergencyContactPrompt": false,
|
||||
// "vehicleGeoPosition": {
|
||||
// "latitude": 40.70019,
|
||||
// "longitude": -74.401375,
|
||||
// "speed": null,
|
||||
// "heading": null,
|
||||
// "timestamp": 1640494569000
|
||||
// },
|
||||
// "extDescrip": "Abyss Blue Pearl",
|
||||
// "intDescrip": "Gray",
|
||||
// "modelName": "Outback",
|
||||
// "transCode": "CVT",
|
||||
// "provisioned": true,
|
||||
// "timeZone": "America/New_York"
|
||||
// }
|
||||
// }
|
||||
// New function creates a New MySubaru client
|
||||
func New(logger *slog.Logger, config *config.MySubaru) (*Client, error) {
|
||||
|
||||
client := &Client{
|
||||
credentials: config.Credentials,
|
||||
country: config.Region,
|
||||
updateInterval: 7200,
|
||||
fetchInterval: 360,
|
||||
log: logger,
|
||||
}
|
||||
|
||||
httpClient := resty.New()
|
||||
httpClient.
|
||||
SetBaseURL(MOBILE_API_SERVER[client.country]).
|
||||
SetHeaders(map[string]string{
|
||||
"User-Agent": "Mozilla/5.0 (Linux; Android 10; Android SDK built for x86 Build/QSR1.191030.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/74.0.3729.185 Mobile Safari/537.36",
|
||||
"Origin": "file://",
|
||||
"X-Requested-With": MOBILE_APP[client.country],
|
||||
"Accept-Language": "en-US,en;q=0.9",
|
||||
"Accept-Encoding": "gzip, deflate",
|
||||
"Accept": "*/*"})
|
||||
|
||||
client.httpClient = httpClient
|
||||
|
||||
resp := client.auth()
|
||||
respParsed, err := gabs.ParseJSON(resp)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if client.isResponseSuccessfull(resp) {
|
||||
logger.Debug("Client authentication successful", "isRegistered", respParsed.Path("data.deviceRegistered").Data().(bool))
|
||||
client.isAuthenticated = true
|
||||
client.isRegistered = respParsed.Path("data.deviceRegistered").Data().(bool)
|
||||
} else {
|
||||
error, _ := respParsed.Path("errorCode").Data().(string)
|
||||
switch {
|
||||
case error == apiErrors["ERROR_INVALID_ACCOUNT"]:
|
||||
logger.Debug("Invalid account")
|
||||
case error == apiErrors["ERROR_INVALID_CREDENTIALS"]:
|
||||
logger.Debug("Client authentication failed")
|
||||
case error == apiErrors["ERROR_PASSWORD_WARNING"]:
|
||||
logger.Debug("Multiple Password Failures.")
|
||||
default:
|
||||
logger.Debug("Uknown error")
|
||||
}
|
||||
}
|
||||
|
||||
if !client.isRegistered {
|
||||
client.registerDevice()
|
||||
}
|
||||
|
||||
// TODO
|
||||
fmt.Printf("Parcing cars: %d\n", len(respParsed.Path("data.vehicles").Children()))
|
||||
for _, vehicle := range respParsed.Path("data.vehicles").Children() {
|
||||
fmt.Printf("CAR: %s\n", vehicle.Path("vin").Data().(string))
|
||||
client.listOfVins = append(client.listOfVins, vehicle.Path("vin").Data().(string))
|
||||
}
|
||||
client.currentVin = respParsed.Path("data.vehicles.0.vin").Data().(string)
|
||||
|
||||
return client, nil
|
||||
}
|
||||
|
||||
func (c *Client) SelectVehicle(vin string) VehicleData {
|
||||
// API > json > dataName > vehicle
|
||||
if vin == "" {
|
||||
vin = c.currentVin
|
||||
}
|
||||
@ -467,78 +311,6 @@ func (c *Client) SelectVehicle(vin string) VehicleData {
|
||||
return vData
|
||||
}
|
||||
|
||||
// New function creates a New MySubaru client
|
||||
func New(logger *slog.Logger, config *config.MySubaru) (*Client, error) {
|
||||
|
||||
credentials := credentials{
|
||||
username: config.Credentials.Username,
|
||||
password: config.Credentials.Password,
|
||||
pin: config.Credentials.PIN,
|
||||
deviceId: config.Credentials.DeviceID,
|
||||
deviceName: config.Credentials.DeviceName,
|
||||
}
|
||||
|
||||
client := &Client{
|
||||
credentials: credentials,
|
||||
country: config.Region,
|
||||
updateInterval: 7200,
|
||||
fetchInterval: 360,
|
||||
log: logger,
|
||||
}
|
||||
|
||||
httpClient := resty.New()
|
||||
httpClient.
|
||||
SetBaseURL(MOBILE_API_SERVER[client.country]).
|
||||
SetHeaders(map[string]string{
|
||||
"User-Agent": "Mozilla/5.0 (Linux; Android 10; Android SDK built for x86 Build/QSR1.191030.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/74.0.3729.185 Mobile Safari/537.36",
|
||||
"Origin": "file://",
|
||||
"X-Requested-With": MOBILE_APP[client.country],
|
||||
"Accept-Language": "en-US,en;q=0.9",
|
||||
"Accept-Encoding": "gzip, deflate",
|
||||
"Accept": "*/*"})
|
||||
|
||||
client.httpClient = httpClient
|
||||
|
||||
resp := client.auth()
|
||||
|
||||
respParsed, err := gabs.ParseJSON(resp)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if client.isResponseSuccessfull(resp) {
|
||||
logger.Debug("Client authentication successful", "isRegistered", respParsed.Path("data.deviceRegistered").Data().(bool))
|
||||
client.isAuthenticated = true
|
||||
client.isRegistered = respParsed.Path("data.deviceRegistered").Data().(bool)
|
||||
} else {
|
||||
error, _ := respParsed.Path("errorCode").Data().(string)
|
||||
switch {
|
||||
case error == apiErrors["ERROR_INVALID_ACCOUNT"]:
|
||||
logger.Debug("Invalid account")
|
||||
case error == apiErrors["ERROR_INVALID_CREDENTIALS"]:
|
||||
logger.Debug("Client authentication failed")
|
||||
case error == apiErrors["ERROR_PASSWORD_WARNING"]:
|
||||
logger.Debug("Multiple Password Failures.")
|
||||
default:
|
||||
logger.Debug("Uknown error")
|
||||
}
|
||||
}
|
||||
|
||||
if !client.isRegistered {
|
||||
client.registerDevice()
|
||||
}
|
||||
|
||||
// TODO
|
||||
fmt.Printf("Parcing cars: %d\n", len(respParsed.Path("data.vehicles").Children()))
|
||||
for _, vehicle := range respParsed.Path("data.vehicles").Children() {
|
||||
fmt.Printf("CAR: %s\n", vehicle.Path("vin").Data().(string))
|
||||
client.listOfVins = append(client.listOfVins, vehicle.Path("vin").Data().(string))
|
||||
}
|
||||
client.currentVin = respParsed.Path("data.vehicles.0.vin").Data().(string)
|
||||
|
||||
return client, nil
|
||||
}
|
||||
|
||||
// GetVehicles .
|
||||
func (c *Client) GetVehicles() []*Vehicle {
|
||||
var vehicles []*Vehicle
|
||||
@ -551,7 +323,7 @@ func (c *Client) GetVehicles() []*Vehicle {
|
||||
|
||||
respParsed, err := gabs.ParseJSON([]byte(resp))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
c.log.Error("error which parsing json", "request", "GetVehicles", "error", err.Error())
|
||||
}
|
||||
|
||||
vData := VehicleData{}
|
||||
@ -603,7 +375,7 @@ func (c *Client) GetVehicleByVIN(vin string) *Vehicle {
|
||||
|
||||
respParsed, err := gabs.ParseJSON([]byte(resp))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
c.log.Error("error which parsing json", "request", "GetVehicleByVIN", "error", err.Error())
|
||||
}
|
||||
|
||||
vData := VehicleData{}
|
||||
@ -682,7 +454,7 @@ func (c *Client) GetVehicleStatus() {
|
||||
|
||||
respParsed, err := gabs.ParseJSON(resp)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
c.log.Error("error which parsing json", "request", "GetVehicleStatus", "error", err.Error())
|
||||
}
|
||||
c.log.Debug("GET VEHICLE STATUS OUTPUT", "body", respParsed)
|
||||
|
||||
@ -718,7 +490,7 @@ func (c *Client) GetClimateSettings() {
|
||||
|
||||
respParsed, err := gabs.ParseJSON(resp)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
c.log.Error("error which parsing json", "request", "GetClimateSettings", "error", err.Error())
|
||||
}
|
||||
c.log.Debug("CLIMATE SETTINGS OUTPUT", "response", respParsed)
|
||||
|
||||
@ -755,12 +527,8 @@ func (c *Client) GetClimateSettings() {
|
||||
func (c *Client) execute(requestUrl string, method string, params map[string]string, pollingUrl string, json bool) []byte {
|
||||
defer timeTrack("[TIMETRK] Executing Get Request")
|
||||
|
||||
// if !isNil(resp.Cookies()) {
|
||||
// log.Debugf("AUTH COOKIES OUTPUT >> %v\n", resp.Cookies())
|
||||
// c.cookies = resp.Cookies()
|
||||
// }
|
||||
|
||||
var resp *resty.Response
|
||||
|
||||
// GET Requests
|
||||
if method == "GET" {
|
||||
resp, _ = c.httpClient.
|
||||
@ -791,9 +559,8 @@ func (c *Client) execute(requestUrl string, method string, params map[string]str
|
||||
// }
|
||||
respParsed, err := gabs.ParseJSON(resBytes)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
c.log.Error("error which parsing json", "request", "execute", "method", method, "url", requestUrl, "error", err.Error())
|
||||
}
|
||||
|
||||
c.log.Debug("HTTP OUTPUT", "body", string(resBytes))
|
||||
|
||||
_, ok := respParsed.Path("success").Data().(bool)
|
||||
|
Reference in New Issue
Block a user