aioamazondevices 4.0.2__tar.gz → 5.0.1__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: 4.0.2
3
+ Version: 5.0.1
4
4
  Summary: Python library to control Amazon devices
5
5
  License: Apache-2.0
6
6
  Author: Simone Chemelli
@@ -19,6 +19,7 @@ Requires-Dist: orjson
19
19
  Requires-Dist: yarl
20
20
  Project-URL: Bug Tracker, https://github.com/chemelli74/aioamazondevices/issues
21
21
  Project-URL: Changelog, https://github.com/chemelli74/aioamazondevices/blob/main/CHANGELOG.md
22
+ Project-URL: Homepage, https://github.com/chemelli74/aioamazondevices
22
23
  Description-Content-Type: text/markdown
23
24
 
24
25
  # aioamazondevices
@@ -74,7 +75,6 @@ The script accept command line arguments or a library_test.json config file:
74
75
 
75
76
  ```json
76
77
  {
77
- "country": "IT",
78
78
  "email": "<my_address@gmail.com>",
79
79
  "password": "<my_password>",
80
80
  "single_device_name": "Echo Dot Livingroom",
@@ -51,7 +51,6 @@ The script accept command line arguments or a library_test.json config file:
51
51
 
52
52
  ```json
53
53
  {
54
- "country": "IT",
55
54
  "email": "<my_address@gmail.com>",
56
55
  "password": "<my_password>",
57
56
  "single_device_name": "Echo Dot Livingroom",
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "aioamazondevices"
3
- version = "4.0.2"
3
+ version = "5.0.1"
4
4
  requires-python = ">=3.12"
5
5
  description = "Python library to control Amazon devices"
6
6
  authors = [
@@ -29,6 +29,7 @@ dependencies = [
29
29
  ]
30
30
 
31
31
  [project.urls]
32
+ "Homepage" = "https://github.com/chemelli74/aioamazondevices"
32
33
  "Bug Tracker" = "https://github.com/chemelli74/aioamazondevices/issues"
33
34
  "Changelog" = "https://github.com/chemelli74/aioamazondevices/blob/main/CHANGELOG.md"
34
35
 
@@ -1,6 +1,6 @@
1
1
  """aioamazondevices library."""
2
2
 
3
- __version__ = "4.0.2"
3
+ __version__ = "5.0.1"
4
4
 
5
5
 
6
6
  from .api import AmazonDevice, AmazonEchoApi
@@ -16,7 +16,11 @@ from typing import Any, cast
16
16
  from urllib.parse import parse_qs, urlencode
17
17
 
18
18
  import orjson
19
- from aiohttp import ClientConnectorError, ClientResponse, ClientSession
19
+ from aiohttp import (
20
+ ClientConnectorError,
21
+ ClientResponse,
22
+ ClientSession,
23
+ )
20
24
  from bs4 import BeautifulSoup, Tag
21
25
  from langcodes import Language
22
26
  from multidict import MultiDictProxy
@@ -37,9 +41,9 @@ from .const import (
37
41
  DEFAULT_AGENT,
38
42
  DEFAULT_ASSOC_HANDLE,
39
43
  DEFAULT_HEADERS,
44
+ DEFAULT_SITE,
40
45
  DEVICE_TO_IGNORE,
41
46
  DEVICE_TYPE_TO_MODEL,
42
- DOMAIN_BY_ISO3166_COUNTRY,
43
47
  HTML_EXTENSION,
44
48
  HTTP_ERROR_199,
45
49
  HTTP_ERROR_299,
@@ -49,6 +53,8 @@ from .const import (
49
53
  NODE_DO_NOT_DISTURB,
50
54
  NODE_IDENTIFIER,
51
55
  NODE_PREFERENCES,
56
+ REFRESH_ACCESS_TOKEN,
57
+ REFRESH_AUTH_COOKIES,
52
58
  SAVE_PATH,
53
59
  SENSORS,
54
60
  URI_IDS,
@@ -61,7 +67,6 @@ from .exceptions import (
61
67
  CannotConnect,
62
68
  CannotRegisterDevice,
63
69
  CannotRetrieveData,
64
- WrongCountry,
65
70
  WrongMethod,
66
71
  )
67
72
  from .utils import obfuscate_email, scrub_fields
@@ -86,7 +91,6 @@ class AmazonDevice:
86
91
  device_type: str
87
92
  device_owner_customer_id: str
88
93
  device_cluster_members: list[str]
89
- device_locale: str
90
94
  online: bool
91
95
  serial_number: str
92
96
  software_version: str
@@ -122,32 +126,22 @@ class AmazonEchoApi:
122
126
  def __init__(
123
127
  self,
124
128
  client_session: ClientSession,
125
- login_country_code: str,
126
129
  login_email: str,
127
130
  login_password: str,
128
131
  login_data: dict[str, Any] | None = None,
129
132
  ) -> None:
130
133
  """Initialize the scanner."""
131
- # Force country digits as lower case
132
- country_code = login_country_code.lower()
133
-
134
- locale: dict = DOMAIN_BY_ISO3166_COUNTRY.get(country_code, {})
135
- domain: str = locale.get("domain", country_code)
136
- market: list[str] = locale.get("market", [f"https://www.amazon.{domain}"])
137
- assoc_handle: str = locale.get(
138
- "openid.assoc_handle", f"{DEFAULT_ASSOC_HANDLE}_{country_code}"
139
- )
134
+ # Check if there is a previous login, otherwise use default (US)
135
+ site = login_data.get("site", DEFAULT_SITE) if login_data else DEFAULT_SITE
136
+ _LOGGER.debug("Using site: %s", site)
137
+ self._country_specific_data(site)
140
138
 
141
- self._assoc_handle = assoc_handle
142
139
  self._login_email = login_email
143
140
  self._login_password = login_password
144
- self._login_country_code = country_code
145
- self._domain = domain
146
- self._market = market
141
+
147
142
  self._cookies = self._build_init_cookies()
148
- self._csrf_cookie: str | None = None
149
143
  self._save_raw_data = False
150
- self._login_stored_data = login_data
144
+ self._login_stored_data = login_data or {}
151
145
  self._serial = self._serial_number()
152
146
  self._list_for_clusters: dict[str, str] = {}
153
147
 
@@ -155,23 +149,40 @@ class AmazonEchoApi:
155
149
  self._devices: dict[str, Any] = {}
156
150
  self._sensors_available: bool = True
157
151
 
158
- lang_object = Language.make(territory=self._login_country_code.upper())
152
+ _LOGGER.debug("Initialize library v%s", __version__)
153
+
154
+ @property
155
+ def domain(self) -> str:
156
+ """Return current Amazon domain."""
157
+ return self._domain
158
+
159
+ def save_raw_data(self) -> None:
160
+ """Save raw data to disk."""
161
+ self._save_raw_data = True
162
+ _LOGGER.debug("Saving raw data to disk")
163
+
164
+ def _country_specific_data(self, domain: str) -> None:
165
+ """Set country specific data."""
166
+ # Force lower case
167
+ domain = domain.replace("https://www.amazon.", "").lower()
168
+ country_code = domain.split(".")[-1] if domain != "com" else "us"
169
+
170
+ lang_object = Language.make(territory=country_code.upper())
159
171
  lang_maximized = lang_object.maximize()
172
+
173
+ self._domain: str = domain
160
174
  self._language = f"{lang_maximized.language}-{lang_maximized.region}"
161
175
 
176
+ # Reset CSRF cookie when changing country
177
+ self._csrf_cookie: str | None = None
178
+
162
179
  _LOGGER.debug(
163
- "Initialize library v%s: domain <amazon.%s>, language <%s>, market: <%s>",
164
- __version__,
180
+ "Initialize country <%s>: domain <amazon.%s>, language <%s>",
181
+ country_code.upper(),
165
182
  self._domain,
166
183
  self._language,
167
- self._market,
168
184
  )
169
185
 
170
- def save_raw_data(self) -> None:
171
- """Save raw data to disk."""
172
- self._save_raw_data = True
173
- _LOGGER.debug("Saving raw data to disk")
174
-
175
186
  def _load_website_cookies(self) -> dict[str, str]:
176
187
  """Get website cookies, if avaliables."""
177
188
  if not self._login_stored_data:
@@ -246,11 +257,11 @@ class AmazonEchoApi:
246
257
  code_challenge = self._create_s256_code_challenge(code_verifier)
247
258
 
248
259
  oauth_params = {
249
- "openid.return_to": f"https://www.amazon.{self._domain}/ap/maplanding",
260
+ "openid.return_to": "https://www.amazon.com/ap/maplanding",
250
261
  "openid.oa2.code_challenge_method": "S256",
251
- "openid.assoc_handle": self._assoc_handle,
262
+ "openid.assoc_handle": DEFAULT_ASSOC_HANDLE,
252
263
  "openid.identity": "http://specs.openid.net/auth/2.0/identifier_select",
253
- "pageId": self._assoc_handle,
264
+ "pageId": DEFAULT_ASSOC_HANDLE,
254
265
  "accountStatusPolicy": "P1",
255
266
  "openid.claimed_id": "http://specs.openid.net/auth/2.0/identifier_select",
256
267
  "openid.mode": "checkid_setup",
@@ -265,9 +276,7 @@ class AmazonEchoApi:
265
276
  "openid.oa2.response_type": "code",
266
277
  }
267
278
 
268
- return (
269
- f"https://www.amazon.{self._domain}{URI_SIGNIN}?{urlencode(oauth_params)}"
270
- )
279
+ return f"https://www.amazon.com{URI_SIGNIN}?{urlencode(oauth_params)}"
271
280
 
272
281
  def _get_inputs_from_soup(self, soup: BeautifulSoup) -> dict[str, str]:
273
282
  """Extract hidden form input fields from a Amazon login page."""
@@ -352,7 +361,7 @@ class AmazonEchoApi:
352
361
  json_data,
353
362
  )
354
363
 
355
- headers = DEFAULT_HEADERS
364
+ headers = DEFAULT_HEADERS.copy()
356
365
  headers.update({"Accept-Language": self._language})
357
366
  if not amazon_user_agent:
358
367
  _LOGGER.debug("Changing User-Agent to %s", DEFAULT_AGENT)
@@ -370,7 +379,15 @@ class AmazonEchoApi:
370
379
  _cookies = (
371
380
  self._load_website_cookies() if self._login_stored_data else self._cookies
372
381
  )
373
- self._session.cookie_jar.update_cookies(_cookies)
382
+ self._session.cookie_jar.update_cookies(_cookies, URL(f"amazon.{self._domain}"))
383
+
384
+ if url.endswith("/auth/token"):
385
+ headers.update(
386
+ {
387
+ "Content-Type": "application/x-www-form-urlencoded",
388
+ "x-amzn-identity-auth-domain": "api.amazon.com",
389
+ }
390
+ )
374
391
 
375
392
  resp: ClientResponse | None = None
376
393
  for delay in [0, 1, 2, 5, 8, 12, 21]:
@@ -405,15 +422,18 @@ class AmazonEchoApi:
405
422
  _LOGGER.error("No response received from %s", url)
406
423
  raise CannotConnect(f"No response received from {url}")
407
424
 
408
- if not self._csrf_cookie:
409
- self._csrf_cookie = resp.cookies.get(CSRF_COOKIE, Morsel()).value
410
- _LOGGER.debug("CSRF cookie value: <%s>", self._csrf_cookie)
425
+ if not self._csrf_cookie and (
426
+ csrf := resp.cookies.get(CSRF_COOKIE, Morsel()).value
427
+ ):
428
+ self._csrf_cookie = csrf
429
+ _LOGGER.debug("CSRF cookie value: <%s> [%s]", self._csrf_cookie, url)
411
430
 
412
431
  content_type: str = resp.headers.get("Content-Type", "")
413
432
  _LOGGER.debug(
414
- "Response %s for url %s with content type: %s",
415
- resp.status,
433
+ "Response for url %s :\nstatus : %s \
434
+ \ncontent type: %s ",
416
435
  url,
436
+ resp.status,
417
437
  content_type,
418
438
  )
419
439
 
@@ -508,6 +528,7 @@ class AmazonEchoApi:
508
528
  "software_version": AMAZON_DEVICE_SOFTWARE_VERSION,
509
529
  },
510
530
  "auth_data": {
531
+ "use_global_authentication": "true",
511
532
  "client_id": self._build_client_id(),
512
533
  "authorization_code": authorization_code,
513
534
  "code_verifier": code_verifier.decode(),
@@ -523,7 +544,7 @@ class AmazonEchoApi:
523
544
  ],
524
545
  }
525
546
 
526
- register_url = f"https://api.amazon.{self._domain}/auth/register"
547
+ register_url = "https://api.amazon.com/auth/register"
527
548
  _, resp = await self._session_request(
528
549
  method=HTTPMethod.POST,
529
550
  url=register_url,
@@ -573,31 +594,9 @@ class AmazonEchoApi:
573
594
  "device_info": device_info,
574
595
  "customer_info": customer_info,
575
596
  }
576
- await self._save_to_file(login_data, "login_data", JSON_EXTENSION)
597
+ _LOGGER.info("Register device: %s", scrub_fields(login_data))
577
598
  return login_data
578
599
 
579
- async def _check_country(self) -> None:
580
- """Check if user selected country matches Amazon account country."""
581
- url = f"https://alexa.amazon.{self._domain}/api/users/me"
582
- _, resp_me = await self._session_request(HTTPMethod.GET, url)
583
-
584
- if resp_me.status != HTTPStatus.OK:
585
- raise CannotAuthenticate
586
-
587
- resp_me_json = await resp_me.json()
588
- amazon_market = resp_me_json["marketPlaceDomainName"]
589
-
590
- if amazon_market not in self._market:
591
- _LOGGER.warning(
592
- "Selected country <%s> doesn't match Amazon API reply:\n%s\n vs \n%s",
593
- self._login_country_code.upper(),
594
- {"input ": self._market},
595
- {"amazon": amazon_market},
596
- )
597
- raise WrongCountry
598
-
599
- _LOGGER.debug("User selected country matches Amazon API one")
600
-
601
600
  async def _get_devices_ids(self) -> list[dict[str, str]]:
602
601
  """Retrieve devices entityId and applianceId."""
603
602
  _, raw_resp = await self._session_request(
@@ -728,6 +727,22 @@ class AmazonEchoApi:
728
727
  bool(otp_code),
729
728
  )
730
729
 
730
+ device_login_data = await self._login_mode_interactive_oauth(otp_code)
731
+
732
+ login_data = await self._register_device(device_login_data)
733
+ self._login_stored_data = login_data
734
+
735
+ await self._domain_refresh_auth_cookies()
736
+
737
+ self._login_stored_data.update({"site": f"https://www.amazon.{self._domain}"})
738
+ await self._save_to_file(self._login_stored_data, "login_data", JSON_EXTENSION)
739
+
740
+ return self._login_stored_data
741
+
742
+ async def _login_mode_interactive_oauth(
743
+ self, otp_code: str
744
+ ) -> dict[str, str | bytes]:
745
+ """Login interactive via oauth URL."""
731
746
  code_verifier = self._create_code_verifier()
732
747
  client_id = self._build_client_id()
733
748
 
@@ -772,21 +787,12 @@ class AmazonEchoApi:
772
787
  authcode = self._extract_code_from_url(login_resp.url)
773
788
  _LOGGER.debug("Login extracted authcode: %s", authcode)
774
789
 
775
- device_login_data = {
790
+ return {
776
791
  "authorization_code": authcode,
777
792
  "code_verifier": code_verifier,
778
793
  "domain": self._domain,
779
794
  }
780
795
 
781
- register_device = await self._register_device(device_login_data)
782
- self._login_stored_data = register_device
783
-
784
- _LOGGER.info("Register device: %s", scrub_fields(register_device))
785
-
786
- await self._check_country()
787
-
788
- return register_device
789
-
790
796
  async def login_mode_stored_data(self) -> dict[str, Any]:
791
797
  """Login to Amazon using previously stored data."""
792
798
  if not self._login_stored_data:
@@ -801,10 +807,51 @@ class AmazonEchoApi:
801
807
  obfuscate_email(self._login_email),
802
808
  )
803
809
 
804
- await self._check_country()
805
-
806
810
  return self._login_stored_data
807
811
 
812
+ async def _get_alexa_domain(self) -> str:
813
+ """Get the Alexa domain."""
814
+ _LOGGER.debug("Retrieve Alexa domain")
815
+ _, raw_resp = await self._session_request(
816
+ method=HTTPMethod.GET,
817
+ url=f"https://alexa.amazon.{self._domain}/api/welcome",
818
+ )
819
+ json_data = await raw_resp.json()
820
+ return cast(
821
+ "str", json_data.get("alexaHostName", f"alexa.amazon.{self._domain}")
822
+ )
823
+
824
+ async def _refresh_auth_cookies(self) -> None:
825
+ """Refresh cookies after domain swap."""
826
+ _, json_token_resp = await self._refresh_data(REFRESH_AUTH_COOKIES)
827
+
828
+ # Need to take cookies from response and create them as cookies
829
+ website_cookies = self._login_stored_data["website_cookies"] = {}
830
+ self._session.cookie_jar.clear()
831
+
832
+ cookie_json = json_token_resp["response"]["tokens"]["cookies"]
833
+ for cookie_domain in cookie_json:
834
+ for cookie in cookie_json[cookie_domain]:
835
+ new_cookie_value = cookie["Value"].replace(r'"', r"")
836
+ new_cookie = {cookie["Name"]: new_cookie_value}
837
+ self._session.cookie_jar.update_cookies(new_cookie, URL(cookie_domain))
838
+ website_cookies.update(new_cookie)
839
+ if cookie["Name"] == "session-token":
840
+ self._login_stored_data["store_authentication_cookie"] = {
841
+ "cookie": new_cookie_value
842
+ }
843
+
844
+ async def _domain_refresh_auth_cookies(self) -> None:
845
+ """Refresh cookies after domain swap."""
846
+ _LOGGER.debug("Refreshing auth cookies after domain change")
847
+
848
+ # Get the new Alexa domain
849
+ user_domain = (await self._get_alexa_domain()).replace("alexa", "https://www")
850
+ if user_domain != DEFAULT_SITE:
851
+ _LOGGER.debug("User domain changed to %s", user_domain)
852
+ self._country_specific_data(user_domain)
853
+ await self._refresh_auth_cookies()
854
+
808
855
  async def get_devices_data(
809
856
  self,
810
857
  ) -> dict[str, AmazonDevice]:
@@ -815,9 +862,6 @@ class AmazonEchoApi:
815
862
  method=HTTPMethod.GET,
816
863
  url=f"https://alexa.amazon.{self._domain}{URI_QUERIES[key]}",
817
864
  )
