aioamazondevices 6.4.6__py3-none-any.whl → 6.5.0__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.
Potentially problematic release.
This version of aioamazondevices might be problematic. Click here for more details.
- aioamazondevices/__init__.py +1 -1
- aioamazondevices/api.py +201 -0
- aioamazondevices/const.py +55 -0
- {aioamazondevices-6.4.6.dist-info → aioamazondevices-6.5.0.dist-info}/METADATA +2 -1
- aioamazondevices-6.5.0.dist-info/RECORD +12 -0
- aioamazondevices-6.4.6.dist-info/RECORD +0 -12
- {aioamazondevices-6.4.6.dist-info → aioamazondevices-6.5.0.dist-info}/WHEEL +0 -0
- {aioamazondevices-6.4.6.dist-info → aioamazondevices-6.5.0.dist-info}/licenses/LICENSE +0 -0
aioamazondevices/__init__.py
CHANGED
aioamazondevices/api.py
CHANGED
|
@@ -23,6 +23,8 @@ from aiohttp import (
|
|
|
23
23
|
ContentTypeError,
|
|
24
24
|
)
|
|
25
25
|
from bs4 import BeautifulSoup, Tag
|
|
26
|
+
from dateutil.parser import parse
|
|
27
|
+
from dateutil.rrule import rrulestr
|
|
26
28
|
from langcodes import Language, standardize_tag
|
|
27
29
|
from multidict import MultiDictProxy
|
|
28
30
|
from yarl import URL
|
|
@@ -39,6 +41,7 @@ from .const import (
|
|
|
39
41
|
AMAZON_DEVICE_SOFTWARE_VERSION,
|
|
40
42
|
AMAZON_DEVICE_TYPE,
|
|
41
43
|
BIN_EXTENSION,
|
|
44
|
+
COUNTRY_GROUPS,
|
|
42
45
|
CSRF_COOKIE,
|
|
43
46
|
DEFAULT_HEADERS,
|
|
44
47
|
DEFAULT_SITE,
|
|
@@ -48,6 +51,11 @@ from .const import (
|
|
|
48
51
|
HTTP_ERROR_199,
|
|
49
52
|
HTTP_ERROR_299,
|
|
50
53
|
JSON_EXTENSION,
|
|
54
|
+
NOTIFICATION_ALARM,
|
|
55
|
+
NOTIFICATION_MUSIC_ALARM,
|
|
56
|
+
NOTIFICATION_REMINDER,
|
|
57
|
+
NOTIFICATION_TIMER,
|
|
58
|
+
RECURRING_PATTERNS,
|
|
51
59
|
REFRESH_ACCESS_TOKEN,
|
|
52
60
|
REFRESH_AUTH_COOKIES,
|
|
53
61
|
REQUEST_AGENT,
|
|
@@ -56,7 +64,9 @@ from .const import (
|
|
|
56
64
|
URI_DEVICES,
|
|
57
65
|
URI_DND,
|
|
58
66
|
URI_NEXUS_GRAPHQL,
|
|
67
|
+
URI_NOTIFICATIONS,
|
|
59
68
|
URI_SIGNIN,
|
|
69
|
+
WEEKEND_EXCEPTIONS,
|
|
60
70
|
)
|
|
61
71
|
from .exceptions import (
|
|
62
72
|
CannotAuthenticate,
|
|
@@ -81,6 +91,16 @@ class AmazonDeviceSensor:
|
|
|
81
91
|
scale: str | None
|
|
82
92
|
|
|
83
93
|
|
|
94
|
+
@dataclass
|
|
95
|
+
class AmazonSchedule:
|
|
96
|
+
"""Amazon schedule class."""
|
|
97
|
+
|
|
98
|
+
type: str # alarm, reminder, timer
|
|
99
|
+
status: str
|
|
100
|
+
label: str
|
|
101
|
+
next_occurrence: datetime | None
|
|
102
|
+
|
|
103
|
+
|
|
84
104
|
@dataclass
|
|
85
105
|
class AmazonDevice:
|
|
86
106
|
"""Amazon device class."""
|
|
@@ -98,6 +118,7 @@ class AmazonDevice:
|
|
|
98
118
|
entity_id: str | None
|
|
99
119
|
endpoint_id: str | None
|
|
100
120
|
sensors: dict[str, AmazonDeviceSensor]
|
|
121
|
+
notifications: dict[str, AmazonSchedule]
|
|
101
122
|
|
|
102
123
|
|
|
103
124
|
class AmazonSequenceType(StrEnum):
|
|
@@ -173,6 +194,7 @@ class AmazonEchoApi:
|
|
|
173
194
|
lang_object = Language.make(territory=country_code.upper())
|
|
174
195
|
lang_maximized = lang_object.maximize()
|
|
175
196
|
|
|
197
|
+
self._country_code: str = country_code
|
|
176
198
|
self._domain: str = domain
|
|
177
199
|
language = f"{lang_maximized.language}-{lang_maximized.territory}"
|
|
178
200
|
self._language = standardize_tag(language)
|
|
@@ -766,6 +788,163 @@ class AmazonEchoApi:
|
|
|
766
788
|
except orjson.JSONDecodeError as exc:
|
|
767
789
|
raise ValueError("Response with corrupted JSON format") from exc
|
|
768
790
|
|
|
791
|
+
async def _get_notifications(self) -> dict[str, dict[str, AmazonSchedule]]:
|
|
792
|
+
final_notifications: dict[str, dict[str, AmazonSchedule]] = {}
|
|
793
|
+
|
|
794
|
+
_, raw_resp = await self._session_request(
|
|
795
|
+
HTTPMethod.GET,
|
|
796
|
+
url=f"https://alexa.amazon.{self._domain}{URI_NOTIFICATIONS}",
|
|
797
|
+
)
|
|
798
|
+
notifications = await self._response_to_json(raw_resp)
|
|
799
|
+
for schedule in notifications["notifications"]:
|
|
800
|
+
schedule_type: str = schedule["type"]
|
|
801
|
+
schedule_device_serial = schedule["deviceSerialNumber"]
|
|
802
|
+
if schedule_type == NOTIFICATION_MUSIC_ALARM:
|
|
803
|
+
# Structure is the same as standard Alarm
|
|
804
|
+
schedule_type = NOTIFICATION_ALARM
|
|
805
|
+
schedule["type"] = NOTIFICATION_ALARM
|
|
806
|
+
label_desc = schedule_type.lower() + "Label"
|
|
807
|
+
if (schedule_status := schedule["status"]) == "ON" and (
|
|
808
|
+
next_occurrence := await self._parse_next_occurence(schedule)
|
|
809
|
+
):
|
|
810
|
+
schedule_notification_list = final_notifications.get(
|
|
811
|
+
schedule_device_serial, {}
|
|
812
|
+
)
|
|
813
|
+
schedule_notification_by_type = schedule_notification_list.get(
|
|
814
|
+
schedule_type
|
|
815
|
+
)
|
|
816
|
+
# Replace if no existing notification
|
|
817
|
+
# or if existing.next_occurrence is None
|
|
818
|
+
# or if new next_occurrence is earlier
|
|
819
|
+
if (
|
|
820
|
+
not schedule_notification_by_type
|
|
821
|
+
or schedule_notification_by_type.next_occurrence is None
|
|
822
|
+
or next_occurrence < schedule_notification_by_type.next_occurrence
|
|
823
|
+
):
|
|
824
|
+
final_notifications.update(
|
|
825
|
+
{
|
|
826
|
+
schedule_device_serial: {
|
|
827
|
+
**schedule_notification_list
|
|
828
|
+
| {
|
|
829
|
+
schedule_type: AmazonSchedule(
|
|
830
|
+
type=schedule_type,
|
|
831
|
+
status=schedule_status,
|
|
832
|
+
label=schedule[label_desc],
|
|
833
|
+
next_occurrence=next_occurrence,
|
|
834
|
+
),
|
|
835
|
+
}
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
)
|
|
839
|
+
|
|
840
|
+
return final_notifications
|
|
841
|
+
|
|
842
|
+
async def _parse_next_occurence(
|
|
843
|
+
self,
|
|
844
|
+
schedule: dict[str, Any],
|
|
845
|
+
) -> datetime | None:
|
|
846
|
+
"""Parse RFC5545 rule set for next iteration."""
|
|
847
|
+
# Local timezone
|
|
848
|
+
tzinfo = datetime.now().astimezone().tzinfo
|
|
849
|
+
# Current time
|
|
850
|
+
actual_time = datetime.now(tz=tzinfo)
|
|
851
|
+
# Reference start date
|
|
852
|
+
today_midnight = actual_time.replace(hour=0, minute=0, second=0, microsecond=0)
|
|
853
|
+
# Reference time (1 minute ago to avoid edge cases)
|
|
854
|
+
now_reference = actual_time - timedelta(minutes=1)
|
|
855
|
+
|
|
856
|
+
# Schedule data
|
|
857
|
+
original_date = schedule.get("originalDate")
|
|
858
|
+
original_time = schedule.get("originalTime")
|
|
859
|
+
|
|
860
|
+
recurring_rules: list[str] = []
|
|
861
|
+
if schedule.get("rRuleData"):
|
|
862
|
+
recurring_rules = schedule["rRuleData"]["recurrenceRules"]
|
|
863
|
+
if schedule.get("recurringPattern"):
|
|
864
|
+
recurring_rules.append(schedule["recurringPattern"])
|
|
865
|
+
|
|
866
|
+
# Recurring events
|
|
867
|
+
if recurring_rules:
|
|
868
|
+
next_candidates: list[datetime] = []
|
|
869
|
+
for recurring_rule in recurring_rules:
|
|
870
|
+
# Already in RFC5545 format
|
|
871
|
+
if "FREQ=" in recurring_rule:
|
|
872
|
+
rule = await self._add_hours_minutes(recurring_rule, original_time)
|
|
873
|
+
|
|
874
|
+
# Add date to candidates list
|
|
875
|
+
next_candidates.append(
|
|
876
|
+
rrulestr(rule, dtstart=today_midnight).after(
|
|
877
|
+
now_reference, True
|
|
878
|
+
),
|
|
879
|
+
)
|
|
880
|
+
continue
|
|
881
|
+
|
|
882
|
+
if recurring_rule not in RECURRING_PATTERNS:
|
|
883
|
+
_LOGGER.warning("Unknown recurring rule: %s", recurring_rule)
|
|
884
|
+
return None
|
|
885
|
+
|
|
886
|
+
# Adjust recurring rules for country specific weekend exceptions
|
|
887
|
+
recurring_pattern = RECURRING_PATTERNS.copy()
|
|
888
|
+
for group, countries in COUNTRY_GROUPS.items():
|
|
889
|
+
if self._country_code in countries:
|
|
890
|
+
recurring_pattern |= WEEKEND_EXCEPTIONS[group]
|
|
891
|
+
break
|
|
892
|
+
|
|
893
|
+
rule = await self._add_hours_minutes(
|
|
894
|
+
recurring_pattern[recurring_rule], original_time
|
|
895
|
+
)
|
|
896
|
+
|
|
897
|
+
# Add date to candidates list
|
|
898
|
+
next_candidates.append(
|
|
899
|
+
rrulestr(rule, dtstart=today_midnight).after(now_reference, True),
|
|
900
|
+
)
|
|
901
|
+
|
|
902
|
+
return min(next_candidates) if next_candidates else None
|
|
903
|
+
|
|
904
|
+
# Single events
|
|
905
|
+
if schedule["type"] == NOTIFICATION_ALARM:
|
|
906
|
+
timestamp = parse(f"{original_date} {original_time}").replace(tzinfo=tzinfo)
|
|
907
|
+
|
|
908
|
+
elif schedule["type"] == NOTIFICATION_TIMER:
|
|
909
|
+
# API returns triggerTime in milliseconds since epoch
|
|
910
|
+
timestamp = datetime.fromtimestamp(
|
|
911
|
+
schedule["triggerTime"] / 1000, tz=tzinfo
|
|
912
|
+
)
|
|
913
|
+
|
|
914
|
+
elif schedule["type"] == NOTIFICATION_REMINDER:
|
|
915
|
+
# API returns alarmTime in milliseconds since epoch
|
|
916
|
+
timestamp = datetime.fromtimestamp(schedule["alarmTime"] / 1000, tz=tzinfo)
|
|
917
|
+
|
|
918
|
+
else:
|
|
919
|
+
_LOGGER.warning(("Unknown schedule type: %s"), schedule["type"])
|
|
920
|
+
return None
|
|
921
|
+
|
|
922
|
+
if timestamp > now_reference:
|
|
923
|
+
return timestamp
|
|
924
|
+
|
|
925
|
+
return None
|
|
926
|
+
|
|
927
|
+
async def _add_hours_minutes(
|
|
928
|
+
self,
|
|
929
|
+
recurring_rule: str,
|
|
930
|
+
original_time: str | None,
|
|
931
|
+
) -> str:
|
|
932
|
+
"""Add hours and minutes to a RFC5545 string."""
|
|
933
|
+
rule = recurring_rule.removesuffix(";")
|
|
934
|
+
|
|
935
|
+
if not original_time:
|
|
936
|
+
return rule
|
|
937
|
+
|
|
938
|
+
# Add missing BYHOUR, BYMINUTE if needed (Alarms only)
|
|
939
|
+
if "BYHOUR=" not in recurring_rule:
|
|
940
|
+
hour = int(original_time.split(":")[0])
|
|
941
|
+
rule += f";BYHOUR={hour}"
|
|
942
|
+
if "BYMINUTE=" not in recurring_rule:
|
|
943
|
+
minute = int(original_time.split(":")[1])
|
|
944
|
+
rule += f";BYMINUTE={minute}"
|
|
945
|
+
|
|
946
|
+
return rule
|
|
947
|
+
|
|
769
948
|
async def login_mode_interactive(self, otp_code: str) -> dict[str, Any]:
|
|
770
949
|
"""Login to Amazon interactively via OTP."""
|
|
771
950
|
_LOGGER.debug(
|
|
@@ -965,6 +1144,7 @@ class AmazonEchoApi:
|
|
|
965
1144
|
async def _get_sensor_data(self) -> None:
|
|
966
1145
|
devices_sensors = await self._get_sensors_states()
|
|
967
1146
|
dnd_sensors = await self._get_dnd_status()
|
|
1147
|
+
notifications = await self._get_notifications()
|
|
968
1148
|
for device in self._final_devices.values():
|
|
969
1149
|
# Update sensors
|
|
970
1150
|
sensors = devices_sensors.get(device.serial_number, {})
|
|
@@ -976,6 +1156,26 @@ class AmazonEchoApi:
|
|
|
976
1156
|
if device_dnd := dnd_sensors.get(device.serial_number):
|
|
977
1157
|
device.sensors["dnd"] = device_dnd
|
|
978
1158
|
|
|
1159
|
+
# Update notifications
|
|
1160
|
+
device_notifications = notifications.get(device.serial_number, {})
|
|
1161
|
+
|
|
1162
|
+
# Add only supported notification types
|
|
1163
|
+
for capability, notification_type in [
|
|
1164
|
+
("REMINDERS", NOTIFICATION_REMINDER),
|
|
1165
|
+
("TIMERS_AND_ALARMS", NOTIFICATION_ALARM),
|
|
1166
|
+
("TIMERS_AND_ALARMS", NOTIFICATION_TIMER),
|
|
1167
|
+
]:
|
|
1168
|
+
if (
|
|
1169
|
+
capability in device.capabilities
|
|
1170
|
+
and notification_type in device_notifications
|
|
1171
|
+
and (
|
|
1172
|
+
notification_object := device_notifications.get(
|
|
1173
|
+
notification_type
|
|
1174
|
+
)
|
|
1175
|
+
)
|
|
1176
|
+
):
|
|
1177
|
+
device.notifications[notification_type] = notification_object
|
|
1178
|
+
|
|
979
1179
|
async def _set_device_endpoints_data(self) -> None:
|
|
980
1180
|
"""Set device endpoint data."""
|
|
981
1181
|
devices_endpoints = await self._get_devices_endpoint_data()
|
|
@@ -1039,6 +1239,7 @@ class AmazonEchoApi:
|
|
|
1039
1239
|
entity_id=None,
|
|
1040
1240
|
endpoint_id=None,
|
|
1041
1241
|
sensors={},
|
|
1242
|
+
notifications={},
|
|
1042
1243
|
)
|
|
1043
1244
|
|
|
1044
1245
|
self._list_for_clusters.update(
|
aioamazondevices/const.py
CHANGED
|
@@ -54,6 +54,7 @@ REFRESH_AUTH_COOKIES = "auth_cookies"
|
|
|
54
54
|
|
|
55
55
|
URI_DEVICES = "/api/devices-v2/device"
|
|
56
56
|
URI_DND = "/api/dnd/device-status-list"
|
|
57
|
+
URI_NOTIFICATIONS = "/api/notifications"
|
|
57
58
|
URI_SIGNIN = "/ap/signin"
|
|
58
59
|
URI_NEXUS_GRAPHQL = "/nexus/v1/graphql"
|
|
59
60
|
|
|
@@ -477,3 +478,57 @@ DEVICE_TYPE_TO_MODEL: dict[str, dict[str, str | None]] = {
|
|
|
477
478
|
"hw_version": "Gen2",
|
|
478
479
|
},
|
|
479
480
|
}
|
|
481
|
+
|
|
482
|
+
RECURRING_PATTERNS: dict[str, str] = {
|
|
483
|
+
"XXXX-WD": "FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR",
|
|
484
|
+
"XXXX-WE": "FREQ=WEEKLY;BYDAY=SA,SU",
|
|
485
|
+
"XXXX-WXX-1": "FREQ=WEEKLY;BYDAY=MO",
|
|
486
|
+
"XXXX-WXX-2": "FREQ=WEEKLY;BYDAY=TU",
|
|
487
|
+
"XXXX-WXX-3": "FREQ=WEEKLY;BYDAY=WE",
|
|
488
|
+
"XXXX-WXX-4": "FREQ=WEEKLY;BYDAY=TH",
|
|
489
|
+
"XXXX-WXX-5": "FREQ=WEEKLY;BYDAY=FR",
|
|
490
|
+
"XXXX-WXX-6": "FREQ=WEEKLY;BYDAY=SA",
|
|
491
|
+
"XXXX-WXX-7": "FREQ=WEEKLY;BYDAY=SU",
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
WEEKEND_EXCEPTIONS = {
|
|
495
|
+
"TH-FR": {
|
|
496
|
+
"XXXX-WD": "FREQ=WEEKLY;BYDAY=MO,TU,WE,SA,SU",
|
|
497
|
+
"XXXX-WE": "FREQ=WEEKLY;BYDAY=TH,FR",
|
|
498
|
+
},
|
|
499
|
+
"FR-SA": {
|
|
500
|
+
"XXXX-WD": "FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,SU",
|
|
501
|
+
"XXXX-WE": "FREQ=WEEKLY;BYDAY=FR,SA",
|
|
502
|
+
},
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
# Countries grouped by their weekend type
|
|
506
|
+
COUNTRY_GROUPS = {
|
|
507
|
+
"TH-FR": ["IR"],
|
|
508
|
+
"FR-SA": [
|
|
509
|
+
"AF",
|
|
510
|
+
"BD",
|
|
511
|
+
"BH",
|
|
512
|
+
"DZ",
|
|
513
|
+
"EG",
|
|
514
|
+
"IL",
|
|
515
|
+
"IQ",
|
|
516
|
+
"JO",
|
|
517
|
+
"KW",
|
|
518
|
+
"LY",
|
|
519
|
+
"MV",
|
|
520
|
+
"MY",
|
|
521
|
+
"OM",
|
|
522
|
+
"PS",
|
|
523
|
+
"QA",
|
|
524
|
+
"SA",
|
|
525
|
+
"SD",
|
|
526
|
+
"SY",
|
|
527
|
+
"YE",
|
|
528
|
+
],
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
NOTIFICATION_ALARM = "Alarm"
|
|
532
|
+
NOTIFICATION_MUSIC_ALARM = "MusicAlarm"
|
|
533
|
+
NOTIFICATION_REMINDER = "Reminder"
|
|
534
|
+
NOTIFICATION_TIMER = "Timer"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: aioamazondevices
|
|
3
|
-
Version: 6.
|
|
3
|
+
Version: 6.5.0
|
|
4
4
|
Summary: Python library to control Amazon devices
|
|
5
5
|
License-Expression: Apache-2.0
|
|
6
6
|
License-File: LICENSE
|
|
@@ -17,6 +17,7 @@ Requires-Dist: beautifulsoup4
|
|
|
17
17
|
Requires-Dist: colorlog
|
|
18
18
|
Requires-Dist: langcodes
|
|
19
19
|
Requires-Dist: orjson (>=3.10,<4)
|
|
20
|
+
Requires-Dist: python-dateutil
|
|
20
21
|
Project-URL: Bug Tracker, https://github.com/chemelli74/aioamazondevices/issues
|
|
21
22
|
Project-URL: Changelog, https://github.com/chemelli74/aioamazondevices/blob/main/CHANGELOG.md
|
|
22
23
|
Project-URL: Homepage, https://github.com/chemelli74/aioamazondevices
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
aioamazondevices/__init__.py,sha256=T63aexWxTzW2X40gC-0WS_XqR-gWU7pV8ggK1C-xOPM,276
|
|
2
|
+
aioamazondevices/api.py,sha256=5RY7f5mGCpIg3QUxD2ZhjhZ2UwR1IRuuT170aEp1X6U,58561
|
|
3
|
+
aioamazondevices/const.py,sha256=DLjCgIEVBBezEAqlKHNA2KN9JjR-oxr3UCKG1WXdJqQ,13515
|
|
4
|
+
aioamazondevices/exceptions.py,sha256=gRYrxNAJnrV6uRuMx5e76VMvtNKyceXd09q84pDBBrI,638
|
|
5
|
+
aioamazondevices/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
6
|
+
aioamazondevices/query.py,sha256=SKn-fXFUnXnCvmKd6IvAGdkFL7sBzhYBEAZ0aZ2ez9E,1800
|
|
7
|
+
aioamazondevices/sounds.py,sha256=CXMDk-KoKVFxBdVAw3MeOClqgpzcVDxvQhFOJp7qX-Y,1896
|
|
8
|
+
aioamazondevices/utils.py,sha256=RzuKRhnq_8ymCoJMoQJ2vBYyuew06RSWpqQWmqdNczE,2019
|
|
9
|
+
aioamazondevices-6.5.0.dist-info/METADATA,sha256=ehwDX3IxhNr57zmjOw4i4EiBP01bBblB64kfZG2iBwk,7679
|
|
10
|
+
aioamazondevices-6.5.0.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
|
|
11
|
+
aioamazondevices-6.5.0.dist-info/licenses/LICENSE,sha256=sS48k5sp9bFV-NSHDfAJuTZZ_-AP9ZDqUzQ9sffGlsg,11346
|
|
12
|
+
aioamazondevices-6.5.0.dist-info/RECORD,,
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
aioamazondevices/__init__.py,sha256=G3JnYhlhatrCtpn_93BQbFjsfMMhklpDM4ACRD_F0Jw,276
|
|
2
|
-
aioamazondevices/api.py,sha256=VaOGSfUmpy8hRF7vISGoalZbyn2RqRpelDN9LepkPbw,50685
|
|
3
|
-
aioamazondevices/const.py,sha256=BZTyUku94uQa50R1ZeXo1h585xgUNT_Pb7KAifjawWc,12266
|
|
4
|
-
aioamazondevices/exceptions.py,sha256=gRYrxNAJnrV6uRuMx5e76VMvtNKyceXd09q84pDBBrI,638
|
|
5
|
-
aioamazondevices/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
6
|
-
aioamazondevices/query.py,sha256=SKn-fXFUnXnCvmKd6IvAGdkFL7sBzhYBEAZ0aZ2ez9E,1800
|
|
7
|
-
aioamazondevices/sounds.py,sha256=CXMDk-KoKVFxBdVAw3MeOClqgpzcVDxvQhFOJp7qX-Y,1896
|
|
8
|
-
aioamazondevices/utils.py,sha256=RzuKRhnq_8ymCoJMoQJ2vBYyuew06RSWpqQWmqdNczE,2019
|
|
9
|
-
aioamazondevices-6.4.6.dist-info/METADATA,sha256=e7_GTeYgN9fJp_P4o2Spft3iE2oY78DDaQtpQlakT4c,7648
|
|
10
|
-
aioamazondevices-6.4.6.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
|
|
11
|
-
aioamazondevices-6.4.6.dist-info/licenses/LICENSE,sha256=sS48k5sp9bFV-NSHDfAJuTZZ_-AP9ZDqUzQ9sffGlsg,11346
|
|
12
|
-
aioamazondevices-6.4.6.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|