"""Web lookup routes — image picker and driver-download search. Both return HTML fragments for HTMX, never JSON: the results are only ever rendered into a page, and keeping the shaping server-side means the templates own the "unverified source" warnings. """ from __future__ import annotations from fastapi import APIRouter, Request from fastapi.responses import HTMLResponse from imptune.db.models import Driver, Printer from imptune.services import websearch from imptune.templating import templates router = APIRouter(prefix="/web") MAX_RESULTS = 12 _TARGETS = ("printer", "driver") def _notice(key: str, fallback: str, status_code: int = 200) -> HTMLResponse: """A one-line status fragment that still speaks French. Server-rendered fragments are normally English-only, but these are the everyday path (empty search box, disabled feature), so they go through the i18n store like the rest of the picker — Alpine initializes the swapped-in node, and the English body is the fallback if it does not. """ return HTMLResponse( content=f"

{fallback}

", status_code=status_code, ) @router.get("/images", response_class=HTMLResponse) def search_images( request: Request, q: str = "", target: str = "printer", id: int = 0, ) -> HTMLResponse: """Image results for `q`, each pickable as the icon of `target`/`id`. `target` decides which POST endpoint the result buttons hit, so the picker is the same partial for a printer icon and a driver icon. """ if not websearch.enabled(): return _notice("web_search_off", "Web lookups are disabled on this server.") if target not in _TARGETS: return _notice("unknown_target", "Unknown search target.", status_code=400) # Confirm the caller may write to this entity before spending a search on # it — an unowned printer id must not even reveal that it exists. if target == "printer": owned = Printer.get_or_none( (Printer.id == id) & (Printer.owner == request.state.owner) ) if owned is None: return _notice("printer_not_found", "Printer not found.", status_code=404) post_url = f"/printers/{id}/icon/from-web" status_target = "#icon-status" else: if Driver.get_or_none(Driver.id == id) is None: return _notice("driver_not_found", "Driver not found.", status_code=404) post_url = f"/drivers/{id}/icon/from-web" status_target = f"#driver-icon-status-{id}" query = q.strip() if not query: return _notice("type_to_search_image", "Type something to search for.") hits = websearch.search_images(query, limit=MAX_RESULTS) return templates.TemplateResponse( request=request, name="partials/image_results.html", context={ "hits": hits, "query": query, "post_url": post_url, "status_target": status_target, }, ) @router.get("/drivers", response_class=HTMLResponse) def search_driver_pages(request: Request, q: str = "", mode: str = "generic") -> HTMLResponse: """Search the web for a driver download page. `mode=generic` rewrites the term into the vendor's universal-driver product name (HP UPD, Xerox Global, …); `mode=exact` searches the text as typed. Results are plain links — nothing is downloaded, and the partial says so. """ if not websearch.enabled(): return _notice("web_search_off", "Web lookups are disabled on this server.") typed = q.strip() if not typed: return _notice("type_to_search_driver", "Type a printer model or brand to search for.") query = websearch.generic_driver_query(typed) if mode == "generic" else typed hits = websearch.search_pages(query, limit=MAX_RESULTS) return templates.TemplateResponse( request=request, name="partials/driver_search_results.html", context={ "hits": hits, "query": query, "typed": typed, "mode": mode, "brand": websearch.detect_brand(typed), }, )