818
- _LOGGER.debug("Response URL: %s", raw_resp.url)
819
- response_code = raw_resp.status
820
- _LOGGER.debug("Response code: |%s|", response_code)
821
865
 
822
866
  response_data = await raw_resp.text()
823
867
  json_data = {} if len(response_data) == 0 else await raw_resp.json()
@@ -867,7 +911,6 @@ class AmazonEchoApi:
867
911
  device_cluster_members=(
868
912
  devices_node["clusterMembers"] or [serial_number]
869
913
  ),
870
- device_locale=preferences_node.get("locale", self._language),
871
914
  online=devices_node["online"],
872
915
  serial_number=serial_number,
873
916
  software_version=devices_node["softwareVersion"],
@@ -939,7 +982,7 @@ class AmazonEchoApi:
939
982
  base_payload = {
940
983
  "deviceType": device.device_type,
941
984
  "deviceSerialNumber": device.serial_number,
942
- "locale": device.device_locale,
985
+ "locale": self._language,
943
986
  "customerId": device.device_owner_customer_id,
944
987
  }
945
988
 
@@ -974,7 +1017,7 @@ class AmazonEchoApi:
974
1017
  "expireAfter": "PT5S",
975
1018
  "content": [
976
1019
  {
977
- "locale": device.device_locale,
1020
+ "locale": self._language,
978
1021
  "display": {
979
1022
  "title": "Home Assistant",
980
1023
  "body": message_body,
@@ -1122,3 +1165,58 @@ class AmazonEchoApi:
1122
1165
  await self._session_request(
1123
1166
  method="PUT", url=url, input_data=payload, json_data=True
1124
1167
  )
1168
+
1169
+ async def _refresh_data(self, data_type: str) -> tuple[bool, dict]:
1170
+ """Refresh data."""
1171
+ if not self._login_stored_data:
1172
+ _LOGGER.debug("No login data available, cannot refresh")
1173
+ return False, {}
1174
+
1175
+ data = {
1176
+ "app_name": AMAZON_APP_NAME,
1177
+ "app_version": AMAZON_APP_VERSION,
1178
+ "di.sdk.version": "6.12.4",
1179
+ "source_token": self._login_stored_data["refresh_token"],
1180
+ "package_name": AMAZON_APP_BUNDLE_ID,
1181
+ "di.hw.version": "iPhone",
1182
+ "platform": "iOS",
1183
+ "requested_token_type": data_type,
1184
+ "source_token_type": "refresh_token",
1185
+ "di.os.name": "iOS",
1186
+ "di.os.version": AMAZON_CLIENT_OS,
1187
+ "current_version": "6.12.4",
1188
+ "previous_version": "6.12.4",
1189
+ "domain": f"www.amazon.{self._domain}",
1190
+ }
1191
+
1192
+ response = await self._session.post(
1193
+ "https://api.amazon.com/auth/token",
1194
+ data=data,
1195
+ )
1196
+ _LOGGER.debug(
1197
+ "Refresh data response %s with payload %s",
1198
+ response.status,
1199
+ orjson.dumps(data),
1200
+ )
1201
+
1202
+ if response.status != HTTPStatus.OK:
1203
+ _LOGGER.debug("Failed to refresh data")
1204
+ return False, {}
1205
+
1206
+ json_response = await response.json()
1207
+ _LOGGER.debug("Refresh data json:\n%s ", json_response)
1208
+
1209
+ if data_type == REFRESH_ACCESS_TOKEN and (
1210
+ new_token := json_response.get(REFRESH_ACCESS_TOKEN)
1211
+ ):
1212
+ self._login_stored_data[REFRESH_ACCESS_TOKEN] = new_token
1213
+ self.expires_in = datetime.now(tz=UTC).timestamp() + int(
1214
+ json_response.get("expires_in")
1215
+ )
1216
+ return True, json_response
1217
+
1218
+ if data_type == REFRESH_AUTH_COOKIES:
1219
+ return True, json_response
1220
+
1221
+ _LOGGER.debug("Unexpected refresh data response")
1222
+ return False, {}
@@ -1,7 +1,6 @@
1
1
  """Constants for Amazon devices."""
2
2
 
3
3
  import logging
4
- from typing import Any
5
4
 
6
5
  _LOGGER = logging.getLogger(__package__)
7
6
 
@@ -31,56 +30,6 @@ TO_REDACT = {
31
30
  "user_id",
32
31
  }
33
32
 
34
- AMAZON_DE_OVERRIDE: dict[str, str] = {
35
- "domain": "de",
36
- "openid.assoc_handle": f"{DEFAULT_ASSOC_HANDLE}_de",
37
- }
38
- AMAZON_US_OVERRIDE: dict[str, str] = {
39
- "domain": "com",
40
- "openid.assoc_handle": DEFAULT_ASSOC_HANDLE,
41
- }
42
-
43
- DOMAIN_BY_ISO3166_COUNTRY: dict[str, dict[str, Any]] = {
44
- "ar": AMAZON_US_OVERRIDE,
45
- "at": AMAZON_DE_OVERRIDE,
46
- "au": {
47
- "domain": "com.au",
48
- "openid.assoc_handle": f"{DEFAULT_ASSOC_HANDLE}_au",
49
- },
50
- "be": {
51
- "domain": "com.be",
52
- },
53
- "br": AMAZON_US_OVERRIDE | {"market": "https://www.amazon.com.br"},
54
- "gb": {
55
- "domain": "co.uk",
56
- "openid.assoc_handle": f"{DEFAULT_ASSOC_HANDLE}_uk",
57
- },
58
- "il": AMAZON_US_OVERRIDE,
59
- "jp": {
60
- "domain": "co.jp",
61
- },
62
- "mx": {
63
- "domain": "com.mx",
64
- },
65
- "nl": {
66
- "domain": "nl",
67
- "market": "https://www.amazon.co.uk",
68
- },
69
- "no": AMAZON_DE_OVERRIDE,
70
- "nz": {
71
- "domain": "com.au",
72
- "openid.assoc_handle": f"{DEFAULT_ASSOC_HANDLE}_au",
73
- },
74
- "pl": AMAZON_US_OVERRIDE,
75
- "tr": {
76
- "domain": "com.tr",
77
- },
78
- "us": AMAZON_US_OVERRIDE,
79
- "za": {
80
- "domain": "co.za",
81
- },
82
- }
83
-
84
33
  # Amazon APP info
85
34
  AMAZON_APP_BUNDLE_ID = "com.amazon.echo"
86
35
  AMAZON_APP_ID = "MAPiOSLib/6.0/ToHideRetailLink"
@@ -90,6 +39,7 @@ AMAZON_DEVICE_SOFTWARE_VERSION = "35602678"
90
39
  AMAZON_DEVICE_TYPE = "A2IVLV5VM2W81"
91
40
  AMAZON_CLIENT_OS = "18.5"
92
41
 
42
+ DEFAULT_SITE = "https://www.amazon.com"
93
43
  DEFAULT_HEADERS = {
94
44
  "User-Agent": (
95
45
  f"AmazonWebView/AmazonAlexa/{AMAZON_APP_VERSION}/iOS/{AMAZON_CLIENT_OS}/iPhone"
@@ -101,6 +51,9 @@ DEFAULT_HEADERS = {
101
51
  DEFAULT_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0" # noqa: E501
102
52
  CSRF_COOKIE = "csrf"
103
53
 
54
+ REFRESH_ACCESS_TOKEN = "access_token" # noqa: S105
55
+ REFRESH_AUTH_COOKIES = "auth_cookies"
56
+
104
57
  NODE_DEVICES = "devices"
105
58
  NODE_DO_NOT_DISTURB = "doNotDisturbDeviceStatusList"
106
59
  NODE_PREFERENCES = "devicePreferences"
@@ -228,6 +181,11 @@ DEVICE_TYPE_TO_MODEL: dict[str, dict[str, str | None]] = {
228
181
  "model": "FireTV 4k MAX",
229
182
  "hw_version": "Gen2",
230
183
  },
184
+ "A1X92YQU8MWAPD": {
185
+ "manufacturer": "Devialet",
186
+ "model": "Freebox Delta",
187
+ "hw_version": None,
188
+ },
231
189
  "A1XWJRHALS1REP": {
232
190
  "model": "Echo Show 5",
233
191
  "hw_version": "Gen2",
@@ -379,7 +337,7 @@ DEVICE_TYPE_TO_MODEL: dict[str, dict[str, str | None]] = {
379
337
  "hw_version": None,
380
338
  },
381
339
  "A3RMGO6LYLH7YN": {
382
- "model": "Echo Dot",
340
+ "model": "Echo",
383
341
  "hw_version": "Gen4",
384
342
  },
385
343
  "A3S5BH2HU6VAYF": {
@@ -411,6 +369,10 @@ DEVICE_TYPE_TO_MODEL: dict[str, dict[str, str | None]] = {
411
369
  "model": "Echo",
412
370
  "hw_version": "Gen2",
413
371
  },
372
+ "ADMKNMEVNL158": {
373
+ "model": "Echo Hub",
374
+ "hw_version": "Gen1",
375
+ },
414
376
  "ADOUDFQX2QVX0": {
415
377
  "model": "Fire TV Omni QLED",
416
378
  "hw_version": None,
@@ -25,7 +25,3 @@ 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."""