lint / ruff (push) Failing after 15s
tests / desktop (push) Successful in 21s
tests / web (push) Successful in 46s
docker / image (push) Failing after 1m31s
tests / android-core (push) Successful in 1m5s
tests / backend (push) Successful in 2m33s
android / apk (push) Successful in 4m34s
86 lines
2.4 KiB
Python
86 lines
2.4 KiB
Python
"""Request bodies. Responses are plain dicts built by the services."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from datetime import date
|
|
from typing import Any, Literal
|
|
|
|
from pydantic import BaseModel, Field
|
|
|
|
|
|
class StartTimerRequest(BaseModel):
|
|
kind: Literal["work", "short_break", "long_break"] | None = None
|
|
minutes: int | None = Field(default=None, ge=1, le=240)
|
|
task_id: int | None = None
|
|
note: str | None = None
|
|
|
|
|
|
class AbandonRequest(BaseModel):
|
|
reason: str | None = None
|
|
|
|
|
|
class ExtendRequest(BaseModel):
|
|
minutes: int = Field(default=5, ge=1, le=120)
|
|
|
|
|
|
class AttachTaskRequest(BaseModel):
|
|
task_id: int | None = None
|
|
|
|
|
|
class CompleteTimerRequest(BaseModel):
|
|
auto_next: bool = True
|
|
session_id: int | None = None
|
|
"""Which interval the client believes it is finishing.
|
|
|
|
Every client ticks its own local countdown and calls `complete` when it
|
|
reaches zero, so with two of them open (the phone and the desktop, say)
|
|
both fire within the same second. Unconditionally, the second call lands
|
|
on whatever `auto_next` has just started and ends *that* — which is why a
|
|
break could vanish the instant it began. Sent along, a stale call is a
|
|
no-op instead. Omitted, the old unconditional behaviour stands.
|
|
"""
|
|
|
|
|
|
class TaskCreateRequest(BaseModel):
|
|
title: str = Field(min_length=1, max_length=500)
|
|
description: str | None = None
|
|
due_date: date | None = None
|
|
priority: str | None = None
|
|
project: str | None = None
|
|
estimated_pomodoros: int | None = Field(default=None, ge=1, le=50)
|
|
|
|
|
|
class TaskUpdateRequest(BaseModel):
|
|
title: str | None = None
|
|
description: str | None = None
|
|
due_date: date | None = None
|
|
priority: str | None = None
|
|
project: str | None = None
|
|
estimated_pomodoros: int | None = None
|
|
pinned: bool | None = None
|
|
|
|
|
|
class BlockEventRequest(BaseModel):
|
|
kind: Literal["domain", "app"] = "domain"
|
|
target: str = Field(min_length=1, max_length=255)
|
|
action: Literal["blocked", "killed", "warned"] = "blocked"
|
|
details: str | None = None
|
|
|
|
|
|
class SendReportRequest(BaseModel):
|
|
report_date: date | None = None
|
|
force: bool = True
|
|
|
|
|
|
class TestNotificationRequest(BaseModel):
|
|
text: str | None = None
|
|
|
|
|
|
class SettingsPatch(BaseModel):
|
|
"""A partial settings document; anything omitted keeps its stored value."""
|
|
|
|
model_config = {"extra": "allow"}
|
|
|
|
def as_dict(self) -> dict[str, Any]:
|
|
return self.model_dump(exclude_unset=True)
|