Move caldav_handler to caldav.py
Test python action / test (push) Successful in 38s
Pull-Request Vibe Check / ci-test (pull_request) Successful in 29s

Make the sleep interruptable
Add debug endpoints for caldav - gonna make a new endpoint for them i think...
This commit is contained in:
2026-11-05 22:48:26 +01:00
parent 9810a4f810
commit 1d37be5317
4 changed files with 92 additions and 20 deletions
+25
View File
@@ -6,6 +6,7 @@ from sqlmodel import Session, select
from app.model.models import Card
from app.services.auth import auth_is_admin
from app.services.caldav import get_caldav_handler
from app.services.database import add_and_refresh, get_session
logger = logging.getLogger(__name__)
@@ -63,3 +64,27 @@ def list_all_cards(db: Session = Depends(get_session)):
for i in cards:
out.append({i.key: i.group.name})
return out
@debug_router.get("/calGetActiveEvents")
def cal_get_active_events(db: Session = Depends(get_session)):
handler = get_caldav_handler()
if handler is None:
raise HTTPException(503, "Caldav handler not initialized")
return handler.get_active_events()
@debug_router.get("/calGetFutureEvents")
def cal_get_future_events(db: Session = Depends(get_session)):
handler = get_caldav_handler()
if handler is None:
raise HTTPException(503, "Caldav handler not initialized")
return handler.get_future_events()
@debug_router.get("/calGetActiveGroups")
def cal_get_active_groups(db: Session = Depends(get_session)):
handler = get_caldav_handler()
if handler is None:
raise HTTPException(503, "Caldav handler not initialized")
return handler.get_active_groups()
+4 -11
View File
@@ -14,9 +14,9 @@ from app.controllers import (
userManager,
)
from app.services.auth import create_first_user, token_router
from app.services.caldav import CaldavEventCache
from app.services.caldav import init_caldav_handler, stop_caldav_handler
from app.services.database import create_db_and_tables, get_db_session
from app.services.door import DoorController, init_caldav_handler, init_controller
from app.services.door import DoorController, init_controller
from app.services.scanner import BackgroundScanner
from app.services.settings import settings
@@ -24,12 +24,6 @@ logger = logging.getLogger(__name__)
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
scanner = BackgroundScanner(db=get_db_session())
caldav_handler = CaldavEventCache(
url=settings.caldav_url,
username=settings.caldav_user,
password=settings.caldav_password,
calendarNames=settings.caldav_calendars,
)
logging.basicConfig(level=logging.INFO)
@@ -47,14 +41,13 @@ async def lifespan(app: FastAPI):
if not settings.disable_cards:
scanner.start()
if not settings.disable_caldav:
caldav_handler.start()
init_caldav_handler(caldav_handler)
init_caldav_handler()
logger.info("-" * 63)
logger.info("---- Documentation is at http://127.0.0.1:8000/api/v1/docs ----")
logger.info("-" * 63)
yield
stop_caldav_handler()
# scanner.stop()
+60 -2
View File
@@ -1,6 +1,5 @@
import logging
import threading
import time
from datetime import UTC, date, datetime, timedelta
from caldav import get_calendars
@@ -19,18 +18,21 @@ class CaldavEventCache:
self.events = []
self.is_running = False
self.thread: threading.Thread | None = None
self._stopped = threading.Event()
def start(self):
if self.is_running:
logger.error("CaldavEventCache already running")
return
self.is_running = True
self._stopped.clear()
self.thread = threading.Thread(target=self._refresh_loop, daemon=True)
self.thread.start()
logger.info("CaldavEventCache started")
def stop(self):
self.is_running = False
self._stopped.set()
if self.thread:
self.thread.join()
logger.info("CaldavEventCache stopped")
@@ -41,7 +43,7 @@ class CaldavEventCache:
self.refresh()
except Exception as e:
logger.error(f"Error updating CaldavEventCache: {e}", exc_info=True)
time.sleep(settings.caldav_refresh_interval)
self._stopped.wait(settings.caldav_refresh_interval)
def refresh(self, daysBack=1, daysAhead=7):
calendars = get_calendars(
@@ -113,6 +115,28 @@ class CaldavEventCache:
return active
def get_future_events(self, active_time=None):
active_time = active_time or datetime.now().astimezone()
if active_time.tzinfo is None:
active_time = active_time.astimezone()
today = active_time.date()
future = []
for event in self.events:
start = event["start"]
if event["all_day"]: # noqa: SIM108
# All-day event end dates are exclusive.
is_active = start <= today
else:
is_active = start <= active_time
if is_active:
future.append(event)
return future
def get_active_groups(self, active_time=None):
active_events = self.get_active_events(active_time)
@@ -126,3 +150,37 @@ class CaldavEventCache:
def is_group_active(self, group_name, active_time=None):
return group_name in self.get_active_groups(active_time)
_caldav_handler: CaldavEventCache | None = None
def init_caldav_handler() -> CaldavEventCache | None:
"""Build and start the event cache from settings.
Returns None when caldav handling is disabled
"""
global _caldav_handler
if settings.disable_caldav:
logger.info("Caldav handling disabled")
return None
handler = CaldavEventCache(
url=settings.caldav_url,
username=settings.caldav_user,
password=settings.caldav_password,
calendarNames=settings.caldav_calendars,
)
handler.start()
_caldav_handler = handler
return handler
def get_caldav_handler() -> CaldavEventCache | None:
return _caldav_handler
def stop_caldav_handler() -> None:
global _caldav_handler
if _caldav_handler is not None:
_caldav_handler.stop()
_caldav_handler = None
+3 -7
View File
@@ -5,6 +5,7 @@ from sqlalchemy import exc
from sqlmodel import select
from app.model.models import Card, OneShotAccess
from app.services.caldav import get_caldav_handler
from app.services.database import Session, add_and_refresh
logger = logging.getLogger(__name__)
@@ -65,7 +66,6 @@ class DoorController:
_contoller: DoorController | None = None
_caldav_handler = None
def init_controller(ctrl: DoorController):
@@ -73,11 +73,6 @@ def init_controller(ctrl: DoorController):
_contoller = ctrl
def init_caldav_handler(handler):
global _caldav_handler
_caldav_handler = handler
def get_controller():
if _contoller is None:
raise RuntimeError("DoorController not initialized.")
@@ -111,7 +106,8 @@ def checkAccess(key: str, db: Session):
logger.info("Card Inactive!")
return False
if _caldav_handler and _caldav_handler.is_group_active(card.group.name):
caldav_handler = get_caldav_handler()
if caldav_handler and caldav_handler.is_group_active(card.group.name):
logger.info("Access Valid!")
return True