More changes
All checks were successful
Golan Testing / testing (1.24.x, ubuntu-latest) (push) Successful in 27s

This commit is contained in:
2025-06-01 15:30:08 -04:00
parent cec922f363
commit 2f86d769fc
3 changed files with 448 additions and 482 deletions

811
client.go
View File

@ -27,6 +27,370 @@ type Client struct {
sync.RWMutex
}
// New function creates a New MySubaru client
func New(config *config.Config) (*Client, error) {
client := &Client{
credentials: config.MySubaru.Credentials,
country: config.MySubaru.Region,
updateInterval: 7200,
fetchInterval: 360,
logger: config.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()
if r, ok := client.parseResponse(resp); ok {
var sd SessionData
err := json.Unmarshal(r.Data, &sd)
if err != nil {
client.logger.Error("error while parsing json", "request", "auth", "error", err.Error())
}
// client.logger.Debug("unmarshaled json data", "request", "auth", "type", "sessionData", "body", sd)
if sd.DeviceRegistered && sd.RegisteredDevicePermanent {
client.logger.Debug("client authentication successful")
client.isAuthenticated = true
client.isRegistered = true
} else {
client.logger.Debug("client authentication successful, but devices is not registered")
client.registerDevice()
}
// client.logger.Debug("parsing cars assigned to the account", "quantity", len(sd.Vehicles))
if len(sd.Vehicles) > 0 {
for _, vehicle := range sd.Vehicles {
// client.logger.Debug("parsing car", "vin", vehicle.Vin)
client.listOfVins = append(client.listOfVins, vehicle.Vin)
}
client.currentVin = client.listOfVins[0]
} else {
client.logger.Error("there no cars assigned to the account")
return nil, err
}
} else {
// TODO: Work on errors
// error, _ := respParsed.Path("errorCode").Data().(string)
// switch {
// case error == apiErrors["ERROR_INVALID_ACCOUNT"]:
// client.logger.Debug("Invalid account")
// case error == apiErrors["ERROR_INVALID_CREDENTIALS"]:
// client.logger.Debug("Client authentication failed")
// case error == apiErrors["ERROR_PASSWORD_WARNING"]:
// client.logger.Debug("Multiple Password Failures.")
// default:
// client.logger.Debug("Uknown error")
// }
client.logger.Error("request was not successfull", "request", "auth")
// TODO: Work on providing error
return nil, nil
}
return client, nil
}
// SelectVehicle .
func (c *Client) SelectVehicle(vin string) VehicleData {
// API > json > dataName > vehicle
if vin == "" {
vin = c.currentVin
}
vinCheck(vin)
params := map[string]string{
"vin": vin,
"_": timestamp()}
reqURL := MOBILE_API_VERSION + apiURLs["API_SELECT_VEHICLE"]
resp := c.execute(reqURL, GET, params, "", false)
// c.logger.Debug("http request output", "request", "SelectVehicle", "body", resp)
if r, ok := c.parseResponse(resp); ok {
var vd VehicleData
err := json.Unmarshal(r.Data, &vd)
if err != nil {
c.logger.Error("error while parsing json", "request", "GetClimatePresets", "error", err.Error())
}
// c.logger.Debug("http request output", "request", "GetVehicleStatus", "body", resp)
return vd
} else {
return VehicleData{}
}
// resp := c.execute(reqURL, GET, params, "", false)
// logger.Debugf("SELECT VEHICLE OUTPUT >> %v\n", string([]byte(resp)))
// ERRORS
// {"success":false,"errorCode":"vehicleNotInAccount","dataName":null,"data":null}
// """Select active vehicle for accounts with multiple VINs."""
// params = {"vin": vin, "_": int(time.time())}
// js_resp = await self.get(API_SELECT_VEHICLE, params=params)
// _LOGGER.debug(pprint.pformat(js_resp))
// if js_resp.get("success"):
// self._current_vin = vin
// _LOGGER.debug("Current vehicle: vin=%s", js_resp["data"]["vin"])
// return js_resp["data"]
// if not js_resp.get("success") and js_resp.get("errorCode") == "VEHICLESETUPERROR":
// # Occasionally happens every few hours. Resetting the session seems to deal with it.
// _LOGGER.warning("VEHICLESETUPERROR received. Resetting session.")
// self.reset_session()
// return False
// _LOGGER.debug("Failed to switch vehicle errorCode=%s", js_resp.get("errorCode"))
// # Something else is probably wrong with the backend server context - try resetting
// self.reset_session()
// raise SubaruException("Failed to switch vehicle %s - resetting session." % js_resp.get("errorCode"))
}
// GetVehicles .
func (c *Client) GetVehicles() []*Vehicle {
var vehicles []*Vehicle
for _, vin := range c.listOfVins {
vehicle := c.GetVehicleByVIN(vin)
vehicles = append(vehicles, vehicle)
}
return vehicles
}
// GetVehicleByVIN .
func (c *Client) GetVehicleByVIN(vin string) *Vehicle {
var vehicle *Vehicle
if contains(c.listOfVins, vin) {
params := map[string]string{
"vin": vin,
"_": timestamp()}
reqURL := MOBILE_API_VERSION + apiURLs["API_SELECT_VEHICLE"]
resp := c.execute(reqURL, GET, params, "", false)
// c.logger.Debug("http request output", "request", "GetVehicleByVIN", "body", resp)
if r, ok := c.parseResponse(resp); ok {
var vd VehicleData
err := json.Unmarshal(r.Data, &vd)
if err != nil {
c.logger.Error("error while parsing json", "request", "GetVehicleByVIN", "error", err.Error())
}
// c.logger.Debug("http request output", "request", "GetVehicleByVIN", "body", resp)
vehicle = &Vehicle{
Vin: vin,
CarName: vd.VehicleName,
CarNickname: vd.Nickname,
ModelName: vd.ModelName,
ModelYear: vd.ModelYear,
ModelCode: vd.ModelCode,
ExtDescrip: vd.ExtDescrip,
IntDescrip: vd.IntDescrip,
TransCode: vd.TransCode,
EngineSize: vd.EngineSize,
VehicleKey: vd.VehicleKey,
LicensePlate: vd.LicensePlate,
LicensePlateState: vd.LicensePlateState,
Features: vd.Features,
SubscriptionFeatures: vd.SubscriptionFeatures,
client: c,
}
vehicle.Doors = make(map[string]Door)
vehicle.Windows = make(map[string]Window)
vehicle.Tires = make(map[string]Tire)
vehicle.ClimateProfiles = make(map[string]ClimateProfile)
vehicle.GetVehicleStatus()
vehicle.GetVehicleCondition()
vehicle.GetVehicleHealth()
vehicle.GetClimatePresets()
vehicle.GetClimateUserPresets()
vehicle.GetClimateQuickPresets()
return vehicle
}
}
c.logger.Error("error while parsing json", "request", "GetVehicleByVIN")
return &Vehicle{}
}
// func isPINRequired() {}
// func getVehicles() {}
// func getEVStatus() {}
// func getRemoteOptionsStatus() {}
// func getRemoteStartStatus() {}
// func getSafetyStatus() {}
// func getSubscriptionStatus() {}
// func getAPIGen() {}
// func getClimateData() {}
// func saveClimateSettings() {}
// func getVehicleName() {}
// func fetch() {}
// Exec method executes a Client instance with the API URL
func (c *Client) execute(requestUrl string, method string, params map[string]string, pollingUrl string, j bool) []byte {
defer timeTrack("[TIMETRK] Executing Get Request")
var resp *resty.Response
// GET Requests
if method == "GET" {
resp, _ = c.httpClient.
R().
SetQueryParams(params).
Get(requestUrl)
}
// POST Requests
if method == "POST" {
if j {
// POST > JSON Body
resp, _ = c.httpClient.
R().
SetBody(params).
Post(requestUrl)
} else {
// POST > Form Data
resp, _ = c.httpClient.
R().
SetFormData(params).
Post(requestUrl)
}
}
resBytes, err := io.ReadAll(resp.Body)
if err != nil {
c.logger.Error("error while getting body", "error", err.Error())
}
var r Response
err = json.Unmarshal(resBytes, &r)
if err != nil {
c.logger.Error("error while parsing json", "request", "execute", "method", method, "url", requestUrl, "error", err.Error())
}
c.logger.Debug("parsed http request output", "request", "HTTP POLLING", "data", r.Data)
if r.Success {
var sr ServiceRequest
err := json.Unmarshal(r.Data, &sr)
if err != nil {
c.logger.Error("error while parsing json", "request", "HTTP POLLING", "error", err.Error())
}
if pollingUrl != "" {
time.Sleep(3 * time.Second)
attempts := 20
// for {
// if attempt >= attempts {
// break
// }
// resp := c.execute(pollingUrl, GET, map[string]string{"serviceRequestId": sr.ServiceRequestID}, pollingUrl, false)
// var r Response
// err = json.Unmarshal(resp, &r)
// if err != nil {
// c.logger.Error("error while parsing json", "request", "execute", "method", method, "url", requestUrl, "error", err.Error())
// }
// c.logger.Debug("parsed http request output", "request", "HTTP POLLING", "data", r.Data)
// var sr ServiceRequest
// err := json.Unmarshal(r.Data, &sr)
// if err != nil {
// c.logger.Error("error while parsing json", "request", "HTTP POLLING", "error", err.Error())
// }
// switch {
// case sr.RemoteServiceState == "finished":
// c.logger.Debug("Remote service request completed successfully", "request id", sr.ServiceRequestID)
// break
// case sr.RemoteServiceState == "started":
// c.logger.Debug("Subaru API reports remote service request is in progress", "request id", sr.ServiceRequestID)
// }
// attempt++
// }
poolingLoop:
for attempts > 0 {
resp, _ = c.httpClient.
SetBaseURL(MOBILE_API_SERVER[c.country]).
R().
SetQueryParams(map[string]string{
"serviceRequestId": sr.ServiceRequestID,
}).
Get(pollingUrl)
resBytes, _ := io.ReadAll(resp.Body)
c.logger.Debug("POLLING HTTP OUTPUT", "body", string(resBytes))
// {"success":false,"errorCode":"404-soa-unableToParseResponseBody","dataName":"errorResponse","data":{"errorLabel":"404-soa-unableToParseResponseBody","errorDescription":null}}
var r Response
err := json.Unmarshal(resBytes, &r)
if err != nil {
c.logger.Error("error while parsing json", "request", "HTTP POLLING", "error", err.Error())
}
c.logger.Debug("parsed loop http request output", "request", "HTTP POLLING", "data", r.Data)
if r.Success {
var sr ServiceRequest
err := json.Unmarshal(r.Data, &sr)
if err != nil {
c.logger.Error("error while parsing json", "request", "HTTP POLLING", "error", err.Error())
}
switch {
case sr.RemoteServiceState == "finished":
c.logger.Debug("Remote service request completed successfully", "request id", sr.ServiceRequestID)
break poolingLoop
case sr.RemoteServiceState == "started":
c.logger.Debug("Subaru API reports remote service request is in progress", "request id", sr.ServiceRequestID)
}
} else {
c.logger.Debug("Backend session expired, please try again")
break poolingLoop
}
attempts--
time.Sleep(3 * time.Second)
}
}
} else {
c.logger.Error("request is not successfull", "request", "execute", "method", method, "url", requestUrl, "error", err.Error())
}
return resBytes
}
// // isResponseSuccessfull .
// func (c *Client) isResponseSuccessfull(resp []byte) bool {
// respParsed, err := gabs.ParseJSON(resp)
// if err != nil {
// c.logger.Debug("error while parsing json response", "error", err)
// }
// success, ok := respParsed.Path("success").Data().(bool)
// if !ok {
// c.logger.Debug("response is not successful", "error", resp)
// }
// // ERRORS FROM CLIENT CREATION AFTER AUTH
// // error, _ := respParsed.Path("errorCode").Data().(string)
// // switch {
// // case error == apiErrors["ERROR_INVALID_ACCOUNT"]:
// // fmt.Println("Invalid account")
// // case error == apiErrors["ERROR_INVALID_CREDENTIALS"]:
// // {"success":false,"errorCode":"InvalidCredentials","dataName":"remoteServiceStatus","data":{"serviceRequestId":null,"success":false,"cancelled":false,"remoteServiceType":null,"remoteServiceState":null,"subState":null,"errorCode":null,"result":null,"updateTime":null,"vin":null,"errorDescription":"The credentials supplied are invalid, tries left 2"}}
// // fmt.Println("Client authentication failed")
// // case error == apiErrors["ERROR_PASSWORD_WARNING"]:
// // fmt.Println("Multiple Password Failures.")
// // default:
// // fmt.Println("Uknown error")
// // }
// return success
// }
// auth .
func (c *Client) auth() []byte {
params := map[string]string{
@ -44,6 +408,59 @@ func (c *Client) auth() []byte {
return resp
}
// parseResponse .
func (c *Client) parseResponse(b []byte) (Response, bool) {
var r Response
err := json.Unmarshal(b, &r)
if err != nil {
c.logger.Error("error while parsing json", "error", err.Error())
}
return r, true
}
// validateSession .
func (c *Client) validateSession() bool {
// {
// "success": true,
// "errorCode": null,
// "dataName": null,
// "data": null
// }
reqURL := MOBILE_API_VERSION + apiURLs["API_VALIDATE_SESSION"]
resp := c.execute(reqURL, GET, map[string]string{}, "", false)
c.logger.Debug("http request output", "request", "validateSession", "body", resp)
var r Response
err := json.Unmarshal(resp, &r)
if err != nil {
c.logger.Error("error while parsing json", "request", "validateSession", "error", err.Error())
}
if r.Success {
return true
}
return false
// result = False
// js_resp = await self.__open(API_VALIDATE_SESSION, GET)
// _LOGGER.debug(pprint.pformat(js_resp))
// if js_resp["success"]:
// if vin != self._current_vin:
// # API call for VIN that is not the current remote context.
// _LOGGER.debug("Switching Subaru API vehicle context to: %s", vin)
// if await self._select_vehicle(vin):
// result = True
// else:
// result = True
// if result is False:
// await self._authenticate(vin)
// # New session cookie. Must call selectVehicle.json before any other API call.
// if await self._select_vehicle(vin):
// result = True
}
// GET
// https://www.mysubaru.com/profile/verifyDeviceName.json?clientId=2574212&deviceName=Alex%20Google%20Pixel%204%20XL
// RESP: true/false
@ -158,397 +575,3 @@ func (c *Client) listDevices() {
// logger.Debugf("LIST DEVICES OUTPUT >> %v\n", string(resp))
// }
}
// validateSession .
func (c *Client) validateSession() bool {
// {
// "success": true,
// "errorCode": null,
// "dataName": null,
// "data": null
// }
reqURL := MOBILE_API_VERSION + apiURLs["API_VALIDATE_SESSION"]
resp := c.execute(reqURL, GET, map[string]string{}, "", false)
c.logger.Debug("http request output", "request", "validateSession", "body", resp)
var r Response
err := json.Unmarshal(resp, &r)
if err != nil {
c.logger.Error("error while parsing json", "request", "validateSession", "error", err.Error())
}
if r.Success {
return true
}
return false
// result = False
// js_resp = await self.__open(API_VALIDATE_SESSION, GET)
// _LOGGER.debug(pprint.pformat(js_resp))
// if js_resp["success"]:
// if vin != self._current_vin:
// # API call for VIN that is not the current remote context.
// _LOGGER.debug("Switching Subaru API vehicle context to: %s", vin)
// if await self._select_vehicle(vin):
// result = True
// else:
// result = True
// if result is False:
// await self._authenticate(vin)
// # New session cookie. Must call selectVehicle.json before any other API call.
// if await self._select_vehicle(vin):
// result = True
}
// New function creates a New MySubaru client
func New(config *config.Config) (*Client, error) {
client := &Client{
credentials: config.MySubaru.Credentials,
country: config.MySubaru.Region,
updateInterval: 7200,
fetchInterval: 360,
logger: config.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()
var r Response
err := json.Unmarshal(resp, &r)
if err != nil {
client.logger.Error("error while parsing json", "request", "auth", "error", err.Error())
}
if r.Success {
var sd SessionData
err := json.Unmarshal(r.Data, &sd)
if err != nil {
client.logger.Error("error while parsing json", "request", "auth", "error", err.Error())
}
// client.logger.Debug("unmarshaled json data", "request", "auth", "type", "sessionData", "body", sd)
if sd.DeviceRegistered && sd.RegisteredDevicePermanent {
client.logger.Debug("client authentication successful")
client.isAuthenticated = true
client.isRegistered = true
} else {
client.logger.Debug("client authentication successful, but devices is not registered")
client.registerDevice()
}
// client.logger.Debug("parsing cars assigned to the account", "quantity", len(sd.Vehicles))
if len(sd.Vehicles) > 0 {
for _, vehicle := range sd.Vehicles {
// client.logger.Debug("parsing car", "vin", vehicle.Vin)
client.listOfVins = append(client.listOfVins, vehicle.Vin)
}
client.currentVin = client.listOfVins[0]
} else {
client.logger.Error("there no cars assigned to the account")
return nil, err
}
} else {
// TODO: Work on errors
// error, _ := respParsed.Path("errorCode").Data().(string)
// switch {
// case error == apiErrors["ERROR_INVALID_ACCOUNT"]:
// client.logger.Debug("Invalid account")
// case error == apiErrors["ERROR_INVALID_CREDENTIALS"]:
// client.logger.Debug("Client authentication failed")
// case error == apiErrors["ERROR_PASSWORD_WARNING"]:
// client.logger.Debug("Multiple Password Failures.")
// default:
// client.logger.Debug("Uknown error")
// }
client.logger.Error("request was not successfull", "request", "auth", "error", err.Error())
return nil, err
}
return client, nil
}
// SelectVehicle .
func (c *Client) SelectVehicle(vin string) VehicleData {
// API > json > dataName > vehicle
if vin == "" {
vin = c.currentVin
}
vinCheck(vin)
params := map[string]string{
"vin": vin,
"_": timestamp()}
reqURL := MOBILE_API_VERSION + apiURLs["API_SELECT_VEHICLE"]
resp := c.execute(reqURL, GET, params, "", false)
// c.logger.Debug("http request output", "request", "SelectVehicle", "body", resp)
var r Response
err := json.Unmarshal(resp, &r)
if err != nil {
c.logger.Error("error while parsing json", "request", "SelectVehicle", "error", err.Error())
}
if r.Success {
var vd VehicleData
err = json.Unmarshal(r.Data, &vd)
if err != nil {
c.logger.Error("error while parsing json", "request", "GetClimatePresets", "error", err.Error())
}
// c.logger.Debug("http request output", "request", "GetVehicleStatus", "body", resp)
return vd
} else {
return VehicleData{}
}
// resp := c.execute(reqURL, GET, params, "", false)
// logger.Debugf("SELECT VEHICLE OUTPUT >> %v\n", string([]byte(resp)))
// ERRORS
// {"success":false,"errorCode":"vehicleNotInAccount","dataName":null,"data":null}
// """Select active vehicle for accounts with multiple VINs."""
// params = {"vin": vin, "_": int(time.time())}
// js_resp = await self.get(API_SELECT_VEHICLE, params=params)
// _LOGGER.debug(pprint.pformat(js_resp))
// if js_resp.get("success"):
// self._current_vin = vin
// _LOGGER.debug("Current vehicle: vin=%s", js_resp["data"]["vin"])
// return js_resp["data"]
// if not js_resp.get("success") and js_resp.get("errorCode") == "VEHICLESETUPERROR":
// # Occasionally happens every few hours. Resetting the session seems to deal with it.
// _LOGGER.warning("VEHICLESETUPERROR received. Resetting session.")
// self.reset_session()
// return False
// _LOGGER.debug("Failed to switch vehicle errorCode=%s", js_resp.get("errorCode"))
// # Something else is probably wrong with the backend server context - try resetting
// self.reset_session()
// raise SubaruException("Failed to switch vehicle %s - resetting session." % js_resp.get("errorCode"))
}
// GetVehicles .
func (c *Client) GetVehicles() []*Vehicle {
var vehicles []*Vehicle
for _, vin := range c.listOfVins {
vehicle := c.GetVehicleByVIN(vin)
vehicles = append(vehicles, vehicle)
}
return vehicles
}
// GetVehicleByVIN .
func (c *Client) GetVehicleByVIN(vin string) *Vehicle {
var vehicle *Vehicle
if contains(c.listOfVins, vin) {
params := map[string]string{
"vin": vin,
"_": timestamp()}
reqURL := MOBILE_API_VERSION + apiURLs["API_SELECT_VEHICLE"]
resp := c.execute(reqURL, GET, params, "", false)
// c.logger.Debug("http request output", "request", "GetVehicleByVIN", "body", resp)
var r Response
err := json.Unmarshal(resp, &r)
if err != nil {
c.logger.Error("error while parsing json", "request", "GetVehicleByVIN", "error", err.Error())
}
if r.Success {
var vd VehicleData
err = json.Unmarshal(r.Data, &vd)
if err != nil {
c.logger.Error("error while parsing json", "request", "GetVehicleByVIN", "error", err.Error())
}
// c.logger.Debug("http request output", "request", "GetVehicleByVIN", "body", resp)
vehicle = &Vehicle{
Vin: vin,
CarName: vd.VehicleName,
CarNickname: vd.Nickname,
ModelName: vd.ModelName,
ModelYear: vd.ModelYear,
ModelCode: vd.ModelCode,
ExtDescrip: vd.ExtDescrip,
IntDescrip: vd.IntDescrip,
TransCode: vd.TransCode,
EngineSize: vd.EngineSize,
VehicleKey: vd.VehicleKey,
LicensePlate: vd.LicensePlate,
LicensePlateState: vd.LicensePlateState,
Features: vd.Features,
SubscriptionFeatures: vd.SubscriptionFeatures,
client: c,
}
vehicle.Doors = make(map[string]Door)
vehicle.Windows = make(map[string]Window)
vehicle.Tires = make(map[string]Tire)
vehicle.ClimateProfiles = make(map[string]ClimateProfile)
vehicle.GetVehicleStatus()
vehicle.GetVehicleCondition()
vehicle.GetVehicleHealth()
vehicle.GetClimatePresets()
vehicle.GetClimateUserPresets()
vehicle.GetClimateQuickPresets()
return vehicle
}
}
c.logger.Error("error while parsing json", "request", "GetVehicleByVIN")
return &Vehicle{}
}
// func isPINRequired() {}
// func getVehicles() {}
// func getEVStatus() {}
// func getRemoteOptionsStatus() {}
// func getRemoteStartStatus() {}
// func getSafetyStatus() {}
// func getSubscriptionStatus() {}
// func getAPIGen() {}
// func getClimateData() {}
// func saveClimateSettings() {}
// func getVehicleName() {}
// func fetch() {}
// Exec method executes a Client instance with the API URL
func (c *Client) execute(requestUrl string, method string, params map[string]string, pollingUrl string, j bool) []byte {
defer timeTrack("[TIMETRK] Executing Get Request")
var resp *resty.Response
// GET Requests
if method == "GET" {
resp, _ = c.httpClient.
R().
SetQueryParams(params).
Get(requestUrl)
}
// POST Requests
if method == "POST" {
if j {
// POST > JSON Body
resp, _ = c.httpClient.
R().
SetBody(params).
Post(requestUrl)
} else {
// POST > Form Data
resp, _ = c.httpClient.
R().
SetFormData(params).
Post(requestUrl)
}
}
resBytes, err := io.ReadAll(resp.Body)
if err != nil {
c.logger.Error("error while getting body", "error", err.Error())
}
var r Response
err = json.Unmarshal(resBytes, &r)
if err != nil {
c.logger.Error("error while parsing json", "request", "execute", "method", method, "url", requestUrl, "error", err.Error())
}
c.logger.Debug("parsed http request output", "request", "HTTP POLLING", "data", r.Data)
if r.Success {
var sr ServiceRequest
err := json.Unmarshal(r.Data, &sr)
if err != nil {
c.logger.Error("error while parsing json", "request", "HTTP POLLING", "error", err.Error())
}
if pollingUrl != "" {
time.Sleep(3 * time.Second)
attempts := 20
poolingLoop:
for attempts > 0 {
resp, _ = c.httpClient.
SetBaseURL(MOBILE_API_SERVER[c.country]).
R().
SetQueryParams(map[string]string{
"serviceRequestId": sr.ServiceRequestID,
}).
Get(pollingUrl)
resBytes, _ := io.ReadAll(resp.Body)
c.logger.Debug("POLLING HTTP OUTPUT", "body", string(resBytes))
// {"success":false,"errorCode":"404-soa-unableToParseResponseBody","dataName":"errorResponse","data":{"errorLabel":"404-soa-unableToParseResponseBody","errorDescription":null}}
var r Response
err := json.Unmarshal(resBytes, &r)
if err != nil {
c.logger.Error("error while parsing json", "request", "HTTP POLLING", "error", err.Error())
}
c.logger.Debug("parsed loop http request output", "request", "HTTP POLLING", "data", r.Data)
if r.Success {
var sr ServiceRequest
err := json.Unmarshal(r.Data, &sr)
if err != nil {
c.logger.Error("error while parsing json", "request", "HTTP POLLING", "error", err.Error())
}
switch {
case sr.RemoteServiceState == "finished":
c.logger.Debug("Remote service request completed successfully", "request id", sr.ServiceRequestID)
break poolingLoop
case sr.RemoteServiceState == "started":
c.logger.Debug("Subaru API reports remote service request is in progress", "request id", sr.ServiceRequestID)
}
} else {
c.logger.Debug("Backend session expired, please try again")
break poolingLoop
}
attempts--
time.Sleep(3 * time.Second)
}
}
} else {
c.logger.Error("request is not successfull", "request", "execute", "method", method, "url", requestUrl, "error", err.Error())
}
return resBytes
}
// // isResponseSuccessfull .
// func (c *Client) isResponseSuccessfull(resp []byte) bool {
// respParsed, err := gabs.ParseJSON(resp)
// if err != nil {
// c.logger.Debug("error while parsing json response", "error", err)
// }
// success, ok := respParsed.Path("success").Data().(bool)
// if !ok {
// c.logger.Debug("response is not successful", "error", resp)
// }
// // ERRORS FROM CLIENT CREATION AFTER AUTH
// // error, _ := respParsed.Path("errorCode").Data().(string)
// // switch {
// // case error == apiErrors["ERROR_INVALID_ACCOUNT"]:
// // fmt.Println("Invalid account")
// // case error == apiErrors["ERROR_INVALID_CREDENTIALS"]:
// // {"success":false,"errorCode":"InvalidCredentials","dataName":"remoteServiceStatus","data":{"serviceRequestId":null,"success":false,"cancelled":false,"remoteServiceType":null,"remoteServiceState":null,"subState":null,"errorCode":null,"result":null,"updateTime":null,"vin":null,"errorDescription":"The credentials supplied are invalid, tries left 2"}}
// // fmt.Println("Client authentication failed")
// // case error == apiErrors["ERROR_PASSWORD_WARNING"]:
// // fmt.Println("Multiple Password Failures.")
// // default:
// // fmt.Println("Uknown error")
// // }
// return success
// }