aioamazondevices 3.0.2__tar.gz → 3.0.4__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.0.2
3
+ Version: 3.0.4
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
  [tool.poetry]
2
2
  name = "aioamazondevices"
3
- version = "3.0.2"
3
+ version = "3.0.4"
4
4
  description = "Python library to control Amazon devices"
5
5
  authors = ["Simone Chemelli <simone.chemelli@gmail.com>"]
6
6
  license = "Apache-2.0"
@@ -1,6 +1,6 @@
1
1
  """aioamazondevices library."""
2
2
 
3
- __version__ = "3.0.2"
3
+ __version__ = "3.0.4"
4
4
 
5
5
 
6
6
  from .api import AmazonDevice, AmazonEchoApi
@@ -18,7 +18,9 @@ import orjson
18
18
  from aiohttp import ClientResponse, ClientSession
19
19
  from babel import Locale
20
20
  from bs4 import BeautifulSoup, Tag
21
- from yarl import URL
21
+ from httpx import URL as HTTPX_URL
22
+ from multidict import MultiDictProxy
23
+ from yarl import URL as YARL_URL
22
24
 
23
25
  from .const import (
24
26
  _LOGGER,
@@ -116,7 +118,6 @@ class AmazonEchoApi:
116
118
  self._domain = domain
117
119
  self._cookies = self._build_init_cookies()
118
120
  self._csrf_cookie: str | None = None
119
- self._headers = DEFAULT_HEADERS
120
121
  self._save_raw_data = save_raw_data
121
122
  self._login_stored_data = login_data
122
123
  self._serial = self._serial_number()
@@ -162,7 +163,7 @@ class AmazonEchoApi:
162
163
  map_md_str = orjson.dumps(map_md_dict).decode("utf-8")
163
164
  map_md = base64.b64encode(map_md_str.encode()).decode().rstrip("=")
164
165
 
165
- return {"frc": frc, "map-md": map_md, "amzn-app-id": AMAZON_APP_ID}
166
+ return {"amzn-app-id": AMAZON_APP_ID, "frc": frc, "map-md": map_md}
166
167
 
167
168
  def _create_code_verifier(self, length: int = 32) -> bytes:
168
169
  """Create code verifier."""
@@ -213,11 +214,11 @@ class AmazonEchoApi:
213
214
  form = soup.find("form", {"name": "signIn"}) or soup.find("form")
214
215
 
215
216
  if not isinstance(form, Tag):
216
- raise TypeError("No form found in page or something other is going wrong.")
217
+ raise TypeError("Unable to find form in login response")
217
218
 
218
219
  inputs = {}
219
220
  for field in form.find_all("input"):
220
- if field.get("type") and field["type"] == "hidden":
221
+ if isinstance(field, Tag) and field.get("type", "") == "hidden":
221
222
  inputs[field["name"]] = field.get("value", "")
222
223
 
223
224
  return inputs
@@ -227,15 +228,22 @@ class AmazonEchoApi:
227
228
  _LOGGER.debug("Get request data from HTML source")
228
229
  form = soup.find("form", {"name": "signIn"}) or soup.find("form")
229
230
  if isinstance(form, Tag):
230
- method = form["method"]
231
- url = form["action"]
231
+ method = form.get("method")
232
+ url = form.get("action")
232
233
  if isinstance(method, str) and isinstance(url, str):
233
234
  return method, url
234
- raise TypeError("Unable to extract form data from response.")
235
+ raise TypeError("Unable to extract form data from response")
235
236
 
236
- def _extract_code_from_url(self, url: URL) -> str:
237
+ def _extract_code_from_url(self, url: YARL_URL | HTTPX_URL) -> str:
237
238
  """Extract the access token from url query after login."""
238
- parsed_url = parse_qs(url.query.decode())
239
+ parsed_url: dict[str, list[str]] = {}
240
+ if isinstance(url.query, bytes):
241
+ parsed_url = parse_qs(url.query.decode())
242
+ elif isinstance(url.query, MultiDictProxy):
243
+ for key, value in url.query.items():
244
+ parsed_url[key] = [value]
245
+ else:
246
+ raise TypeError(f"Unable to extract authorization code from url: {url}")
239
247
  return parsed_url["openid.oa2.authorization_code"][0]
240
248
 
241
249
  def _client_session(self) -> None:
@@ -281,9 +289,13 @@ class AmazonEchoApi:
281
289
  _LOGGER.debug("Adding %s to headers", json_header)
282
290
  headers.update(json_header)
283
291
 
292
+ _url: YARL_URL | str = url
293
+ if LIBRARY == "aiohttp":
294
+ _url = YARL_URL(url, encoded=True)
295
+
284
296
  resp = await self.session.request(
285
297
  method,
286
- url,
298
+ _url,
287
299
  data=input_data if not json_data else orjson.dumps(input_data),
288
300
  cookies=self._load_website_cookies(),
289
301
  headers=headers,
@@ -325,7 +337,8 @@ class AmazonEchoApi:
325
337
  base_filename = url
326
338
  fullpath = Path(output_dir, base_filename + extension)
327
339
 
328
- if type(raw_data) is dict:
340
+ data: str
341
+ if isinstance(raw_data, dict):
329
342
  data = orjson.dumps(raw_data, option=orjson.OPT_INDENT_2).decode("utf-8")
330
343
  elif extension in [HTML_EXTENSION, BIN_EXTENSION]:
331
344
  data = raw_data
@@ -484,22 +497,13 @@ class AmazonEchoApi:
484
497
  url=login_url,
485
498
  input_data=login_inputs,
486
499
  )
500
+ _LOGGER.debug("Login response url:%s", login_resp.url)
487
501
 
488
- authcode_url = None
489
- _LOGGER.debug("Login query: %s", login_resp.url.query)
490
- if b"openid.oa2.authorization_code" in login_resp.url.query:
491
- authcode_url = login_resp.url
492
- elif len(login_resp.history) > 0:
493
- for history in login_resp.history:
494
- if b"openid.oa2.authorization_code" in history.url.query:
495
- authcode_url = history.url
496
- break
497
-
498
- if authcode_url is None:
499
- raise CannotAuthenticate
502
+ authcode = self._extract_code_from_url(login_resp.url)
503
+ _LOGGER.debug("Login extracted authcode: %s", authcode)
500
504
 
501
505
  device_login_data = {
502
- "authorization_code": self._extract_code_from_url(authcode_url),
506
+ "authorization_code": authcode,
503
507
  "code_verifier": code_verifier,
504
508
  "domain": self._domain,
505
509
  }
@@ -13,6 +13,7 @@ DOMAIN_BY_ISO3166_COUNTRY = {
13
13
  },
14
14
  "gb": {
15
15
  "domain": "co.uk",
16
+ "openid.assoc_handle": f"{DEFAULT_ASSOC_HANDLE}_uk",
16
17
  },
17
18
  "au": {
18
19
  "domain": "com.au",
@@ -42,6 +43,7 @@ DEFAULT_HEADERS = {
42
43
  ),
43
44
  "Accept-Language": "en-US",
44
45
  "Accept-Encoding": "gzip",
46
+ "Connection": "keep-alive",
45
47
  }
46
48
  CSRF_COOKIE = "csrf"
47
49
 
@@ -75,13 +77,17 @@ DEVICE_TYPE_TO_MODEL: dict[str, dict[str, str | None]] = {
75
77
  "hw_version": "Gen3",
76
78
  },
77
79
  "A1Q6UGEXJZWJQ0": {
78
- "model": "Fire TV Stick",
79
- "hw_version": "4K",
80
+ "model": "Fire TV Stick 4K",
81
+ "hw_version": "Gen2",
80
82
  },
81
83
  "A1RABVCI4QCIKC": {
82
84
  "model": "Echo Dot",
83
85
  "hw_version": "Gen3",
84
86
  },
87
+ "A271DR1789MXDS": {
88
+ "model": "Fire Tablet 7",
89
+ "hw_version": "Gen12",
90
+ },
85
91
  "A2DS1Q2TPDJ48U": {
86
92
  "model": "Echo Dot Clock",
87
93
  "hw_version": "Gen5",
@@ -95,8 +101,8 @@ DEVICE_TYPE_TO_MODEL: dict[str, dict[str, str | None]] = {
95
101
  "hw_version": "Gen2",
96
102
  },
97
103
  "A2M4YX06LWP8WI": {
98
- "model": "Fire Tablet",
99
- "hw_version": "Gen1",
104
+ "model": "Fire Tablet 7",
105
+ "hw_version": "Gen5",
100
106
  },
101
107
  "A2U21SRK4QGSE1": {
102
108
  "model": "Echo Dot Clock",
@@ -106,6 +112,10 @@ DEVICE_TYPE_TO_MODEL: dict[str, dict[str, str | None]] = {
106
112
  "model": "Echo Auto",
107
113
  "hw_version": "Gen1",
108
114
  },
115
+ "A30YDR2MK8HMRV": {
116
+ "model": "Echo Dot",
117
+ "hw_version": "Gen3",
118
+ },
109
119
  "A32DDESGESSHZA": {
110
120
  "model": "Echo Dot",
111
121
  "hw_version": "Gen3",
@@ -126,6 +136,10 @@ DEVICE_TYPE_TO_MODEL: dict[str, dict[str, str | None]] = {
126
136
  "model": "Echo Dot",
127
137
  "hw_version": "Gen2",
128
138
  },
139
+ "A3VRME03NAXFUB": {
140
+ "model": "Echo Flex",
141
+ "hw_version": "None",
142
+ },
129
143
  "A4ZP7ZC4PI6TO": {
130
144
  "model": "Echo Show 3",
131
145
  "hw_version": "Gen1",
@@ -146,6 +160,18 @@ DEVICE_TYPE_TO_MODEL: dict[str, dict[str, str | None]] = {
146
160
  "model": "Echo Dot",
147
161
  "hw_version": "Gen1",
148
162
  },
163
+ "AKPGW064GI9HE": {
164
+ "model": " Fire TV Stick 4K",
165
+ "hw_version": "Gen1",
166
+ },
167
+ "ATNLRCEBX3W4P": {
168
+ "model": "Fire Tablet HD 10",
169
+ "hw_version": "Gen11",
170
+ },
171
+ "AVU7CPPF2ZRAS": {
172
+ "model": "Fire Tablet HD 8 Plus",
173
+ "hw_version": "Gen10",
174
+ },
149
175
  "G2A0V704840708AP": {
150
176
  "model": "Echo Plus",
151
177
  "hw_version": "Gen2",