aioamazondevices 3.0.1__tar.gz → 3.0.3__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.
- {aioamazondevices-3.0.1 → aioamazondevices-3.0.3}/PKG-INFO +1 -1
- {aioamazondevices-3.0.1 → aioamazondevices-3.0.3}/pyproject.toml +1 -1
- {aioamazondevices-3.0.1 → aioamazondevices-3.0.3}/src/aioamazondevices/__init__.py +1 -1
- {aioamazondevices-3.0.1 → aioamazondevices-3.0.3}/src/aioamazondevices/api.py +30 -26
- {aioamazondevices-3.0.1 → aioamazondevices-3.0.3}/src/aioamazondevices/const.py +64 -11
- {aioamazondevices-3.0.1 → aioamazondevices-3.0.3}/LICENSE +0 -0
- {aioamazondevices-3.0.1 → aioamazondevices-3.0.3}/README.md +0 -0
- {aioamazondevices-3.0.1 → aioamazondevices-3.0.3}/src/aioamazondevices/exceptions.py +0 -0
- {aioamazondevices-3.0.1 → aioamazondevices-3.0.3}/src/aioamazondevices/httpx.py +0 -0
- {aioamazondevices-3.0.1 → aioamazondevices-3.0.3}/src/aioamazondevices/py.typed +0 -0
- {aioamazondevices-3.0.1 → aioamazondevices-3.0.3}/src/aioamazondevices/sounds.py +0 -0
@@ -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
|
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,13 +118,12 @@ 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()
|
123
124
|
self._list_for_clusters: dict[str, str] = {}
|
124
125
|
|
125
|
-
self.session: ClientSession
|
126
|
+
self.session: ClientSession | HttpxClientSession
|
126
127
|
|
127
128
|
def _load_website_cookies(self) -> dict[str, str]:
|
128
129
|
"""Get website cookies, if avaliables."""
|
@@ -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 {"
|
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("
|
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"
|
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
|
231
|
-
url = form
|
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:
|
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 =
|
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
|
-
|
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
|
-
|
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
|
-
|
489
|
-
_LOGGER.debug("Login
|
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":
|
506
|
+
"authorization_code": authcode,
|
503
507
|
"code_verifier": code_verifier,
|
504
508
|
"domain": self._domain,
|
505
509
|
}
|
@@ -42,6 +42,7 @@ DEFAULT_HEADERS = {
|
|
42
42
|
),
|
43
43
|
"Accept-Language": "en-US",
|
44
44
|
"Accept-Encoding": "gzip",
|
45
|
+
"Connection": "keep-alive",
|
45
46
|
}
|
46
47
|
CSRF_COOKIE = "csrf"
|
47
48
|
|
@@ -66,10 +67,26 @@ BIN_EXTENSION = ".bin"
|
|
66
67
|
SPEAKER_GROUP_MODEL = "Speaker Group"
|
67
68
|
|
68
69
|
DEVICE_TYPE_TO_MODEL: dict[str, dict[str, str | None]] = {
|
70
|
+
"A10A33FOX2NUBK": {
|
71
|
+
"model": "Echo Spot",
|
72
|
+
"hw_version": "Gen1",
|
73
|
+
},
|
74
|
+
"A11QM4H9HGV71H": {
|
75
|
+
"model": "Echo Show 5",
|
76
|
+
"hw_version": "Gen3",
|
77
|
+
},
|
78
|
+
"A1Q6UGEXJZWJQ0": {
|
79
|
+
"model": "Fire TV Stick 4K",
|
80
|
+
"hw_version": "Gen2",
|
81
|
+
},
|
69
82
|
"A1RABVCI4QCIKC": {
|
70
83
|
"model": "Echo Dot",
|
71
84
|
"hw_version": "Gen3",
|
72
85
|
},
|
86
|
+
"A271DR1789MXDS": {
|
87
|
+
"model": "Fire Tablet 7",
|
88
|
+
"hw_version": "Gen12",
|
89
|
+
},
|
73
90
|
"A2DS1Q2TPDJ48U": {
|
74
91
|
"model": "Echo Dot Clock",
|
75
92
|
"hw_version": "Gen5",
|
@@ -78,10 +95,26 @@ DEVICE_TYPE_TO_MODEL: dict[str, dict[str, str | None]] = {
|
|
78
95
|
"model": "Echo Dot Clock",
|
79
96
|
"hw_version": "Gen4",
|
80
97
|
},
|
98
|
+
"A2LWARUGJLBYEW": {
|
99
|
+
"model": "Fire TV Stick",
|
100
|
+
"hw_version": "Gen2",
|
101
|
+
},
|
102
|
+
"A2M4YX06LWP8WI": {
|
103
|
+
"model": "Fire Tablet 7",
|
104
|
+
"hw_version": "Gen5",
|
105
|
+
},
|
81
106
|
"A2U21SRK4QGSE1": {
|
82
107
|
"model": "Echo Dot Clock",
|
83
108
|
"hw_version": "Gen4",
|
84
109
|
},
|
110
|
+
"A303PJF6ISQ7IC": {
|
111
|
+
"model": "Echo Auto",
|
112
|
+
"hw_version": "Gen1",
|
113
|
+
},
|
114
|
+
"A30YDR2MK8HMRV": {
|
115
|
+
"model": "Echo Dot",
|
116
|
+
"hw_version": "Gen3",
|
117
|
+
},
|
85
118
|
"A32DDESGESSHZA": {
|
86
119
|
"model": "Echo Dot",
|
87
120
|
"hw_version": "Gen3",
|
@@ -90,6 +123,10 @@ DEVICE_TYPE_TO_MODEL: dict[str, dict[str, str | None]] = {
|
|
90
123
|
"model": "Echo Dot",
|
91
124
|
"hw_version": "Gen3",
|
92
125
|
},
|
126
|
+
"A3C9PE6TNYLTCH": {
|
127
|
+
"model": "Speaker Group",
|
128
|
+
"hw_version": "None",
|
129
|
+
},
|
93
130
|
"A3RMGO6LYLH7YN": {
|
94
131
|
"model": "Echo Dot",
|
95
132
|
"hw_version": "Gen4",
|
@@ -98,28 +135,44 @@ DEVICE_TYPE_TO_MODEL: dict[str, dict[str, str | None]] = {
|
|
98
135
|
"model": "Echo Dot",
|
99
136
|
"hw_version": "Gen2",
|
100
137
|
},
|
138
|
+
"A3VRME03NAXFUB": {
|
139
|
+
"model": "Echo Flex",
|
140
|
+
"hw_version": "None",
|
141
|
+
},
|
142
|
+
"A4ZP7ZC4PI6TO": {
|
143
|
+
"model": "Echo Show 3",
|
144
|
+
"hw_version": "Gen1",
|
145
|
+
},
|
101
146
|
"A4ZXE0RM7LQ7A": {
|
102
147
|
"model": "Echo Dot",
|
103
148
|
"hw_version": "Gen5",
|
104
149
|
},
|
150
|
+
"A7WXQPH584YP": {
|
151
|
+
"model": "Echo Dot",
|
152
|
+
"hw_version": "Gen2",
|
153
|
+
},
|
154
|
+
"AB72C64C86AW2": {
|
155
|
+
"model": "Echo Dot",
|
156
|
+
"hw_version": "Gen2",
|
157
|
+
},
|
105
158
|
"AKNO1N0KSFN8L": {
|
106
159
|
"model": "Echo Dot",
|
107
160
|
"hw_version": "Gen1",
|
108
161
|
},
|
109
|
-
"
|
110
|
-
"model":
|
111
|
-
"hw_version":
|
162
|
+
"AKPGW064GI9HE": {
|
163
|
+
"model": " Fire TV Stick 4K",
|
164
|
+
"hw_version": "Gen1",
|
112
165
|
},
|
113
|
-
"
|
114
|
-
"model": "Fire
|
115
|
-
"hw_version": "
|
166
|
+
"ATNLRCEBX3W4P": {
|
167
|
+
"model": "Fire Tablet HD 10",
|
168
|
+
"hw_version": "Gen11",
|
116
169
|
},
|
117
|
-
"
|
118
|
-
"model": "
|
119
|
-
"hw_version": "
|
170
|
+
"AVU7CPPF2ZRAS": {
|
171
|
+
"model": "Fire Tablet HD 8 Plus",
|
172
|
+
"hw_version": "Gen10",
|
120
173
|
},
|
121
|
-
"
|
122
|
-
"model": "Echo
|
174
|
+
"G2A0V704840708AP": {
|
175
|
+
"model": "Echo Plus",
|
123
176
|
"hw_version": "Gen2",
|
124
177
|
},
|
125
178
|
}
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|