forked from Lash-L/python-snoo
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbaby.py
More file actions
116 lines (93 loc) · 4.45 KB
/
baby.py
File metadata and controls
116 lines (93 loc) · 4.45 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
from datetime import datetime
from python_snoo.containers import Activity, BabyData, BreastfeedingActivity, DiaperActivity, DiaperTypes
from python_snoo.exceptions import SnooBabyError
from python_snoo.snoo import Snoo
class Baby:
def __init__(self, baby_id: str, snoo: Snoo):
self.baby_id = baby_id
self.snoo = snoo
self.baby_url = f"https://api-us-east-1-prod.happiestbaby.com/us/me/v10/babies/{self.baby_id}"
self.activity_base_url = "https://api-us-east-1-prod.happiestbaby.com/cs/me/v11"
@property
def session(self):
return self.snoo.session
async def get_status(self) -> BabyData:
hdrs = self.snoo.generate_snoo_auth_headers(self.snoo.tokens.aws_id)
try:
r = await self.session.get(self.baby_url, headers=hdrs)
resp = await r.json()
except Exception as ex:
raise SnooBabyError from ex
return BabyData.from_dict(resp)
async def get_activity_data(self, from_date: datetime, to_date: datetime) -> list[Activity]:
"""Get activity data for this baby including feeding and diaper changes
Args:
from_date: Start date for activity range
to_date: End date for activity range
Returns:
List of typed Activity objects (DiaperActivity or BreastfeedingActivity)
"""
hdrs = self.snoo.generate_snoo_auth_headers(self.snoo.tokens.aws_id)
url = f"{self.activity_base_url}/babies/{self.baby_id}/journals/grouped-tracking"
params = {
"group": "activity",
"fromDateTime": from_date.astimezone().isoformat(timespec="milliseconds"),
"toDateTime": to_date.astimezone().isoformat(timespec="milliseconds"),
}
try:
r = await self.session.get(url, headers=hdrs, params=params)
resp = await r.json()
if r.status < 200 or r.status >= 300:
raise SnooBabyError(f"Failed to get activity data: {r.status}: {resp}. Payload: {params}")
activities: list[Activity] = []
if isinstance(resp, list):
for activity in resp:
activity_type = activity.get("type", "").lower()
if activity_type == "diaper":
activities.append(DiaperActivity.from_dict(activity))
elif activity_type == "breastfeeding":
activities.append(BreastfeedingActivity.from_dict(activity))
else:
# Other activity types exist but aren't supported yet
raise SnooBabyError(f"Unknown activity type: {activity_type}")
else:
raise SnooBabyError(f"Unexpected response format: {type(resp)}")
return activities
except Exception as ex:
raise SnooBabyError from ex
async def log_diaper_change(
self,
diaper_types: list[DiaperTypes],
note: str | None = None,
start_time: datetime | None = None,
) -> DiaperActivity:
"""Log a diaper change for this baby
Args:
diaper_types (list): List of diaper types. e.g. ['pee'], ['poo'], or ['pee', 'poo']
note (str, optional): Optional note about the diaper change
start_time (datetime, optional): Diaper change timestamp, doesn't allow length.
Defaults to current local time if not provided.
"""
if not start_time:
start_time = datetime.now()
# Always include the timezone indicator in the ISO string - seems to be required by the API
if start_time.tzinfo is None:
start_time = start_time.astimezone()
hdrs = self.snoo.generate_snoo_auth_headers(self.snoo.tokens.aws_id)
url = f"{self.activity_base_url}/journals"
payload = {
"babyId": self.baby_id,
"data": {"types": [dt.value for dt in diaper_types]},
"type": "diaper",
"startTime": start_time.isoformat(timespec="milliseconds"),
}
if note:
payload["note"] = note
try:
r = await self.session.post(url, headers=hdrs, json=payload)
resp = await r.json()
if r.status < 200 or r.status >= 300:
raise SnooBabyError(f"Failed to log diaper change: {r.status}: {resp}. Payload: {payload}")
return DiaperActivity.from_dict(resp)
except Exception as ex:
raise SnooBabyError from ex