MouseTools 3.0.0.dev1__py3-none-any.whl → 3.0.0.dev2__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.
- {MouseTools-3.0.0.dev1.dist-info → MouseTools-3.0.0.dev2.dist-info}/METADATA +41 -3
- MouseTools-3.0.0.dev2.dist-info/RECORD +32 -0
- {MouseTools-3.0.0.dev1.dist-info → MouseTools-3.0.0.dev2.dist-info}/WHEEL +1 -1
- mousetools/__init__.py +1 -7
- mousetools/auth.py +13 -3
- mousetools/entities/__init__.py +34 -6
- mousetools/entities/attraction.py +8 -4
- mousetools/entities/base.py +235 -129
- mousetools/entities/character.py +12 -0
- mousetools/entities/destination.py +12 -4
- mousetools/entities/dining_event.py +8 -11
- mousetools/entities/dinner_show.py +12 -0
- mousetools/entities/entertainment.py +8 -4
- mousetools/entities/entertainment_venue.py +8 -4
- mousetools/entities/event.py +8 -4
- mousetools/entities/guest_services.py +12 -0
- mousetools/entities/land.py +12 -0
- mousetools/entities/menu.py +12 -0
- mousetools/entities/merchandise_facility.py +8 -4
- mousetools/entities/park.py +39 -5
- mousetools/entities/point_of_interest.py +12 -0
- mousetools/entities/resort.py +8 -4
- mousetools/entities/resort_area.py +12 -0
- mousetools/entities/restaurant.py +8 -4
- mousetools/exceptions.py +3 -3
- mousetools/ids.py +42 -36
- mousetools/mixins/disney.py +37 -46
- mousetools/mixins/themeparksapi.py +20 -14
- mousetools/urls.py +2 -3
- MouseTools-3.0.0.dev1.dist-info/RECORD +0 -25
- {MouseTools-3.0.0.dev1.dist-info → MouseTools-3.0.0.dev2.dist-info}/LICENSE +0 -0
- {MouseTools-3.0.0.dev1.dist-info → MouseTools-3.0.0.dev2.dist-info}/top_level.txt +0 -0
mousetools/entities/base.py
CHANGED
|
@@ -1,22 +1,30 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
import typing
|
|
3
|
-
from datetime import datetime
|
|
3
|
+
from datetime import datetime, time
|
|
4
4
|
from zoneinfo import ZoneInfo
|
|
5
|
+
|
|
6
|
+
from mousetools.exceptions import AncestorDestinationMissingError
|
|
7
|
+
from mousetools.ids import DestinationIds, FacilityServiceEntityTypes
|
|
5
8
|
from mousetools.mixins.disney import DisneyAPIMixin
|
|
6
9
|
from mousetools.mixins.themeparksapi import ThemeParkAPIMixin
|
|
7
|
-
from mousetools.
|
|
8
|
-
from mousetools.urls import ENTITY_DETAILS_SIMPLE_BASE_URL
|
|
9
|
-
from mousetools.exceptions import AncestorDestinationMissing
|
|
10
|
-
|
|
10
|
+
from mousetools.urls import WDPRO_FACILITY_SERVICE_BASE_URL
|
|
11
11
|
|
|
12
12
|
logger = logging.getLogger(__name__)
|
|
13
13
|
|
|
14
14
|
|
|
15
|
-
class
|
|
16
|
-
def __init__(
|
|
17
|
-
self
|
|
15
|
+
class EntityBase(DisneyAPIMixin, ThemeParkAPIMixin):
|
|
16
|
+
def __init__(
|
|
17
|
+
self,
|
|
18
|
+
entity_id: str,
|
|
19
|
+
facility_service_entity_type: typing.Union[str, FacilityServiceEntityTypes],
|
|
20
|
+
):
|
|
21
|
+
self.entity_id: str = entity_id
|
|
18
22
|
self.disney_data: typing.Optional[dict] = None
|
|
19
23
|
|
|
24
|
+
if isinstance(facility_service_entity_type, FacilityServiceEntityTypes):
|
|
25
|
+
facility_service_entity_type = facility_service_entity_type.value
|
|
26
|
+
self.__facility_service_url = f"{WDPRO_FACILITY_SERVICE_BASE_URL}/{facility_service_entity_type}/{self.entity_id}"
|
|
27
|
+
|
|
20
28
|
@property
|
|
21
29
|
def name(self) -> typing.Optional[str]:
|
|
22
30
|
"""
|
|
@@ -27,11 +35,11 @@ class Entity(DisneyAPIMixin, ThemeParkAPIMixin):
|
|
|
27
35
|
"""
|
|
28
36
|
|
|
29
37
|
if self.disney_data is None:
|
|
30
|
-
self.disney_data = self.get_disney_data()
|
|
38
|
+
self.disney_data = self.get_disney_data(self.__facility_service_url)
|
|
31
39
|
try:
|
|
32
40
|
return self.disney_data["name"]
|
|
33
41
|
except KeyError:
|
|
34
|
-
logger.debug("No name found for %s", self.
|
|
42
|
+
logger.debug("No name found for %s", self.entity_id)
|
|
35
43
|
return None
|
|
36
44
|
|
|
37
45
|
@property
|
|
@@ -44,27 +52,27 @@ class Entity(DisneyAPIMixin, ThemeParkAPIMixin):
|
|
|
44
52
|
"""
|
|
45
53
|
|
|
46
54
|
if self.disney_data is None:
|
|
47
|
-
self.disney_data = self.get_disney_data()
|
|
55
|
+
self.disney_data = self.get_disney_data(self.__facility_service_url)
|
|
48
56
|
try:
|
|
49
|
-
return self.disney_data["
|
|
57
|
+
return self.disney_data["type"]
|
|
50
58
|
except KeyError:
|
|
51
|
-
logger.debug("No entity type found for %s", self.
|
|
59
|
+
logger.debug("No entity type found for %s", self.entity_id)
|
|
52
60
|
return None
|
|
53
61
|
|
|
54
62
|
@property
|
|
55
|
-
def
|
|
63
|
+
def sub_type(self) -> typing.Optional[str]:
|
|
56
64
|
"""
|
|
57
|
-
The
|
|
65
|
+
The sub type of entity.
|
|
58
66
|
|
|
59
67
|
Returns:
|
|
60
|
-
(typing.Optional[str]): The
|
|
68
|
+
(typing.Optional[str]): The sub type of entity, or None if it was not found.
|
|
61
69
|
"""
|
|
62
70
|
if self.disney_data is None:
|
|
63
|
-
self.disney_data = self.get_disney_data()
|
|
71
|
+
self.disney_data = self.get_disney_data(self.__facility_service_url)
|
|
64
72
|
try:
|
|
65
|
-
return self.disney_data["
|
|
73
|
+
return self.disney_data["subType"]
|
|
66
74
|
except KeyError:
|
|
67
|
-
logger.debug("No
|
|
75
|
+
logger.debug("No sub type found for %s", self.entity_id)
|
|
68
76
|
return None
|
|
69
77
|
|
|
70
78
|
@property
|
|
@@ -76,14 +84,12 @@ class Entity(DisneyAPIMixin, ThemeParkAPIMixin):
|
|
|
76
84
|
(typing.Optional[str]): The url friendly id of the entity, or None if not found.
|
|
77
85
|
"""
|
|
78
86
|
if self.disney_data is None:
|
|
79
|
-
self.disney_data = self.get_disney_data()
|
|
87
|
+
self.disney_data = self.get_disney_data(self.__facility_service_url)
|
|
80
88
|
try:
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
id = id.replace("-wdw", "").replace("-dlr", "")
|
|
84
|
-
return id
|
|
89
|
+
_id = self.disney_data["urlFriendlyId"]
|
|
90
|
+
return _id
|
|
85
91
|
except KeyError:
|
|
86
|
-
logger.debug("No url friendly id found for %s", self.
|
|
92
|
+
logger.debug("No url friendly id found for %s", self.entity_id)
|
|
87
93
|
return None
|
|
88
94
|
|
|
89
95
|
@property
|
|
@@ -95,146 +101,193 @@ class Entity(DisneyAPIMixin, ThemeParkAPIMixin):
|
|
|
95
101
|
(typing.Optional[dict[str, float]]): A dict with "lat" and "lng" keys containing the coordinates of this entity as floats, or None if no coordinates are found
|
|
96
102
|
"""
|
|
97
103
|
if self.disney_data is None:
|
|
98
|
-
self.disney_data = self.get_disney_data()
|
|
104
|
+
self.disney_data = self.get_disney_data(self.__facility_service_url)
|
|
99
105
|
try:
|
|
100
106
|
return {
|
|
101
|
-
"lat": float(
|
|
102
|
-
|
|
107
|
+
"lat": float(
|
|
108
|
+
self.disney_data["coordinates"]["Guest Entrance"]["gps"][
|
|
109
|
+
"lattitude"
|
|
110
|
+
]
|
|
111
|
+
),
|
|
112
|
+
"lng": float(
|
|
113
|
+
self.disney_data["coordinates"]["Guest entrance"]["gps"][
|
|
114
|
+
"longitude"
|
|
115
|
+
]
|
|
116
|
+
),
|
|
103
117
|
}
|
|
104
118
|
except KeyError:
|
|
105
|
-
logger.debug("No coordinates found for %s", self.
|
|
119
|
+
logger.debug("No coordinates found for %s", self.entity_id)
|
|
106
120
|
return None
|
|
107
121
|
|
|
108
122
|
@property
|
|
109
|
-
def ancestor_destination_id(self) -> typing.Optional[str]:
|
|
123
|
+
def ancestor_destination_id(self) -> typing.Optional[str]: # type: ignore
|
|
110
124
|
"""
|
|
111
125
|
The id of the ancestor destination of this entity.
|
|
112
126
|
|
|
113
127
|
Returns:
|
|
114
128
|
(typing.Optional[str]): The id of the ancestor destination of this entity, or None if it was not found.
|
|
115
129
|
"""
|
|
116
|
-
|
|
130
|
+
# TODO check other ancestors to guess dest if not found
|
|
117
131
|
if self.disney_data is None:
|
|
118
|
-
self.disney_data = self.get_disney_data()
|
|
132
|
+
self.disney_data = self.get_disney_data(self.__facility_service_url)
|
|
119
133
|
try:
|
|
120
|
-
return
|
|
134
|
+
return (
|
|
135
|
+
self.disney_data["links"]["ancestorDestination"]["href"]
|
|
136
|
+
.split("?")[0]
|
|
137
|
+
.split("/")[-1]
|
|
138
|
+
)
|
|
121
139
|
except KeyError:
|
|
122
|
-
|
|
123
|
-
|
|
140
|
+
try:
|
|
141
|
+
return (
|
|
142
|
+
self.disney_data["ancestorDestination"]["id"]
|
|
143
|
+
.split("?")[0]
|
|
144
|
+
.split("/")[-1]
|
|
145
|
+
)
|
|
146
|
+
except KeyError:
|
|
147
|
+
logger.debug("No ancestor destination id found for %s", self.entity_id)
|
|
148
|
+
return None
|
|
124
149
|
|
|
125
|
-
@
|
|
126
|
-
def
|
|
150
|
+
@property
|
|
151
|
+
def ancestor_theme_park_id(self):
|
|
127
152
|
"""
|
|
128
|
-
|
|
153
|
+
The id of the theme park of this entity.
|
|
129
154
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
Args:
|
|
133
|
-
value (typing.Optional[str]): Str to set ancestor_destination_id to
|
|
155
|
+
Returns:
|
|
156
|
+
(typing.Optional[str]): Theme park id, or None if no such id is found.
|
|
134
157
|
"""
|
|
135
|
-
self.
|
|
158
|
+
if self.disney_data is None:
|
|
159
|
+
self.disney_data = self.get_disney_data(self.__facility_service_url)
|
|
160
|
+
try:
|
|
161
|
+
return (
|
|
162
|
+
self.disney_data["links"]["ancestorThemePark"]["href"]
|
|
163
|
+
.split("?")[0]
|
|
164
|
+
.split("/")[-1]
|
|
165
|
+
)
|
|
166
|
+
except KeyError:
|
|
167
|
+
logger.debug("No ancestor theme park id found for %s", self.entity_id)
|
|
168
|
+
return None
|
|
136
169
|
|
|
137
170
|
@property
|
|
138
|
-
def
|
|
171
|
+
def ancestor_water_park_id(self) -> typing.Optional[str]:
|
|
139
172
|
"""
|
|
140
|
-
The
|
|
173
|
+
The if of the water park of this entity.
|
|
141
174
|
|
|
142
175
|
Returns:
|
|
143
|
-
(typing.Optional[
|
|
176
|
+
(typing.Optional[str]): Water park id, or None if no such id is found.
|
|
144
177
|
"""
|
|
145
178
|
if self.disney_data is None:
|
|
146
|
-
self.disney_data = self.get_disney_data()
|
|
179
|
+
self.disney_data = self.get_disney_data(self.__facility_service_url)
|
|
147
180
|
try:
|
|
148
|
-
return
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
181
|
+
return (
|
|
182
|
+
self.disney_data["links"]["ancestorWaterPark"]["href"]
|
|
183
|
+
.split("?")[0]
|
|
184
|
+
.split("/")[-1]
|
|
185
|
+
)
|
|
153
186
|
except KeyError:
|
|
154
|
-
logger.debug("No ancestor park
|
|
187
|
+
logger.debug("No ancestor water park id found for %s", self.entity_id)
|
|
155
188
|
return None
|
|
156
189
|
|
|
157
190
|
@property
|
|
158
|
-
def
|
|
191
|
+
def ancestor_resort_id(self) -> typing.Optional[str]:
|
|
159
192
|
"""
|
|
160
|
-
The
|
|
193
|
+
The id of the resort of the entity.
|
|
161
194
|
|
|
162
195
|
Returns:
|
|
163
|
-
(typing.Optional[
|
|
196
|
+
(typing.Optional[str): Resort id, or None if no such id is found.
|
|
164
197
|
"""
|
|
165
198
|
|
|
166
199
|
if self.disney_data is None:
|
|
167
|
-
self.disney_data = self.get_disney_data()
|
|
200
|
+
self.disney_data = self.get_disney_data(self.__facility_service_url)
|
|
168
201
|
try:
|
|
169
|
-
return
|
|
202
|
+
return (
|
|
203
|
+
self.disney_data["links"]["ancestorResort"]["href"]
|
|
204
|
+
.split("?")[0]
|
|
205
|
+
.split("/")[-1]
|
|
206
|
+
)
|
|
170
207
|
except KeyError:
|
|
171
|
-
logger.debug("No ancestor resort ids found for %s", self.
|
|
208
|
+
logger.debug("No ancestor resort ids found for %s", self.entity_id)
|
|
172
209
|
return None
|
|
173
210
|
|
|
174
211
|
@property
|
|
175
212
|
def ancestor_land_id(self) -> typing.Optional[str]:
|
|
176
213
|
"""
|
|
177
|
-
The
|
|
214
|
+
The if of the land of this entity.
|
|
178
215
|
|
|
179
216
|
Returns:
|
|
180
|
-
(typing.Optional[str]):
|
|
217
|
+
(typing.Optional[str]): Land id, or None if no such id is found.
|
|
181
218
|
"""
|
|
182
219
|
if self.disney_data is None:
|
|
183
|
-
self.disney_data = self.get_disney_data()
|
|
220
|
+
self.disney_data = self.get_disney_data(self.__facility_service_url)
|
|
184
221
|
try:
|
|
185
|
-
return
|
|
222
|
+
return (
|
|
223
|
+
self.disney_data["links"]["ancestorLand"]["href"]
|
|
224
|
+
.split("?")[0]
|
|
225
|
+
.split("/")[-1]
|
|
226
|
+
)
|
|
186
227
|
except KeyError:
|
|
187
|
-
logger.debug("No ancestor land id found for %s", self.
|
|
228
|
+
logger.debug("No ancestor land id found for %s", self.entity_id)
|
|
188
229
|
return None
|
|
189
230
|
|
|
190
231
|
@property
|
|
191
|
-
def
|
|
232
|
+
def ancestor_resort_area_id(self) -> typing.Optional[str]:
|
|
192
233
|
"""
|
|
193
|
-
The
|
|
234
|
+
The id of the resort area of this entity.
|
|
194
235
|
|
|
195
236
|
Returns:
|
|
196
|
-
(typing.Optional[
|
|
237
|
+
(typing.Optional[str]): Resort area id, or None if no such id is found.
|
|
197
238
|
"""
|
|
198
239
|
if self.disney_data is None:
|
|
199
|
-
self.disney_data = self.get_disney_data()
|
|
240
|
+
self.disney_data = self.get_disney_data(self.__facility_service_url)
|
|
200
241
|
try:
|
|
201
|
-
return
|
|
242
|
+
return (
|
|
243
|
+
self.disney_data["links"]["ancestorResortArea"]["href"]
|
|
244
|
+
.split("?")[0]
|
|
245
|
+
.split("/")[-1]
|
|
246
|
+
)
|
|
202
247
|
except KeyError:
|
|
203
|
-
logger.debug("No ancestor resort area ids found for %s", self.
|
|
248
|
+
logger.debug("No ancestor resort area ids found for %s", self.entity_id)
|
|
204
249
|
return None
|
|
205
250
|
|
|
206
251
|
@property
|
|
207
|
-
def
|
|
252
|
+
def ancestor_entertainment_venue_id(self) -> typing.Optional[str]:
|
|
208
253
|
"""
|
|
209
|
-
The
|
|
254
|
+
The id of entertainment venues of this entity.
|
|
210
255
|
|
|
211
256
|
Returns:
|
|
212
|
-
(typing.Optional[
|
|
257
|
+
(typing.Optional[str]): Entertainment venue id, or None if no such id is found.
|
|
213
258
|
"""
|
|
214
259
|
if self.disney_data is None:
|
|
215
|
-
self.disney_data = self.get_disney_data()
|
|
260
|
+
self.disney_data = self.get_disney_data(self.__facility_service_url)
|
|
216
261
|
try:
|
|
217
|
-
return
|
|
218
|
-
|
|
219
|
-
|
|
262
|
+
return (
|
|
263
|
+
self.disney_data["links"]["ancestorEntertainmentVenue"]["href"]
|
|
264
|
+
.split("?")[0]
|
|
265
|
+
.split("/")[-1]
|
|
266
|
+
)
|
|
220
267
|
except KeyError:
|
|
221
|
-
logger.debug(
|
|
268
|
+
logger.debug(
|
|
269
|
+
"No ancestor entertainment venue ids found for %s", self.entity_id
|
|
270
|
+
)
|
|
222
271
|
return None
|
|
223
272
|
|
|
224
273
|
@property
|
|
225
|
-
def
|
|
274
|
+
def ancestor_restaurant_id(self) -> typing.Optional[str]:
|
|
226
275
|
"""
|
|
227
|
-
The
|
|
276
|
+
The id of the restaurant of this entity.
|
|
228
277
|
|
|
229
278
|
Returns:
|
|
230
|
-
(typing.Optional[
|
|
279
|
+
(typing.Optional[str]): Restaurant id, or None if no such id is found.
|
|
231
280
|
"""
|
|
232
281
|
if self.disney_data is None:
|
|
233
|
-
self.disney_data = self.get_disney_data()
|
|
282
|
+
self.disney_data = self.get_disney_data(self.__facility_service_url)
|
|
234
283
|
try:
|
|
235
|
-
return
|
|
284
|
+
return (
|
|
285
|
+
self.disney_data["links"]["ancestorRestaurant"]["href"]
|
|
286
|
+
.split("?")[0]
|
|
287
|
+
.split("/")[-1]
|
|
288
|
+
)
|
|
236
289
|
except KeyError:
|
|
237
|
-
logger.debug("No ancestor restaurant ids found for %s", self.
|
|
290
|
+
logger.debug("No ancestor restaurant ids found for %s", self.entity_id)
|
|
238
291
|
return None
|
|
239
292
|
|
|
240
293
|
@property
|
|
@@ -246,78 +299,98 @@ class Entity(DisneyAPIMixin, ThemeParkAPIMixin):
|
|
|
246
299
|
(ZoneInfo): The time zone of the entity.
|
|
247
300
|
"""
|
|
248
301
|
|
|
249
|
-
if self.ancestor_destination_id
|
|
302
|
+
if self.ancestor_destination_id is None:
|
|
303
|
+
return ZoneInfo("UTC")
|
|
304
|
+
if self.ancestor_destination_id in DestinationIds.WALT_DISNEY_WORLD.value:
|
|
250
305
|
return ZoneInfo("America/New_York")
|
|
251
|
-
elif self.ancestor_destination_id
|
|
306
|
+
elif self.ancestor_destination_id in DestinationIds.DISNEYLAND_RESORT.value:
|
|
252
307
|
return ZoneInfo("America/Los_Angeles")
|
|
253
|
-
else:
|
|
254
|
-
return ZoneInfo("UTC")
|
|
255
308
|
|
|
256
|
-
|
|
309
|
+
return ZoneInfo("UTC")
|
|
310
|
+
|
|
311
|
+
@property
|
|
312
|
+
def related_location_ids(self) -> typing.List[str]:
|
|
257
313
|
"""
|
|
258
|
-
|
|
314
|
+
The ids of the related locations of this entity.
|
|
259
315
|
|
|
260
316
|
Returns:
|
|
261
|
-
(str): The
|
|
262
|
-
|
|
263
|
-
Raises:
|
|
264
|
-
AncestorDestinationMissing: If the ancestor destination id is not
|
|
265
|
-
either Walt Disney World or Disneyland Resort
|
|
317
|
+
(typing.List[str]): The ids of the related locations of this entity.
|
|
266
318
|
"""
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
elif self.ancestor_destination_id == DestinationIds.DISNEYLAND_RESORT:
|
|
270
|
-
dest_url_friendly_id = "dlr"
|
|
271
|
-
else:
|
|
272
|
-
raise AncestorDestinationMissing
|
|
273
|
-
return f"{ENTITY_DETAILS_SIMPLE_BASE_URL}/{dest_url_friendly_id}/{self.url_friendly_id}/{datetime.now().strftime('%Y-%m-%d')}"
|
|
319
|
+
# https://api.wdprapps.disney.com/facility-service/entertainments/19322758
|
|
320
|
+
raise NotImplementedError
|
|
274
321
|
|
|
275
|
-
|
|
322
|
+
@property
|
|
323
|
+
def duration(self) -> typing.Optional[time]:
|
|
324
|
+
if self.disney_data is None:
|
|
325
|
+
self.disney_data = self.get_disney_data(self.__facility_service_url)
|
|
326
|
+
try:
|
|
327
|
+
return time.fromisoformat(
|
|
328
|
+
":".join(self.disney_data["duration"].split(":")[:3])
|
|
329
|
+
)
|
|
330
|
+
except KeyError:
|
|
331
|
+
logger.debug("No duration found for %s", self.entity_id)
|
|
332
|
+
return None
|
|
333
|
+
|
|
334
|
+
def get_status(self) -> typing.Optional[str]:
|
|
276
335
|
"""
|
|
277
336
|
The current status of the entity.
|
|
278
337
|
|
|
279
338
|
Returns:
|
|
280
339
|
(typing.Optional[str]): The current status of the entity, or None if no such data exists.
|
|
281
340
|
"""
|
|
341
|
+
try:
|
|
342
|
+
live_data = self.get_entity_live_tp()
|
|
343
|
+
except AncestorDestinationMissingError:
|
|
344
|
+
return None
|
|
282
345
|
|
|
283
|
-
live_data = self.get_entity_live_tp()
|
|
284
346
|
try:
|
|
285
347
|
return live_data["liveData"][0]["status"]
|
|
286
348
|
except (KeyError, IndexError):
|
|
287
|
-
logger.debug("No status found for %s", self.
|
|
349
|
+
logger.debug("No status found for %s", self.entity_id)
|
|
288
350
|
return None
|
|
289
351
|
|
|
290
|
-
def
|
|
352
|
+
def get_wait_time(self) -> typing.Optional[int]:
|
|
291
353
|
"""
|
|
292
354
|
The current wait time for the entity.
|
|
293
355
|
|
|
294
356
|
Returns:
|
|
295
357
|
(typing.Optional[int]): The current wait time for the entity, or None if no such data exists.
|
|
296
358
|
"""
|
|
297
|
-
|
|
359
|
+
try:
|
|
360
|
+
live_data = self.get_entity_live_tp()
|
|
361
|
+
except AncestorDestinationMissingError:
|
|
362
|
+
return None
|
|
363
|
+
|
|
298
364
|
try:
|
|
299
365
|
return live_data["liveData"][0]["queue"]["STANDBY"]["waitTime"]
|
|
300
366
|
except (KeyError, IndexError):
|
|
301
|
-
logger.debug("No wait time found for %s", self.
|
|
367
|
+
logger.debug("No wait time found for %s", self.entity_id)
|
|
302
368
|
return None
|
|
303
369
|
|
|
304
|
-
def
|
|
370
|
+
def get_last_updated(self) -> typing.Optional[datetime]:
|
|
305
371
|
"""
|
|
306
|
-
The last time the entity's data was updated.
|
|
372
|
+
The last time the entity's data was updated on ThemePark.wiki.
|
|
307
373
|
|
|
308
374
|
Returns:
|
|
309
375
|
(typing.Optional[datetime]): The last time the entity's data was updated, or None if no such data exists.
|
|
310
376
|
"""
|
|
311
|
-
|
|
377
|
+
try:
|
|
378
|
+
live_data = self.get_entity_live_tp()
|
|
379
|
+
except AncestorDestinationMissingError:
|
|
380
|
+
return None
|
|
381
|
+
|
|
312
382
|
try:
|
|
313
383
|
return datetime.strptime(
|
|
314
|
-
live_data["liveData"][0]["lastUpdated"],
|
|
384
|
+
live_data["liveData"][0]["lastUpdated"],
|
|
385
|
+
"%Y-%m-%dT%H:%M:%SZ",
|
|
315
386
|
).replace(tzinfo=ZoneInfo("UTC"))
|
|
316
387
|
except (KeyError, IndexError):
|
|
317
|
-
logger.debug("No last updated found for %s", self.
|
|
388
|
+
logger.debug("No last updated found for %s", self.entity_id)
|
|
318
389
|
return None
|
|
319
390
|
|
|
320
|
-
def
|
|
391
|
+
def get_today_operating_hours(
|
|
392
|
+
self,
|
|
393
|
+
) -> typing.Optional[dict[str, dict[str, datetime]]]:
|
|
321
394
|
"""
|
|
322
395
|
The operating hours for today for the entity.
|
|
323
396
|
|
|
@@ -325,57 +398,90 @@ class Entity(DisneyAPIMixin, ThemeParkAPIMixin):
|
|
|
325
398
|
(typing.Optional[dict[str, dict[str, datetime]]]): A dictionary of the operating hours for today, or None if no such data exists.
|
|
326
399
|
"""
|
|
327
400
|
|
|
328
|
-
|
|
401
|
+
try:
|
|
402
|
+
live_data = self.get_entity_live_tp()
|
|
403
|
+
except AncestorDestinationMissingError:
|
|
404
|
+
return None
|
|
405
|
+
|
|
329
406
|
temp = {}
|
|
330
407
|
|
|
331
408
|
try:
|
|
332
409
|
for i in live_data["liveData"][0]["operatingHours"]:
|
|
333
410
|
temp[i["type"]] = {
|
|
334
411
|
"start_time": datetime.strptime(
|
|
335
|
-
i["startTime"],
|
|
412
|
+
i["startTime"],
|
|
413
|
+
"%Y-%m-%dT%H:%M:%S%z",
|
|
336
414
|
).replace(tzinfo=self.time_zone),
|
|
337
415
|
"end_time": datetime.strptime(
|
|
338
|
-
i["endTime"],
|
|
416
|
+
i["endTime"],
|
|
417
|
+
"%Y-%m-%dT%H:%M:%S%z",
|
|
339
418
|
).replace(tzinfo=self.time_zone),
|
|
340
419
|
}
|
|
341
420
|
except (KeyError, IndexError):
|
|
342
|
-
logger.debug("No operating hours found for %s", self.
|
|
421
|
+
logger.debug("No operating hours found for %s", self.entity_id)
|
|
343
422
|
return None
|
|
344
423
|
|
|
345
424
|
return temp
|
|
346
425
|
|
|
347
|
-
def
|
|
426
|
+
def get_today_showtimes(self) -> typing.Optional[list[datetime]]:
|
|
348
427
|
"""
|
|
349
428
|
The showtimes for today for the entity.
|
|
350
429
|
|
|
351
430
|
Returns:
|
|
352
431
|
(typing.Optional[list[datetime]]): A list of the showtimes for today, or None if no such data exists.
|
|
353
432
|
"""
|
|
354
|
-
|
|
433
|
+
try:
|
|
434
|
+
live_data = self.get_entity_live_tp()
|
|
435
|
+
except AncestorDestinationMissingError:
|
|
436
|
+
return None
|
|
437
|
+
|
|
355
438
|
temp = []
|
|
356
439
|
|
|
357
440
|
try:
|
|
358
441
|
for i in live_data["liveData"][0]["showtimes"]:
|
|
359
442
|
temp.append(
|
|
360
443
|
datetime.strptime(i["startTime"], "%Y-%m-%dT%H:%M:%S%z").replace(
|
|
361
|
-
tzinfo=self.time_zone
|
|
362
|
-
)
|
|
444
|
+
tzinfo=self.time_zone,
|
|
445
|
+
),
|
|
363
446
|
)
|
|
364
447
|
except (KeyError, IndexError):
|
|
365
|
-
logger.debug("No showtimes found for %s", self.
|
|
448
|
+
logger.debug("No showtimes found for %s", self.entity_id)
|
|
366
449
|
return None
|
|
367
450
|
|
|
368
451
|
return temp
|
|
369
452
|
|
|
453
|
+
def get_children_entity_ids(
|
|
454
|
+
self, entity_type: typing.Union[str, FacilityServiceEntityTypes]
|
|
455
|
+
) -> list[str]:
|
|
456
|
+
"""
|
|
457
|
+
Get the children entity IDs for the given entity type.
|
|
458
|
+
|
|
459
|
+
Args:
|
|
460
|
+
entity_type (typing.Union[str, FacilityServiceEntityTypes]): The type of entity to get children for.
|
|
461
|
+
|
|
462
|
+
Returns:
|
|
463
|
+
(list[str]): A list of the children entity IDs, or an empty list if no such data exists
|
|
464
|
+
"""
|
|
465
|
+
if isinstance(entity_type, FacilityServiceEntityTypes):
|
|
466
|
+
entity_type = entity_type.value
|
|
467
|
+
|
|
468
|
+
children_url = f"{self.__facility_service_url}/{entity_type}"
|
|
469
|
+
data = self.get_disney_data(children_url)
|
|
470
|
+
if data:
|
|
471
|
+
return [
|
|
472
|
+
i["links"]["self"]["href"].split("?")[0].split("/")[-1]
|
|
473
|
+
for i in data["entries"]
|
|
474
|
+
]
|
|
475
|
+
|
|
476
|
+
return []
|
|
477
|
+
|
|
370
478
|
def __str__(self) -> str:
|
|
371
|
-
return f"{self.entity_type}: {self.name} ({self.
|
|
479
|
+
return f"{self.entity_type}: {self.name} ({self.entity_id})"
|
|
372
480
|
|
|
373
481
|
def __repr__(self) -> str:
|
|
374
|
-
return f"
|
|
482
|
+
return f"{self.__class__.__name__}(entity_id='{self.entity_id}')"
|
|
375
483
|
|
|
376
484
|
def __eq__(self, other) -> bool:
|
|
377
|
-
if isinstance(other,
|
|
378
|
-
return self.
|
|
485
|
+
if isinstance(other, EntityBase):
|
|
486
|
+
return self.entity_id == other.entity_id
|
|
379
487
|
return False
|
|
380
|
-
|
|
381
|
-
# TODO virtual queue
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
from mousetools.entities.base import EntityBase
|
|
2
|
+
from mousetools.ids import FacilityServiceEntityTypes
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class Character(EntityBase):
|
|
6
|
+
"""Class for Character Entities."""
|
|
7
|
+
|
|
8
|
+
def __init__(self, entity_id: str):
|
|
9
|
+
super().__init__(
|
|
10
|
+
entity_id=entity_id,
|
|
11
|
+
facility_service_entity_type=FacilityServiceEntityTypes.CHARACTERS,
|
|
12
|
+
)
|
|
@@ -1,8 +1,16 @@
|
|
|
1
|
-
|
|
1
|
+
import typing
|
|
2
2
|
|
|
3
|
+
from mousetools.entities.base import EntityBase
|
|
4
|
+
from mousetools.ids import DestinationIds, FacilityServiceEntityTypes
|
|
3
5
|
|
|
4
|
-
|
|
6
|
+
|
|
7
|
+
class Destination(EntityBase):
|
|
5
8
|
"""Class for Destination Entities."""
|
|
6
9
|
|
|
7
|
-
def
|
|
8
|
-
|
|
10
|
+
def __init__(self, entity_id: typing.Union[str, DestinationIds]):
|
|
11
|
+
if isinstance(entity_id, DestinationIds):
|
|
12
|
+
entity_id = entity_id.value
|
|
13
|
+
super().__init__(
|
|
14
|
+
entity_id=entity_id,
|
|
15
|
+
facility_service_entity_type=FacilityServiceEntityTypes.DESTINATIONS,
|
|
16
|
+
)
|
|
@@ -1,15 +1,12 @@
|
|
|
1
|
-
from mousetools.entities.base import
|
|
1
|
+
from mousetools.entities.base import EntityBase
|
|
2
|
+
from mousetools.ids import FacilityServiceEntityTypes
|
|
2
3
|
|
|
3
4
|
|
|
4
|
-
class DiningEvent(
|
|
5
|
+
class DiningEvent(EntityBase):
|
|
5
6
|
"""Class for DiningEvent Entities."""
|
|
6
7
|
|
|
7
|
-
def
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
"""Class for DiningEvent Entities."""
|
|
13
|
-
|
|
14
|
-
def __repr__(self) -> str:
|
|
15
|
-
return f"DinnerShow(id='{self.id}')"
|
|
8
|
+
def __init__(self, entity_id: str):
|
|
9
|
+
super().__init__(
|
|
10
|
+
entity_id=entity_id,
|
|
11
|
+
facility_service_entity_type=FacilityServiceEntityTypes.DINING_EVENTS,
|
|
12
|
+
)
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
from mousetools.entities.base import EntityBase
|
|
2
|
+
from mousetools.ids import FacilityServiceEntityTypes
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class DinnerShow(EntityBase):
|
|
6
|
+
"""Class for DiningEvent Entities."""
|
|
7
|
+
|
|
8
|
+
def __init__(self, entity_id: str):
|
|
9
|
+
super().__init__(
|
|
10
|
+
entity_id=entity_id,
|
|
11
|
+
facility_service_entity_type=FacilityServiceEntityTypes.DINNER_SHOWS,
|
|
12
|
+
)
|