First shot at supporting custom handler
This commit is contained in:
parent
817dd98c5c
commit
32692a7dcd
7 changed files with 216 additions and 1 deletions
112
app/customization.py
Normal file
112
app/customization.py
Normal file
|
@ -0,0 +1,112 @@
|
|||
from pathlib import Path
|
||||
from typing import Any
|
||||
from typing import Callable
|
||||
|
||||
from fastapi import APIRouter
|
||||
from fastapi import Depends
|
||||
from fastapi import Request
|
||||
from starlette.responses import JSONResponse
|
||||
|
||||
_DATA_DIR = Path().parent.resolve() / "data"
|
||||
_Handler = Callable[..., Any]
|
||||
|
||||
|
||||
class HTMLPage:
|
||||
def __init__(
|
||||
self,
|
||||
title: str,
|
||||
html_file: str,
|
||||
show_in_navbar: bool,
|
||||
) -> None:
|
||||
self.title = title
|
||||
self.html_file = _DATA_DIR / html_file
|
||||
self.show_in_navbar = show_in_navbar
|
||||
|
||||
|
||||
class RawHandler:
|
||||
def __init__(
|
||||
self,
|
||||
title: str,
|
||||
handler: Any,
|
||||
show_in_navbar: bool,
|
||||
) -> None:
|
||||
self.title = title
|
||||
self.handler = handler
|
||||
self.show_in_navbar = show_in_navbar
|
||||
|
||||
|
||||
_CUSTOM_ROUTES: dict[str, HTMLPage | RawHandler] = {}
|
||||
|
||||
|
||||
def register_html_page(
|
||||
path: str,
|
||||
*,
|
||||
title: str,
|
||||
html_file: str,
|
||||
show_in_navbar: bool = True,
|
||||
) -> None:
|
||||
if path in _CUSTOM_ROUTES:
|
||||
raise ValueError(f"{path} is already registered")
|
||||
|
||||
_CUSTOM_ROUTES[path] = HTMLPage(title, html_file, show_in_navbar)
|
||||
|
||||
|
||||
def register_raw_handler(
|
||||
path: str,
|
||||
*,
|
||||
title: str,
|
||||
handler: _Handler,
|
||||
show_in_navbar: bool = True,
|
||||
) -> None:
|
||||
if path in _CUSTOM_ROUTES:
|
||||
raise ValueError(f"{path} is already registered")
|
||||
|
||||
_CUSTOM_ROUTES[path] = RawHandler(title, handler, show_in_navbar)
|
||||
|
||||
|
||||
class ActivityPubResponse(JSONResponse):
|
||||
media_type = "application/activity+json"
|
||||
|
||||
|
||||
def _custom_page_handler(path: str, html_page: HTMLPage) -> Any:
|
||||
from app import templates
|
||||
from app.actor import LOCAL_ACTOR
|
||||
from app.config import is_activitypub_requested
|
||||
from app.database import AsyncSession
|
||||
from app.database import get_db_session
|
||||
|
||||
async def _handler(
|
||||
request: Request,
|
||||
db_session: AsyncSession = Depends(get_db_session),
|
||||
) -> templates.TemplateResponse | ActivityPubResponse:
|
||||
if path == "/" and is_activitypub_requested(request):
|
||||
return ActivityPubResponse(LOCAL_ACTOR.ap_actor)
|
||||
|
||||
return await templates.render_template(
|
||||
db_session,
|
||||
request,
|
||||
"custom_page.html",
|
||||
{
|
||||
"page_content": html_page.html_file.read_text(),
|
||||
"title": html_page.title,
|
||||
},
|
||||
)
|
||||
|
||||
return _handler
|
||||
|
||||
|
||||
def get_custom_router() -> APIRouter | None:
|
||||
if not _CUSTOM_ROUTES:
|
||||
return None
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
for path, handler in _CUSTOM_ROUTES.items():
|
||||
if isinstance(handler, HTMLPage):
|
||||
router.add_api_route(
|
||||
path, _custom_page_handler(path, handler), methods=["GET"]
|
||||
)
|
||||
else:
|
||||
router.add_api_route(path, handler.handler)
|
||||
|
||||
return router
|
Loading…
Add table
Add a link
Reference in a new issue