aioamazondevices 3.1.22__tar.gz → 3.2.0__tar.gz

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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: aioamazondevices
3
- Version: 3.1.22
3
+ Version: 3.2.0
4
4
  Summary: Python library to control Amazon devices
5
5
  License: Apache-2.0
6
6
  Author: Simone Chemelli
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "aioamazondevices"
3
- version = "3.1.22"
3
+ version = "3.2.0"
4
4
  requires-python = ">=3.12"
5
5
  description = "Python library to control Amazon devices"
6
6
  authors = [
@@ -1,6 +1,6 @@
1
1
  """aioamazondevices library."""
2
2
 
3
- __version__ = "3.1.22"
3
+ __version__ = "3.2.0"
4
4
 
5
5
 
6
6
  from .api import AmazonDevice, AmazonEchoApi
@@ -56,6 +56,7 @@ from .exceptions import (
56
56
  CannotConnect,
57
57
  CannotRegisterDevice,
58
58
  CannotRetrieveData,
59
+ WrongCountry,
59
60
  WrongMethod,
60
61
  )
61
62
  from .utils import obfuscate_email, scrub_fields
@@ -146,6 +147,15 @@ class AmazonEchoApi:
146
147
  self.session: ClientSession
147
148
  self._devices: dict[str, Any] = {}
148
149
 
150
+ lang_object = Language.make(territory=self._login_country_code.upper())
151
+ lang_maximized = lang_object.maximize()
152
+ self._language = f"{lang_maximized.language}-{lang_maximized.region}"
153
+ _LOGGER.debug(
154
+ "Initialize library with domain <%s> and language <%s>",
155
+ self._domain,
156
+ self._language,
157
+ )
158
+
149
159
  def _load_website_cookies(self) -> dict[str, str]:
150
160
  """Get website cookies, if avaliables."""
151
161
  if not self._login_stored_data:
@@ -210,22 +220,23 @@ class AmazonEchoApi:
210
220
  code_challenge = self._create_s256_code_challenge(code_verifier)
211
221
 
212
222
  oauth_params = {
213
- "openid.oa2.response_type": "code",
214
- "openid.oa2.code_challenge_method": "S256",
215
- "openid.oa2.code_challenge": code_challenge,
216
223
  "openid.return_to": f"https://www.amazon.{self._domain}/ap/maplanding",
224
+ "openid.oa2.code_challenge_method": "S256",
217
225
  "openid.assoc_handle": self._assoc_handle,
218
226
  "openid.identity": "http://specs.openid.net/auth/2.0/identifier_select",
227
+ "pageId": self._assoc_handle,
219
228
  "accountStatusPolicy": "P1",
220
229
  "openid.claimed_id": "http://specs.openid.net/auth/2.0/identifier_select",
221
230
  "openid.mode": "checkid_setup",
222
231
  "openid.ns.oa2": "http://www.amazon.com/ap/ext/oauth/2",
223
232
  "openid.oa2.client_id": f"device:{client_id}",
233
+ "language": self._language.replace("-", "_"),
224
234
  "openid.ns.pape": "http://specs.openid.net/extensions/pape/1.0",
235
+ "openid.oa2.code_challenge": code_challenge,
225
236
  "openid.oa2.scope": "device_auth_access",
226
- "forceMobileLayout": "true",
227
237
  "openid.ns": "http://specs.openid.net/auth/2.0",
228
238
  "openid.pape.max_auth_age": "0",
239
+ "openid.oa2.response_type": "code",
229
240
  }
230
241
 
231
242
  return (
@@ -273,8 +284,10 @@ class AmazonEchoApi:
273
284
  """Create HTTP client session."""
274
285
  if not hasattr(self, "session") or self.session.closed:
275
286
  _LOGGER.debug("Creating HTTP session (aiohttp)")
287
+ headers = DEFAULT_HEADERS
288
+ headers.update({"Accept-Language": self._language})
276
289
  self.session = ClientSession(
277
- headers=DEFAULT_HEADERS,
290
+ headers=headers,
278
291
  cookies=self._cookies,
279
292
  )
280
293
 
@@ -323,6 +336,7 @@ class AmazonEchoApi:
323
336
  )
324
337
 
325
338
  headers = DEFAULT_HEADERS
339
+ headers.update({"Accept-Language": self._language})
326
340
  if self._csrf_cookie and CSRF_COOKIE not in headers:
327
341
  csrf = {CSRF_COOKIE: self._csrf_cookie}
328
342
  _LOGGER.debug("Adding <%s> to headers", csrf)
@@ -512,6 +526,31 @@ class AmazonEchoApi:
512
526
  await self._save_to_file(login_data, "login_data", JSON_EXTENSION)
513
527
  return login_data
514
528
 
529
+ async def _check_country(self) -> None:
530
+ """Check if user selected country matches Amazon account country."""
531
+ url = f"https://alexa.amazon.{self._domain}/api/users/me"
532
+ _, resp_me = await self._session_request(HTTPMethod.GET, url)
533
+
534
+ if resp_me.status != HTTPStatus.OK:
535
+ raise CannotAuthenticate
536
+
537
+ resp_me_json = await resp_me.json()
538
+ market = resp_me_json["marketPlaceDomainName"]
539
+ language = resp_me_json["marketPlaceLocale"]
540
+
541
+ _domain = f"https://www.amazon.{self._domain}"
542
+
543
+ if market != _domain or language != self._language:
544
+ _LOGGER.debug(
545
+ "Selected country <%s> doesn't matches Amazon account:\n%s\n vs \n%s",
546
+ self._login_country_code.upper(),
547
+ {"site ": _domain, "locale": self._language},
548
+ {"market": market, "locale": language},
549
+ )
550
+ raise WrongCountry
551
+
552
+ _LOGGER.debug("User selected country matches Amazon account one")
553
+
515
554
  async def _get_devices_ids(self) -> list[dict[str, str]]:
516
555
  """Retrieve devices entityId and applianceId."""
517
556
  _, raw_resp = await self._session_request(
@@ -685,6 +724,9 @@ class AmazonEchoApi:
685
724
  self._login_stored_data = register_device
686
725
 
687
726
  _LOGGER.info("Register device: %s", scrub_fields(register_device))
727
+
728
+ await self._check_country()
729
+
688
730
  return register_device
689
731
 
690
732
  async def login_mode_stored_data(self) -> dict[str, Any]:
@@ -703,6 +745,8 @@ class AmazonEchoApi:
703
745
 
704
746
  self._client_session()
705
747
 
748
+ await self._check_country()
749
+
706
750
  return self._login_stored_data
707
751
 
708
752
  async def close(self) -> None:
@@ -842,10 +886,6 @@ class AmazonEchoApi:
842
886
  message_source: AmazonMusicSource | None = None,
843
887
  ) -> None:
844
888
  """Send message to specific device."""
845
- lang_object = Language.make(territory=self._login_country_code.upper())
846
- lang_maximized = lang_object.maximize()
847
- locale = f"{lang_maximized.language}-{lang_maximized.region}"
848
-
849
889
  if not self._login_stored_data:
850
890
  _LOGGER.warning("Trying to send message before login")
851
891
  return
@@ -853,7 +893,7 @@ class AmazonEchoApi:
853
893
  base_payload = {
854
894
  "deviceType": device.device_type,
855
895
  "deviceSerialNumber": device.serial_number,
856
- "locale": locale,
896
+ "locale": self._language,
857
897
  "customerId": device.device_owner_customer_id,
858
898
  }
859
899
 
@@ -888,7 +928,7 @@ class AmazonEchoApi:
888
928
  "expireAfter": "PT5S",
889
929
  "content": [
890
930
  {
891
- "locale": locale,
931
+ "locale": self._language,
892
932
  "display": {
893
933
  "title": "Home Assistant",
894
934
  "body": message_body,
@@ -84,7 +84,6 @@ DEFAULT_HEADERS = {
84
84
  ),
85
85
  "Accept-Charset": "utf-8",
86
86
  "Accept-Encoding": "gzip",
87
- "Accept-Language": "en-US",
88
87
  "Connection": "keep-alive",
89
88
  }
90
89
  CSRF_COOKIE = "csrf"
@@ -25,3 +25,7 @@ class CannotRegisterDevice(AmazonError):
25
25
 
26
26
  class WrongMethod(AmazonError):
27
27
  """Exception raised when the wrong login metho is used."""
28
+
29
+
30
+ class WrongCountry(AmazonError):
31
+ """Exceptio nraised when Amazon country."""