aioamazondevices 6.4.5__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 +208 -1
- aioamazondevices/const.py +55 -0
- {aioamazondevices-6.4.5.dist-info → aioamazondevices-6.5.0.dist-info}/METADATA +2 -1
- aioamazondevices-6.5.0.dist-info/RECORD +12 -0
- aioamazondevices-6.4.5.dist-info/RECORD +0 -12
- {aioamazondevices-6.4.5.dist-info → aioamazondevices-6.5.0.dist-info}/WHEEL +0 -0
- {aioamazondevices-6.4.5.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(
|
|
@@ -943,8 +1122,13 @@ class AmazonEchoApi:
|
|
|
943
1122
|
await self._get_base_devices()
|
|
944
1123
|
self._last_devices_refresh = datetime.now(UTC)
|
|
945
1124
|
|
|
1125
|
+
# Only refresh endpoint data if we have no endpoints yet
|
|
946
1126
|
delta_endpoints = datetime.now(UTC) - self._last_endpoint_refresh
|
|
947
|
-
|
|
1127
|
+
endpoint_refresh_needed = delta_endpoints >= timedelta(days=1)
|
|
1128
|
+
endpoints_recently_checked = delta_endpoints < timedelta(minutes=30)
|
|
1129
|
+
if (
|
|
1130
|
+
not self._endpoints and not endpoints_recently_checked
|
|
1131
|
+
) or endpoint_refresh_needed:
|
|
948
1132
|
_LOGGER.debug(
|
|
949
1133
|
"Refreshing endpoint data after %s",
|
|
950
1134
|
str(timedelta(minutes=round(delta_endpoints.total_seconds() / 60))),
|
|
@@ -960,6 +1144,7 @@ class AmazonEchoApi:
|
|
|
960
1144
|
async def _get_sensor_data(self) -> None:
|
|
961
1145
|
devices_sensors = await self._get_sensors_states()
|
|
962
1146
|
dnd_sensors = await self._get_dnd_status()
|
|
1147
|
+
notifications = await self._get_notifications()
|
|
963
1148
|
for device in self._final_devices.values():
|
|
964
1149
|
# Update sensors
|
|
965
1150
|
sensors = devices_sensors.get(device.serial_number, {})
|
|
@@ -971,7 +1156,28 @@ class AmazonEchoApi:
|
|
|
971
1156
|
if device_dnd := dnd_sensors.get(device.serial_number):
|
|
972
1157
|
device.sensors["dnd"] = device_dnd
|
|
973
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
|
+
|
|
974
1179
|
async def _set_device_endpoints_data(self) -> None:
|
|
1180
|
+
"""Set device endpoint data."""
|
|
975
1181
|
devices_endpoints = await self._get_devices_endpoint_data()
|
|
976
1182
|
for serial_number in self._final_devices:
|
|
977
1183
|
device_endpoint = devices_endpoints.get(serial_number, {})
|
|
@@ -1033,6 +1239,7 @@ class AmazonEchoApi:
|
|
|
1033
1239
|
entity_id=None,
|
|
1034
1240
|
endpoint_id=None,
|
|
1035
1241
|
sensors={},
|
|
1242
|
+
notifications={},
|
|
1036
1243
|
)
|
|
1037
1244
|
|
|
1038
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=OFf1p25xoL4BCdFQmpphXf541iLmm0Py8LC_rJYPL98,276
|
|
2
|
-
aioamazondevices/api.py,sha256=uTWsZagMQDZ4I-v8lpk9xCTebxUTMDXMU6JE4NANhPc,50367
|
|
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.5.dist-info/METADATA,sha256=k0QHRnM6juLj756-Okw0vq_8FVolrQR7SCF2FF7UdU8,7648
|
|
10
|
-
aioamazondevices-6.4.5.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
|
|
11
|
-
aioamazondevices-6.4.5.dist-info/licenses/LICENSE,sha256=sS48k5sp9bFV-NSHDfAJuTZZ_-AP9ZDqUzQ9sffGlsg,11346
|
|
12
|
-
aioamazondevices-6.4.5.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|