lghorizon 0.6.13__py3-none-any.whl → 0.7.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- lghorizon/const.py +0 -2
- lghorizon/lghorizon_api.py +30 -102
- {lghorizon-0.6.13.dist-info → lghorizon-0.7.0.dist-info}/METADATA +1 -1
- lghorizon-0.7.0.dist-info/RECORD +12 -0
- lghorizon-0.6.13.dist-info/RECORD +0 -12
- {lghorizon-0.6.13.dist-info → lghorizon-0.7.0.dist-info}/LICENSE +0 -0
- {lghorizon-0.6.13.dist-info → lghorizon-0.7.0.dist-info}/WHEEL +0 -0
- {lghorizon-0.6.13.dist-info → lghorizon-0.7.0.dist-info}/top_level.txt +0 -0
lghorizon/const.py
CHANGED
|
@@ -119,9 +119,7 @@ COUNTRY_SETTINGS = {
|
|
|
119
119
|
},
|
|
120
120
|
"gb": {
|
|
121
121
|
"api_url": "https://spark-prod-gb.gnp.cloud.virgintvgo.virginmedia.com",
|
|
122
|
-
"oauth_url": "https://id.virginmedia.com/rest/v40/session/start?protocol=oidc&rememberMe=true",
|
|
123
122
|
"channels": [],
|
|
124
|
-
"oesp_url": "https://prod.oesp.virginmedia.com/oesp/v4/GB/eng/web",
|
|
125
123
|
"language": "en",
|
|
126
124
|
},
|
|
127
125
|
"ie": {
|
lghorizon/lghorizon_api.py
CHANGED
|
@@ -63,10 +63,12 @@ class LGHorizonApi:
|
|
|
63
63
|
password: str,
|
|
64
64
|
country_code: str = "nl",
|
|
65
65
|
identifier: str = None,
|
|
66
|
+
refresh_token = None,
|
|
66
67
|
) -> None:
|
|
67
68
|
"""Create LGHorizon API."""
|
|
68
69
|
self.username = username
|
|
69
70
|
self.password = password
|
|
71
|
+
self.refresh_token = refresh_token
|
|
70
72
|
self._session = Session()
|
|
71
73
|
self._country_settings = COUNTRY_SETTINGS[country_code]
|
|
72
74
|
self._country_code = country_code
|
|
@@ -113,92 +115,36 @@ class LGHorizonApi:
|
|
|
113
115
|
self._auth.fill(auth_response.json())
|
|
114
116
|
_logger.debug("Authorization succeeded")
|
|
115
117
|
|
|
116
|
-
def authorize_gb(self):
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
auth_url = f"{self._country_settings['oesp_url']}/authorization"
|
|
122
|
-
auth_response = login_session.get(auth_url)
|
|
123
|
-
if not auth_response.ok:
|
|
124
|
-
raise LGHorizonApiConnectionError("Can't connect to authorization URL")
|
|
125
|
-
auth_response_json = auth_response.json()
|
|
126
|
-
auth_session = auth_response_json["session"]
|
|
127
|
-
auth_state = auth_session["state"]
|
|
128
|
-
authorizationUri = auth_session["authorizationUri"]
|
|
129
|
-
authValidityToken = auth_session["validityToken"]
|
|
130
|
-
####################################
|
|
131
|
-
_logger.debug("Step 2 - Get Authorization cookie")
|
|
118
|
+
def authorize_gb(self) -> None:
|
|
119
|
+
_logger.debug("Authorizing via refresh")
|
|
120
|
+
refresh_url = (f"{self._country_settings['api_url']}/auth-service/v1/authorization/refresh")
|
|
121
|
+
headers = {"content-type": "application/json", "charset": "utf-8"}
|
|
122
|
+
payload = '{"refreshToken":"' + self.refresh_token + '"}'
|
|
132
123
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
####################################
|
|
137
|
-
_logger.debug("Step 3 - Login")
|
|
138
|
-
payload = {"username": self.username, "credential": self.password}
|
|
139
|
-
headers = {"accept": "application/json; charset=UTF-8, */*"}
|
|
140
|
-
|
|
141
|
-
login_response = login_session.post(
|
|
142
|
-
self._country_settings["oauth_url"],
|
|
143
|
-
json.dumps(payload),
|
|
144
|
-
headers=headers,
|
|
145
|
-
allow_redirects=False,
|
|
124
|
+
try:
|
|
125
|
+
auth_response = self._session.post(
|
|
126
|
+
refresh_url, headers=headers, data=payload
|
|
146
127
|
)
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
if not "x-redirect-location" in login_response.headers:
|
|
151
|
-
raise LGHorizonApiConnectionError("No redirect location in headers.")
|
|
128
|
+
except Exception as ex:
|
|
129
|
+
raise LGHorizonApiConnectionError("Unknown connection failure") from ex
|
|
152
130
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
if
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
raise LGHorizonApiConnectionError("
|
|
165
|
-
authorizationCode = codeMatches[0]
|
|
166
|
-
stateMatches = re.findall(r"state=(.*)", success_url)
|
|
167
|
-
if len(codeMatches) == 0:
|
|
168
|
-
raise LGHorizonApiConnectionError("No state in redirect headers")
|
|
169
|
-
authorizationState = stateMatches[0]
|
|
170
|
-
_logger.debug(
|
|
171
|
-
f"Auth code: {authorizationCode}, Auth state: {authorizationState}"
|
|
172
|
-
)
|
|
173
|
-
####################################
|
|
174
|
-
_logger.debug("Step 6 - Post auth data with valid code")
|
|
175
|
-
authorization_payload = {
|
|
176
|
-
"authorizationGrant": {
|
|
177
|
-
"authorizationCode": authorizationCode,
|
|
178
|
-
"validityToken": authValidityToken,
|
|
179
|
-
"state": authorizationState,
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
headers = {
|
|
183
|
-
"content-type": "application/json",
|
|
184
|
-
}
|
|
185
|
-
# VM requires the client to pass the response from /authorization verbatim to /session?token=true
|
|
186
|
-
post_authorization_result = login_session.post(
|
|
187
|
-
self._country_settings["oesp_url"] + "/authorization",
|
|
188
|
-
json.dumps(authorization_payload),
|
|
189
|
-
headers=headers,
|
|
190
|
-
)
|
|
191
|
-
post_session_result = login_session.post(
|
|
192
|
-
self._country_settings["oesp_url"] + "/session?token=true",
|
|
193
|
-
json.dumps(post_authorization_result.json()),
|
|
194
|
-
headers=headers,
|
|
195
|
-
)
|
|
131
|
+
if not auth_response.ok:
|
|
132
|
+
_logger.debug("response %s", auth_response)
|
|
133
|
+
error_json = auth_response.json()
|
|
134
|
+
error = None
|
|
135
|
+
if "error" in error_json:
|
|
136
|
+
error = error_json["error"]
|
|
137
|
+
if error and error["statusCode"] == 97401:
|
|
138
|
+
raise LGHorizonApiUnauthorizedError("Invalid credentials")
|
|
139
|
+
elif error:
|
|
140
|
+
raise LGHorizonApiConnectionError(error["message"])
|
|
141
|
+
else:
|
|
142
|
+
raise LGHorizonApiConnectionError("Unknown connection error")
|
|
196
143
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
pass
|
|
144
|
+
self._auth.fill(auth_response.json())
|
|
145
|
+
self.refresh_token = self._auth.refreshToken
|
|
146
|
+
self._session.cookies["ACCESSTOKEN"] = self._auth.accessToken
|
|
147
|
+
_logger.debug("Authorization succeeded")
|
|
202
148
|
|
|
203
149
|
def authorize_telenet(self):
|
|
204
150
|
try:
|
|
@@ -276,32 +222,14 @@ class LGHorizonApi:
|
|
|
276
222
|
self._auth.mqttToken = mqtt_response["token"]
|
|
277
223
|
_logger.debug(f"MQTT token: {self._auth.mqttToken}")
|
|
278
224
|
|
|
279
|
-
def _obtain_mqtt_token_gb(self):
|
|
280
|
-
_logger.debug("Obtain Virgin GB mqtt token...")
|
|
281
|
-
self._session.headers["x-oesp-token"] = self._auth.accessToken
|
|
282
|
-
self._session.headers["x-oesp-username"] = self._auth.username
|
|
283
|
-
|
|
284
|
-
mqtt_response = self._do_api_call(
|
|
285
|
-
f"{self._country_settings['oesp_url']}/tokens/jwt"
|
|
286
|
-
)
|
|
287
|
-
self._auth.mqttToken = mqtt_response["token"]
|
|
288
|
-
_logger.debug(f"MQTT token: {self._auth.mqttToken}")
|
|
289
|
-
|
|
290
225
|
@backoff.on_exception(
|
|
291
|
-
backoff.expo,
|
|
292
|
-
BaseException,
|
|
293
|
-
jitter=None,
|
|
294
|
-
max_tries=3,
|
|
295
|
-
logger=_logger,
|
|
226
|
+
backoff.expo, BaseException, jitter=None, max_time=600, logger=_logger
|
|
296
227
|
)
|
|
297
228
|
def connect(self) -> None:
|
|
298
229
|
self._config = self._get_config(self._country_code)
|
|
299
230
|
_logger.debug("Connect to API")
|
|
300
231
|
self._authorize()
|
|
301
|
-
|
|
302
|
-
self._obtain_mqtt_token_gb()
|
|
303
|
-
else:
|
|
304
|
-
self._obtain_mqtt_token()
|
|
232
|
+
self._obtain_mqtt_token()
|
|
305
233
|
self._mqttClient = LGHorizonMqttClient(
|
|
306
234
|
self._auth,
|
|
307
235
|
self._config["mqttBroker"]["URL"],
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
lghorizon/__init__.py,sha256=_VjVE44ErvJJMnF5QgXdlw_nQzbHZUhGWw5hF40PolQ,426
|
|
2
|
+
lghorizon/const.py,sha256=S8UWatG7JPCqd1zk-iOoILTvFDEj7YhLcEXxLGhyJXs,4755
|
|
3
|
+
lghorizon/exceptions.py,sha256=spEjRvbNdce2fauQiOFromAbV1QcfA0uMUt0nRVnnkM,318
|
|
4
|
+
lghorizon/helpers.py,sha256=ZWpi7B3hBvwGV02KWQQHVyj7FLLUDtIvKc-Iqsj5VHA,263
|
|
5
|
+
lghorizon/lghorizon_api.py,sha256=FrYrh-4y_CBZGc6_c8S3xFOCLs9xU8KC2mLdHOLqgLc,20252
|
|
6
|
+
lghorizon/models.py,sha256=yrKlQMnHCy8FHwCel3lcTUEnd7_JQbETqf5yGW3S84o,23893
|
|
7
|
+
lghorizon/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
8
|
+
lghorizon-0.7.0.dist-info/LICENSE,sha256=6Dh2tur1gMX3r3rITjVwUONBEJxyyPZDY8p6DZXtimE,1059
|
|
9
|
+
lghorizon-0.7.0.dist-info/METADATA,sha256=b6vgRtvq_yqodGVn2bwU27Z7NM1wMgl-2QlFwLgpibA,1037
|
|
10
|
+
lghorizon-0.7.0.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
|
|
11
|
+
lghorizon-0.7.0.dist-info/top_level.txt,sha256=usii76_AxGfPI6gjrrh-NyZxcQQuF1B8_Q9kd7sID8Q,10
|
|
12
|
+
lghorizon-0.7.0.dist-info/RECORD,,
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
lghorizon/__init__.py,sha256=_VjVE44ErvJJMnF5QgXdlw_nQzbHZUhGWw5hF40PolQ,426
|
|
2
|
-
lghorizon/const.py,sha256=0IrGb8lgycCJBqTZ7WW7rI8ZPNItRgKJewUa_mnl9uQ,4935
|
|
3
|
-
lghorizon/exceptions.py,sha256=spEjRvbNdce2fauQiOFromAbV1QcfA0uMUt0nRVnnkM,318
|
|
4
|
-
lghorizon/helpers.py,sha256=ZWpi7B3hBvwGV02KWQQHVyj7FLLUDtIvKc-Iqsj5VHA,263
|
|
5
|
-
lghorizon/lghorizon_api.py,sha256=kMOfbwOYLOBqDX0xgvoXlE5PWBJ0eu2pibwiyizVhg0,23669
|
|
6
|
-
lghorizon/models.py,sha256=yrKlQMnHCy8FHwCel3lcTUEnd7_JQbETqf5yGW3S84o,23893
|
|
7
|
-
lghorizon/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
8
|
-
lghorizon-0.6.13.dist-info/LICENSE,sha256=6Dh2tur1gMX3r3rITjVwUONBEJxyyPZDY8p6DZXtimE,1059
|
|
9
|
-
lghorizon-0.6.13.dist-info/METADATA,sha256=a5M6PhIwxWyieNQ0h3RkdJxHwZIhLc_KP17IxunG_Rs,1038
|
|
10
|
-
lghorizon-0.6.13.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
|
|
11
|
-
lghorizon-0.6.13.dist-info/top_level.txt,sha256=usii76_AxGfPI6gjrrh-NyZxcQQuF1B8_Q9kd7sID8Q,10
|
|
12
|
-
lghorizon-0.6.13.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|