aioamazondevices 6.1.1__py3-none-any.whl → 6.1.3__py3-none-any.whl

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
  """aioamazondevices library."""
2
2
 
3
- __version__ = "6.1.1"
3
+ __version__ = "6.1.3"
4
4
 
5
5
 
6
6
  from .api import AmazonDevice, AmazonEchoApi
aioamazondevices/api.py CHANGED
@@ -20,6 +20,7 @@ from aiohttp import (
20
20
  ClientConnectorError,
21
21
  ClientResponse,
22
22
  ClientSession,
23
+ ContentTypeError,
23
24
  )
24
25
  from bs4 import BeautifulSoup, Tag
25
26
  from langcodes import Language, standardize_tag
@@ -528,15 +529,15 @@ class AmazonEchoApi:
528
529
  }
529
530
 
530
531
  register_url = "https://api.amazon.com/auth/register"
531
- _, resp = await self._session_request(
532
+ _, raw_resp = await self._session_request(
532
533
  method=HTTPMethod.POST,
533
534
  url=register_url,
534
535
  input_data=body,
535
536
  json_data=True,
536
537
  )
537
- resp_json = await resp.json()
538
+ resp_json = await self._response_to_json(raw_resp)
538
539
 
539
- if resp.status != HTTPStatus.OK:
540
+ if raw_resp.status != HTTPStatus.OK:
540
541
  msg = resp_json["response"]["error"]["message"]
541
542
  _LOGGER.error(
542
543
  "Cannot register device for %s: %s",
@@ -544,7 +545,7 @@ class AmazonEchoApi:
544
545
  msg,
545
546
  )
546
547
  raise CannotRegisterDevice(
547
- f"{await self._http_phrase_error(resp.status)}: {msg}"
548
+ f"{await self._http_phrase_error(raw_resp.status)}: {msg}"
548
549
  )
549
550
 
550
551
  success_response = resp_json["response"]["success"]
@@ -599,7 +600,7 @@ class AmazonEchoApi:
599
600
  json_data=True,
600
601
  )
601
602
 
602
- return cast("dict", await raw_resp.json())
603
+ return await self._response_to_json(raw_resp)
603
604
 
604
605
  async def _get_sensors_states(
605
606
  self,
@@ -655,6 +656,19 @@ class AmazonEchoApi:
655
656
 
656
657
  return device_sensors
657
658
 
659
+ async def _response_to_json(self, raw_resp: ClientResponse) -> dict[str, Any]:
660
+ """Convert response to JSON, if possible."""
661
+ try:
662
+ data = await raw_resp.json(loads=orjson.loads)
663
+ if not data:
664
+ _LOGGER.warning("Empty JSON data received")
665
+ data = {}
666
+ return cast("dict[str, Any]", data)
667
+ except ContentTypeError as exc:
668
+ raise ValueError("Response not in JSON format") from exc
669
+ except orjson.JSONDecodeError as exc:
670
+ raise ValueError("Response with corrupted JSON format") from exc
671
+
658
672
  async def login_mode_interactive(self, otp_code: str) -> dict[str, Any]:
659
673
  """Login to Amazon interactively via OTP."""
660
674
  _LOGGER.debug(
@@ -704,7 +718,7 @@ class AmazonEchoApi:
704
718
  _LOGGER.debug(
705
719
  'Cannot find "auth-mfa-otpcode" in html source [%s]', login_url
706
720
  )
707
- raise CannotAuthenticate
721
+ raise CannotAuthenticate("MFA OTP code not found on login page")
708
722
 
709
723
  login_method, login_url = self._get_request_from_soup(login_soup)
710
724
 
@@ -743,6 +757,10 @@ class AmazonEchoApi:
743
757
  obfuscate_email(self._login_email),
744
758
  )
745
759
 
760
+ # Check if session is still authenticated
761
+ if not await self.auth_check_status():
762
+ raise CannotAuthenticate("Session no longer authenticated")
763
+
746
764
  return self._login_stored_data
747
765
 
748
766
  async def _get_alexa_domain(self) -> str:
@@ -752,7 +770,7 @@ class AmazonEchoApi:
752
770
  method=HTTPMethod.GET,
753
771
  url=f"https://alexa.amazon.{self._domain}/api/welcome",
754
772
  )
755
- json_data = await raw_resp.json()
773
+ json_data = await self._response_to_json(raw_resp)
756
774
  return cast(
757
775
  "str", json_data.get("alexaHostName", f"alexa.amazon.{self._domain}")
758
776
  )
@@ -798,8 +816,7 @@ class AmazonEchoApi:
798
816
  url=f"https://alexa.amazon.{self._domain}{URI_DEVICES}",
799
817
  )
800
818
 
801
- response_data = await raw_resp.text()
802
- json_data = {} if len(response_data) == 0 else await raw_resp.json()
819
+ json_data = await self._response_to_json(raw_resp)
803
820
 
