diff --git a/api/ovdashboard_api/config.py b/api/ovdashboard_api/config.py index fc5a733..ea526d4 100644 --- a/api/ovdashboard_api/config.py +++ b/api/ovdashboard_api/config.py @@ -37,22 +37,13 @@ class ImageConfig(BaseModel): } -class CalAggregateConfig(BaseModel): - """ - Sections "[[calendar.aggregate]]" in "config.txt". - """ - - name: str = "All Events" - calendars: list[str] - - class CalendarConfig(BaseModel): """ Section "[calendar]" in "config.txt". """ future_days: int = 365 - aggregate: list[CalAggregateConfig] = [] + aggregate: dict[str, list[str]] = {} class Config(BaseModel): @@ -79,9 +70,7 @@ class Config(BaseModel): except RemoteResourceNotFound: cfg = cls() - cfg.calendar.aggregate.append( - CalAggregateConfig(calendars=await caldav_list()), - ) + cfg.calendar.aggregate["All Events"] = list(await caldav_list()) buffer = BytesIO() toml_dump(cfg.dict(), buffer) diff --git a/api/ovdashboard_api/routers/__init__.py b/api/ovdashboard_api/routers/__init__.py index 263eba4..64f4c53 100644 --- a/api/ovdashboard_api/routers/__init__.py +++ b/api/ovdashboard_api/routers/__init__.py @@ -7,12 +7,13 @@ This file: Main API router definition. from fastapi import APIRouter from ..settings import SETTINGS -from . import calendar, image, text +from . import cal_aggregate, calendar, image, text main_router = APIRouter(prefix=f"/{SETTINGS.api_v1_prefix}") main_router.include_router(text.router) main_router.include_router(image.router) main_router.include_router(calendar.router) +main_router.include_router(cal_aggregate.router) __all__ = [ "main_router", diff --git a/api/ovdashboard_api/routers/_common.py b/api/ovdashboard_api/routers/_common.py index 8c210d3..f633299 100644 --- a/api/ovdashboard_api/routers/_common.py +++ b/api/ovdashboard_api/routers/_common.py @@ -9,6 +9,7 @@ from typing import Iterator, Protocol from fastapi import HTTPException, status from webdav3.exceptions import RemoteResourceNotFound +from ..config import Config from ..dav_common import caldav_list, webdav_list @@ -74,6 +75,18 @@ class CalendarNameLister: return await caldav_list() +@dataclass(frozen=True) +class CalAggregateLister: + """ + Can be called to create an iterator containing CalAggregate names. + """ + + async def __call__(self) -> Iterator[str]: + cfg = await Config.get() + + return iter(cfg.calendar.aggregate.keys()) + + @dataclass(frozen=True) class PrefixFinder: """ diff --git a/api/ovdashboard_api/routers/cal_aggregate.py b/api/ovdashboard_api/routers/cal_aggregate.py new file mode 100644 index 0000000..2f76510 --- /dev/null +++ b/api/ovdashboard_api/routers/cal_aggregate.py @@ -0,0 +1,49 @@ +""" +Router "cal_aggregate" provides: + +- listing aggregate calendars +- finding aggregate calendars by name prefix +- getting aggregate calendar events by name prefix +""" + +from typing import Iterator + +from fastapi import APIRouter, Depends +from ovdashboard_api.config import Config + +from ..dav_calendar import CalEvent, DavCalendar +from ._common import CalAggregateLister, PrefixFinder, PrefixUnique + +router = APIRouter(prefix="/aggregate", tags=["calendar"]) + +_lister = CalAggregateLister() +_finder = PrefixFinder(_lister) +_unique = PrefixUnique(_finder) + + +@router.get("/list", response_model=list[str]) +async def list_aggregate_calendars( + names: Iterator[str] = Depends(_lister), +) -> list[str]: + return list(names) + + +@router.get("/find/{prefix}", response_model=list[str]) +async def find_aggregate_calendars( + names: Iterator[str] = Depends(_finder), +) -> list[str]: + return list(names) + + +@router.get("/get/{prefix}", response_model=list[CalEvent]) +async def get_aggregate_calendar( + name: Iterator[str] = Depends(_unique), +) -> list[CalEvent]: + cfg = await Config.get() + aggregate = cfg.calendar.aggregate[name] + + return sorted([ + event + for calendar_name in aggregate + for event in (await DavCalendar(calendar_name).events) + ])