aioamazondevices 1.3.0__tar.gz → 1.4.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.
- {aioamazondevices-1.3.0 → aioamazondevices-1.4.1}/PKG-INFO +3 -4
- {aioamazondevices-1.3.0 → aioamazondevices-1.4.1}/pyproject.toml +3 -4
- {aioamazondevices-1.3.0 → aioamazondevices-1.4.1}/src/aioamazondevices/__init__.py +1 -1
- {aioamazondevices-1.3.0 → aioamazondevices-1.4.1}/src/aioamazondevices/api.py +26 -25
- {aioamazondevices-1.3.0 → aioamazondevices-1.4.1}/src/aioamazondevices/const.py +2 -0
- {aioamazondevices-1.3.0 → aioamazondevices-1.4.1}/LICENSE +0 -0
- {aioamazondevices-1.3.0 → aioamazondevices-1.4.1}/README.md +0 -0
- {aioamazondevices-1.3.0 → aioamazondevices-1.4.1}/src/aioamazondevices/exceptions.py +0 -0
- {aioamazondevices-1.3.0 → aioamazondevices-1.4.1}/src/aioamazondevices/py.typed +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.3
|
2
2
|
Name: aioamazondevices
|
3
|
-
Version: 1.
|
3
|
+
Version: 1.4.1
|
4
4
|
Summary: Python library to control Amazon devices
|
5
5
|
License: Apache-2.0
|
6
6
|
Author: Simone Chemelli
|
@@ -15,13 +15,12 @@ Classifier: Programming Language :: Python :: 3
|
|
15
15
|
Classifier: Programming Language :: Python :: 3.12
|
16
16
|
Classifier: Programming Language :: Python :: 3.13
|
17
17
|
Classifier: Topic :: Software Development :: Libraries
|
18
|
+
Requires-Dist: aiohttp
|
18
19
|
Requires-Dist: babel
|
19
20
|
Requires-Dist: beautifulsoup4
|
20
21
|
Requires-Dist: colorlog
|
21
|
-
Requires-Dist: httpx
|
22
22
|
Requires-Dist: orjson
|
23
|
-
Requires-Dist:
|
24
|
-
Requires-Dist: rsa
|
23
|
+
Requires-Dist: yarl
|
25
24
|
Project-URL: Bug Tracker, https://github.com/chemelli74/aioamazondevices/issues
|
26
25
|
Project-URL: Changelog, https://github.com/chemelli74/aioamazondevices/blob/main/CHANGELOG.md
|
27
26
|
Project-URL: Repository, https://github.com/chemelli74/aioamazondevices
|
@@ -1,6 +1,6 @@
|
|
1
1
|
[tool.poetry]
|
2
2
|
name = "aioamazondevices"
|
3
|
-
version = "1.
|
3
|
+
version = "1.4.1"
|
4
4
|
description = "Python library to control Amazon devices"
|
5
5
|
authors = ["Simone Chemelli <simone.chemelli@gmail.com>"]
|
6
6
|
license = "Apache-2.0"
|
@@ -22,14 +22,13 @@ packages = [
|
|
22
22
|
"Changelog" = "https://github.com/chemelli74/aioamazondevices/blob/main/CHANGELOG.md"
|
23
23
|
|
24
24
|
[tool.poetry.dependencies]
|
25
|
+
aiohttp = "*"
|
25
26
|
python = "^3.12"
|
26
27
|
babel = "*"
|
27
28
|
beautifulsoup4 = "*"
|
28
29
|
colorlog = "*"
|
29
|
-
httpx = "*"
|
30
30
|
orjson = "*"
|
31
|
-
|
32
|
-
rsa = "*"
|
31
|
+
yarl = "*"
|
33
32
|
|
34
33
|
[tool.poetry.group.dev.dependencies]
|
35
34
|
pytest = "^8.1"
|
@@ -8,14 +8,16 @@ import uuid
|
|
8
8
|
from dataclasses import dataclass
|
9
9
|
from datetime import UTC, datetime, timedelta
|
10
10
|
from http import HTTPStatus
|
11
|
+
from http.cookies import SimpleCookie
|
11
12
|
from pathlib import Path
|
12
13
|
from typing import Any, cast
|
13
14
|
from urllib.parse import parse_qs, urlencode
|
14
15
|
|
15
16
|
import orjson
|
17
|
+
from aiohttp import ClientResponse, ClientSession
|
16
18
|
from babel import Locale
|
17
19
|
from bs4 import BeautifulSoup, Tag
|
18
|
-
from
|
20
|
+
from yarl import URL
|
19
21
|
|
20
22
|
from .const import (
|
21
23
|
_LOGGER,
|
@@ -95,14 +97,14 @@ class AmazonEchoApi:
|
|
95
97
|
self._login_stored_data = login_data
|
96
98
|
self._serial = self._serial_number()
|
97
99
|
|
98
|
-
self.session:
|
100
|
+
self.session: ClientSession
|
99
101
|
|
100
|
-
def _load_website_cookies(self) ->
|
102
|
+
def _load_website_cookies(self) -> list[SimpleCookie]:
|
101
103
|
"""Get website cookies, if avaliables."""
|
102
104
|
if not self._login_stored_data:
|
103
|
-
return
|
105
|
+
return []
|
104
106
|
|
105
|
-
return cast("
|
107
|
+
return cast("list", self._login_stored_data["website_cookies"])
|
106
108
|
|
107
109
|
def _serial_number(self) -> str:
|
108
110
|
"""Get or calculate device serial number."""
|
@@ -213,13 +215,11 @@ class AmazonEchoApi:
|
|
213
215
|
|
214
216
|
def _client_session(self) -> None:
|
215
217
|
"""Create HTTP client session."""
|
216
|
-
if not hasattr(self, "session") or self.session.
|
217
|
-
_LOGGER.debug("Creating HTTP session (
|
218
|
-
self.session =
|
219
|
-
base_url=f"https://www.amazon.{self._domain}",
|
218
|
+
if not hasattr(self, "session") or self.session.closed:
|
219
|
+
_LOGGER.debug("Creating HTTP session (aiohttp)")
|
220
|
+
self.session = ClientSession(
|
220
221
|
headers=DEFAULT_HEADERS,
|
221
222
|
cookies=self._cookies,
|
222
|
-
follow_redirects=True,
|
223
223
|
)
|
224
224
|
|
225
225
|
async def _session_request(
|
@@ -228,7 +228,7 @@ class AmazonEchoApi:
|
|
228
228
|
url: str,
|
229
229
|
input_data: dict[str, Any] | None = None,
|
230
230
|
json_data: bool = False,
|
231
|
-
) -> tuple[BeautifulSoup,
|
231
|
+
) -> tuple[BeautifulSoup, ClientResponse]:
|
232
232
|
"""Return request response context data."""
|
233
233
|
_LOGGER.debug(
|
234
234
|
"%s request: %s with payload %s [json=%s]",
|
@@ -255,22 +255,23 @@ class AmazonEchoApi:
|
|
255
255
|
data=input_data if not json_data else orjson.dumps(input_data),
|
256
256
|
cookies=self._load_website_cookies(),
|
257
257
|
headers=headers,
|
258
|
+
allow_redirects=True,
|
258
259
|
)
|
259
260
|
content_type: str = resp.headers.get("Content-Type", "")
|
260
261
|
_LOGGER.debug(
|
261
262
|
"Response %s for url %s with content type: %s",
|
262
|
-
resp.
|
263
|
+
resp.status,
|
263
264
|
url,
|
264
265
|
content_type,
|
265
266
|
)
|
266
267
|
|
267
268
|
await self._save_to_file(
|
268
|
-
resp.text,
|
269
|
+
await resp.text(),
|
269
270
|
url,
|
270
271
|
mimetypes.guess_extension(content_type.split(";")[0]) or ".raw",
|
271
272
|
)
|
272
273
|
|
273
|
-
return BeautifulSoup(resp.
|
274
|
+
return BeautifulSoup(await resp.read(), "html.parser"), resp
|
274
275
|
|
275
276
|
async def _save_to_file(
|
276
277
|
self,
|
@@ -311,7 +312,7 @@ class AmazonEchoApi:
|
|
311
312
|
|
312
313
|
_LOGGER.warning("Saving data to %s", fullpath)
|
313
314
|
|
314
|
-
with Path.open(fullpath, "w
|
315
|
+
with Path.open(fullpath, mode="w", encoding="utf-8") as file:
|
315
316
|
file.write(data)
|
316
317
|
file.write("\n")
|
317
318
|
|
@@ -364,7 +365,7 @@ class AmazonEchoApi:
|
|
364
365
|
)
|
365
366
|
resp_json = resp.json()
|
366
367
|
|
367
|
-
if resp.
|
368
|
+
if resp.status != HTTPStatus.OK:
|
368
369
|
_LOGGER.error(
|
369
370
|
"Cannot register device for %s: %s",
|
370
371
|
self._login_email,
|
@@ -499,8 +500,8 @@ class AmazonEchoApi:
|
|
499
500
|
async def close(self) -> None:
|
500
501
|
"""Close http client session."""
|
501
502
|
if hasattr(self, "session"):
|
502
|
-
_LOGGER.debug("Closing HTTP session (
|
503
|
-
await self.session.
|
503
|
+
_LOGGER.debug("Closing HTTP session (aiohttp)")
|
504
|
+
await self.session.close()
|
504
505
|
|
505
506
|
async def get_devices_data(
|
506
507
|
self,
|
@@ -513,16 +514,16 @@ class AmazonEchoApi:
|
|
513
514
|
url=f"https://alexa.amazon.{self._domain}{URI_QUERIES[key]}",
|
514
515
|
)
|
515
516
|
_LOGGER.debug("Response URL: %s", raw_resp.url)
|
516
|
-
response_code = raw_resp.
|
517
|
+
response_code = raw_resp.status
|
517
518
|
_LOGGER.debug("Response code: |%s|", response_code)
|
518
519
|
|
519
|
-
response_data = raw_resp.text
|
520
|
+
response_data = await raw_resp.text()
|
520
521
|
_LOGGER.debug("Response data: |%s|", response_data)
|
521
522
|
|
522
523
|
if not self._csrf_cookie:
|
523
|
-
self._csrf_cookie = raw_resp.cookies.get(CSRF_COOKIE)
|
524
|
+
self._csrf_cookie = raw_resp.cookies.get(CSRF_COOKIE).value
|
524
525
|
|
525
|
-
json_data = {} if len(response_data) == 0 else raw_resp.json()
|
526
|
+
json_data = {} if len(response_data) == 0 else await raw_resp.json()
|
526
527
|
|
527
528
|
_LOGGER.debug("JSON data: |%s|", json_data)
|
528
529
|
|
@@ -566,14 +567,14 @@ class AmazonEchoApi:
|
|
566
567
|
method="GET",
|
567
568
|
url=f"https://alexa.amazon.{self._domain}/api/bootstrap?version=0",
|
568
569
|
)
|
569
|
-
if raw_resp.
|
570
|
+
if raw_resp.status != HTTPStatus.OK:
|
570
571
|
_LOGGER.debug(
|
571
572
|
"Session not authenticated: reply error %s",
|
572
|
-
raw_resp.
|
573
|
+
raw_resp.status,
|
573
574
|
)
|
574
575
|
return False
|
575
576
|
|
576
|
-
resp_json = raw_resp.json()
|
577
|
+
resp_json = await raw_resp.json()
|
577
578
|
if not (authentication := resp_json.get("authentication")):
|
578
579
|
_LOGGER.debug('Session not authenticated: reply missing "authentication"')
|
579
580
|
return False
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|