Move caldav_handler to caldav.py
Make the sleep interruptable Add debug endpoints for caldav - gonna make a new endpoint for them i think...
This commit is contained in:
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user