rename project to fhdhview

This commit is contained in:
dreamer committed 2026-10-19 16:01:27 +02:00
1 parent c4d3b6b292
commit 6755875938
51 files changed
+39 -39

No files matched your search

View File
Whitespace-only changes.
+55
View File
@@ -0,0 +1,55 @@
# SPDX-FileCopyrightText: 2026 Filmhuis Den Haag
# SPDX-License-Identifier: AGPL-3.0-or-later
from pathlib import Path
from fastapi import APIRouter, Depends, File, HTTPException, UploadFile, status
from fastapi.responses import FileResponse, JSONResponse
from sqlmodel.ext.asyncio.session import AsyncSession
from fhdhview.api.deps import check_auth, get_session
from fhdhview.services.screenwriter.importer import import_sessions
from fhdhview.services.screenwriter.parser import XmlParseError, parse_screenwriter_xml
BASE_DIR = Path(__file__).resolve().parent.parent
router = APIRouter(
prefix="/admin",
tags=["Admin"],
dependencies=[Depends(check_auth)]
)
@router.get("", response_class=FileResponse)
async def upload_form():
return FileResponse(BASE_DIR / "html" / "upload.html")
@router.post("/upload", response_class=JSONResponse)
async def upload_file(
file: UploadFile = File(...),
session: AsyncSession = Depends(get_session)
):
if not file.filename or not file.filename.lower().endswith(".xml"):
raise HTTPException(
status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,
detail="File must be an XML file"
)
contents = await file.read()
if len(contents) > 10 * 1024 * 1024:
raise HTTPException(
status_code=status.HTTP_413_REQUEST_ENTITY_TOO_LARGE,
detail="File too large"
)
try:
aampos = parse_screenwriter_xml(contents)
except XmlParseError as e:
raise HTTPException(
status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,
detail=str(e)
)
await import_sessions(aampos, session=session)
return JSONResponse(content={"filename": file.filename, "size": len(contents)})
+28
View File
@@ -0,0 +1,28 @@
# SPDX-FileCopyrightText: 2026 Filmhuis Den Haag
# SPDX-License-Identifier: AGPL-3.0-or-later
import secrets
from collections.abc import AsyncGenerator
from fastapi import Depends, HTTPException, status
from fastapi.security import HTTPBasic, HTTPBasicCredentials
from sqlmodel.ext.asyncio.session import AsyncSession
from fhdhview.core.config import settings
from fhdhview.core.database import async_session
security = HTTPBasic()
async def get_session() -> AsyncGenerator[AsyncSession]:
async with async_session() as session:
yield session
def check_auth(credentials: HTTPBasicCredentials = Depends(security)):
if not secrets.compare_digest(credentials.password.encode(), settings.api_password.encode()):
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Invalid credentials",
headers={"WWW-Authenticate": "Basic"},
)
+36
View File
@@ -0,0 +1,36 @@
# SPDX-FileCopyrightText: 2026 Filmhuis Den Haag
# SPDX-License-Identifier: AGPL-3.0-or-later
from fastapi import APIRouter, status
from pydantic import BaseModel
router = APIRouter(
prefix="/health",
tags=["Health"]
)
class HealthCheck(BaseModel):
"""Response model to validate and return when performing a health check."""
status: str = "OK"
@router.get(
"/",
summary="Perform a Health Check",
response_description="Return HTTP Status Code 200 (OK)",
status_code=status.HTTP_200_OK,
response_model=HealthCheck,
)
def get_health() -> HealthCheck:
"""
## Perform a Health Check
Endpoint to perform a healthcheck on. This endpoint can primarily be used Docker
to ensure a robust container orchestration and management is in place. Other
services which rely on proper functioning of the API service will not deploy if this
endpoint returns any other HTTP status code except 200 (OK).
Returns:
HealthCheck: Returns a JSON response with the health status
"""
return HealthCheck(status="OK")
+19
View File
@@ -0,0 +1,19 @@
# SPDX-FileCopyrightText: 2026 Filmhuis Den Haag
# SPDX-License-Identifier: AGPL-3.0-or-later
from pathlib import Path
from fastapi import APIRouter
from fastapi.responses import FileResponse
BASE_DIR = Path(__file__).resolve().parent.parent
router = APIRouter(
prefix="/info",
tags=["Info"]
)
@router.get("", response_class=FileResponse)
async def get_info():
return FileResponse(BASE_DIR / "html" / "info.html")
+47
View File
@@ -0,0 +1,47 @@
# SPDX-FileCopyrightText: 2026 Filmhuis Den Haag
# SPDX-License-Identifier: AGPL-3.0-or-later
from datetime import datetime, timedelta
from zoneinfo import ZoneInfo
from fastapi import APIRouter, Depends
from sqlmodel import col, select
from sqlmodel.ext.asyncio.session import AsyncSession
from fhdhview.api.deps import get_session
from fhdhview.core.config import settings
from fhdhview.models.screening import Screening
from fhdhview.schemas.screening import ScreeningRead
router = APIRouter(prefix="/screenings", tags=["Screenings"])
@router.get(
"",
response_model=list[ScreeningRead],
summary="Get upcoming screenings for the infodesk"
)
async def get_infodesk_screenings(
session: AsyncSession = Depends(get_session)
) -> list[ScreeningRead]:
now = datetime.now(tz=ZoneInfo(settings.timezone))
today = now.date()
query = (
select(Screening)
.where(Screening.start > now - timedelta(minutes=10))
.where(Screening.start < today + timedelta(days=1))
.order_by(col(Screening.start))
.limit(8)
)
screenings = await session.exec(query)
return [ScreeningRead.model_validate(s) for s in screenings.all()]
@router.get(
"/prices",
response_model=dict,
summary="Get pricing information"
)
async def get_screening_prices() -> dict:
return settings.prices