804
821
  _LOGGER.debug("JSON devices data: %s", scrub_fields(json_data))
805
822
 
@@ -861,7 +878,7 @@ class AmazonEchoApi:
861
878
  )
862
879
  return False
863
880
 
864
- resp_json = await raw_resp.json()
881
+ resp_json = await self._response_to_json(raw_resp)
865
882
  if not (authentication := resp_json.get("authentication")):
866
883
  _LOGGER.debug('Session not authenticated: reply missing "authentication"')
867
884
  return False
@@ -1106,21 +1123,21 @@ class AmazonEchoApi:
1106
1123
  "domain": f"www.amazon.{self._domain}",
1107
1124
  }
1108
1125
 
1109
- response = await self._session.post(
1126
+ raw_resp = await self._session.post(
1110
1127
  "https://api.amazon.com/auth/token",
1111
1128
  data=data,
1112
1129
  )
1113
1130
  _LOGGER.debug(
1114
1131
  "Refresh data response %s with payload %s",
1115
- response.status,
1132
+ raw_resp.status,
1116
1133
  orjson.dumps(data),
1117
1134
  )
1118
1135
 
1119
- if response.status != HTTPStatus.OK:
1136
+ if raw_resp.status != HTTPStatus.OK:
1120
1137
  _LOGGER.debug("Failed to refresh data")
1121
1138
  return False, {}
1122
1139
 
1123
- json_response = await response.json()
1140
+ json_response = await self._response_to_json(raw_resp)
1124
1141
  _LOGGER.debug("Refresh data json:\n%s ", json_response)
1125
1142
 
1126
1143
  if data_type == REFRESH_ACCESS_TOKEN and (
@@ -1128,7 +1145,7 @@ class AmazonEchoApi:
1128
1145
  ):
1129
1146
  self._login_stored_data[REFRESH_ACCESS_TOKEN] = new_token
1130
1147
  self.expires_in = datetime.now(tz=UTC).timestamp() + int(
1131
- json_response.get("expires_in")
1148
+ json_response.get("expires_in", 0)
1132
1149
  )
1133
1150
  return True, json_response
1134
1151
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: aioamazondevices
3
- Version: 6.1.1
3
+ Version: 6.1.3
4
4
  Summary: Python library to control Amazon devices
5
5
  License: Apache-2.0
6
6
  Author: Simone Chemelli
@@ -1,12 +1,12 @@
1
- aioamazondevices/__init__.py,sha256=MClC2ozQ757Uf3LM3AnbaSMGc47eUbVRdIAQc0fbT8w,276
2
- aioamazondevices/api.py,sha256=oeRI_ZhsEaaSh2iXFbqTgAbTq-VrJ1jW7C11cXpYHss,40721
1
+ aioamazondevices/__init__.py,sha256=xeVWui7vweRIpKp3JwYLPcG-tXnRhz-cFfImDeXVFWU,276
2
+ aioamazondevices/api.py,sha256=C4XD9GvRmwL-sc-dRlaWzarlLzeqq8N4rTymCdyF0-Q,41579
3
3
  aioamazondevices/const.py,sha256=bqJmaStichdm0zB1RQYXa4OPz2gU2JnmUFQHeItlnZE,10808
4
4
  aioamazondevices/exceptions.py,sha256=JDnSFi_7oEhqK31sHXf0S_cyMoMjiRJuLp4ow7mYgLY,643
5
5
  aioamazondevices/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
6
  aioamazondevices/query.py,sha256=AGHHzefzfYzB7RLWPtlFxYc_rpUZdoeApsU2jYz3urQ,2053
7
7
  aioamazondevices/sounds.py,sha256=CXMDk-KoKVFxBdVAw3MeOClqgpzcVDxvQhFOJp7qX-Y,1896
8
8
  aioamazondevices/utils.py,sha256=RzuKRhnq_8ymCoJMoQJ2vBYyuew06RSWpqQWmqdNczE,2019
9
- aioamazondevices-6.1.1.dist-info/LICENSE,sha256=sS48k5sp9bFV-NSHDfAJuTZZ_-AP9ZDqUzQ9sffGlsg,11346
10
- aioamazondevices-6.1.1.dist-info/METADATA,sha256=fWju3izz8YjDYtWqj2CHHTHSC-YjmWWD8DHTIi4wKO8,7623
11
- aioamazondevices-6.1.1.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
12
- aioamazondevices-6.1.1.dist-info/RECORD,,
9
+ aioamazondevices-6.1.3.dist-info/LICENSE,sha256=sS48k5sp9bFV-NSHDfAJuTZZ_-AP9ZDqUzQ9sffGlsg,11346
10
+ aioamazondevices-6.1.3.dist-info/METADATA,sha256=WBhhAbei9OCzT63keD7HIoOVOnmu3Vy2EqitmtTEADQ,7623
11
+ aioamazondevices-6.1.3.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
12
+ aioamazondevices-6.1.3.dist-info/RECORD,,