mirror of
				https://git.sr.ht/~tsileo/microblog.pub
				synced 2025-06-05 21:59:23 +02:00 
			
		
		
		
	
		
			
				
	
	
		
			113 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			113 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
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
 |