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 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": {
@@ -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
- try:
118
- login_session = Session()
119
- ####################################
120
- _logger.debug("Step 1 - Get Authorization data")
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
- auth_cookie_response = login_session.get(authorizationUri)
134
- if not auth_cookie_response.ok:
135
- raise LGHorizonApiConnectionError("Can't connect to authorization URL")
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
- if not login_response.ok:
148
- raise LGHorizonApiConnectionError("Can't connect to authorization URL")
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
- redirect_url = login_response.headers["x-redirect-location"]
154
- ####################################
155
- _logger.debug("Step 4 - Follow redirect")
156
- redirect_response = login_session.get(redirect_url, allow_redirects=False)
157
- if not "Location" in redirect_response.headers:
158
- raise LGHorizonApiConnectionError("No success url in redirect.")
159
- ####################################
160
- _logger.debug("Step 5 - Extract auth code")
161
- success_url = redirect_response.headers["Location"]
162
- codeMatches = re.findall(r"code=(.*)&", success_url)
163
- if len(codeMatches) == 0:
164
- raise LGHorizonApiConnectionError("No code in redirect headers")
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
- self._auth.fill(post_session_result.json())
198
- self._session.cookies["ACCESSTOKEN"] = self._auth.accessToken
199
- ####################################
200
- except Exception as ex:
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
- if self._country_code == "gb":
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"],
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: lghorizon
3
- Version: 0.6.13
3
+ Version: 0.7.0
4
4
  Summary: Python client for Liberty Global Horizon settop boxes
5
5
  Home-page: https://github.com/sholofly/LGHorizon-python
6
6
  Author: Rudolf Offereins
@@ -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,,