"""Federation app fragment endpoints. Exposes HTML fragments at ``/internal/fragments/`` for consumption by other coop apps via the fragment client. """ from __future__ import annotations from quart import Blueprint, Response, request from shared.infrastructure.fragments import FRAGMENT_HEADER from shared.sexp.jinja_bridge import sexp def register(): bp = Blueprint("fragments", __name__, url_prefix="/internal/fragments") _handlers: dict[str, object] = {} @bp.before_request async def _require_fragment_header(): if not request.headers.get(FRAGMENT_HEADER): return Response("", status=403) @bp.get("/") async def get_fragment(fragment_type: str): handler = _handlers.get(fragment_type) if handler is None: return Response("", status=200, content_type="text/html") html = await handler() return Response(html, status=200, content_type="text/html") # --- link-card fragment: actor profile preview card -------------------------- def _render_federation_link_card(actor, link: str) -> str: return sexp( '(~link-card :link link :title title :image image' ' :icon "fas fa-user" :subtitle username' ' :detail summary :data-app "federation")', link=link, title=actor.display_name or actor.preferred_username, image=None, username=f"@{actor.preferred_username}" if actor.preferred_username else None, summary=actor.summary, ) async def _link_card_handler(): from quart import g from shared.services.registry import services from shared.infrastructure.urls import federation_url username = request.args.get("username", "") slug = request.args.get("slug", "") keys_raw = request.args.get("keys", "") # Batch mode if keys_raw: usernames = [k.strip() for k in keys_raw.split(",") if k.strip()] parts = [] for u in usernames: parts.append(f"") actor = await services.federation.get_actor_by_username(g.s, u) if actor: parts.append(_render_federation_link_card( actor, federation_url(f"/users/{actor.preferred_username}"), )) return "\n".join(parts) # Single mode lookup = username or slug if not lookup: return "" actor = await services.federation.get_actor_by_username(g.s, lookup) if not actor: return "" return _render_federation_link_card( actor, federation_url(f"/users/{actor.preferred_username}"), ) _handlers["link-card"] = _link_card_handler bp._fragment_handlers = _handlers return bp