122 lines
3.2 KiB
Python
122 lines
3.2 KiB
Python
from __future__ import annotations
|
|
|
|
from datetime import date
|
|
from enum import Enum
|
|
|
|
from pydantic import BaseModel, Field, field_validator
|
|
|
|
|
|
class LogStatus(str, Enum):
|
|
taken = "taken"
|
|
missed = "missed"
|
|
snoozed = "snoozed"
|
|
|
|
|
|
class PinLogin(BaseModel):
|
|
pin: str = Field(
|
|
...,
|
|
min_length=3,
|
|
max_length=12,
|
|
description="Login-PIN, wie in APP_PIN hinterlegt.",
|
|
)
|
|
|
|
|
|
class LogEntry(BaseModel):
|
|
slot_id: str = Field(
|
|
...,
|
|
min_length=1,
|
|
max_length=64,
|
|
description="ID des Medikamenten-Slots, z.B. 'morning'.",
|
|
)
|
|
status: LogStatus = Field(
|
|
default=LogStatus.taken,
|
|
description="Status der Einnahme: taken, missed oder snoozed.",
|
|
)
|
|
day: date | None = Field(
|
|
default=None,
|
|
description="Optional: Tag im ISO-Format (YYYY-MM-DD). Standard ist heute.",
|
|
)
|
|
logged_at: str | None = Field(
|
|
default=None,
|
|
description="Optional: Zeitstempel im ISO-Format. Standard ist jetzt (UTC).",
|
|
)
|
|
source: str = Field(
|
|
default="app",
|
|
description="Herkunft des Logs, z.B. 'app', 'widget' oder 'voice'.",
|
|
)
|
|
|
|
|
|
class SnoozeRequest(BaseModel):
|
|
slot_id: str = Field(
|
|
...,
|
|
min_length=1,
|
|
max_length=64,
|
|
description="ID des Slots, der verschoben werden soll.",
|
|
)
|
|
minutes: int = Field(
|
|
...,
|
|
description="Snooze-Dauer in Minuten. Erlaubt: 15 oder 30.",
|
|
)
|
|
|
|
@field_validator("minutes")
|
|
@classmethod
|
|
def allowed_snooze(cls, v: int) -> int:
|
|
if v not in (15, 30):
|
|
raise ValueError("minutes must be 15 or 30")
|
|
return v
|
|
|
|
|
|
class PushSubscribe(BaseModel):
|
|
subscription: dict = Field(
|
|
...,
|
|
description="Web-Push-Subscription-Objekt vom Browser (PushManager.subscribe).",
|
|
)
|
|
|
|
|
|
class AgentLogEntry(BaseModel):
|
|
slot_id: str = Field(
|
|
...,
|
|
min_length=1,
|
|
max_length=64,
|
|
description="ID des Medikamenten-Slots, z.B. 'morning'.",
|
|
)
|
|
status: LogStatus = Field(
|
|
default=LogStatus.taken,
|
|
description="Status der Einnahme: taken, missed oder snoozed.",
|
|
)
|
|
day: date | None = Field(
|
|
default=None,
|
|
description="Optional: Tag im ISO-Format (YYYY-MM-DD). Standard ist heute.",
|
|
)
|
|
logged_at: str | None = Field(
|
|
default=None,
|
|
description="Optional: Zeitstempel im ISO-Format. Standard ist jetzt (UTC).",
|
|
)
|
|
source: str = Field(
|
|
default="agent",
|
|
description="Herkunft des Logs, z.B. 'agent', 'voice' oder 'watch'.",
|
|
)
|
|
|
|
|
|
class AgentNotifyRequest(BaseModel):
|
|
title: str = Field(
|
|
...,
|
|
min_length=1,
|
|
max_length=120,
|
|
description="Titel der Push-Benachrichtigung.",
|
|
)
|
|
body: str = Field(
|
|
...,
|
|
min_length=1,
|
|
max_length=512,
|
|
description="Textkörper der Push-Benachrichtigung.",
|
|
)
|
|
slot_id: str | None = Field(
|
|
default=None,
|
|
description="Optional: zugehörige Slot-ID, wird an den Client weitergegeben.",
|
|
)
|
|
tag: str | None = Field(
|
|
default=None,
|
|
description="Optional: Notification-Tag für das Ersetzen älterer Notifications.",
|
|
)
|