diff --git a/backend/app/search.py b/backend/app/search.py index d3b0a4e..3cca02c 100644 --- a/backend/app/search.py +++ b/backend/app/search.py @@ -7,6 +7,7 @@ landen nicht in der Datenbank. import asyncio import random +import unicodedata import httpx @@ -172,14 +173,43 @@ async def discover(filter_, limit=40): return treffer +def ohne_zeichen(text): + """Umlaute und Akzente auf den Grundbuchstaben zurückführen.""" + zerlegt = unicodedata.normalize("NFD", text) + return "".join(z for z in zerlegt if not unicodedata.combining(z)) + + async def search(query, limit=24): + # TMDB findet angefangene Wörter nur ohne Umlaut: "Wilden Hüh" liefert + # nichts, "Wilden Huh" die drei Hühner-Filme. Wer beim Tippen sucht, + # steht sonst vor einer leeren Seite. Also beide Schreibweisen fragen. + schlicht = ohne_zeichen(query) + begriffe = [query] if schlicht == query else [query, schlicht] + + async def einmal(begriff): + try: + resp = await http.get( + "/search/movie", + params={ + "query": begriff, + "language": LANGUAGE, + "include_adult": "false", + }, + ) + resp.raise_for_status() + return resp.json().get("results", []) + except httpx.HTTPError: + return [] + async with client() as http: - resp = await http.get( - "/search/movie", - params={"query": query, "language": LANGUAGE, "include_adult": "false"}, - ) - resp.raise_for_status() - results = resp.json().get("results", []) + results = [] + gesehen = set() + # Die Treffer der wörtlichen Suche stehen vorn + for liste in await asyncio.gather(*(einmal(b) for b in begriffe)): + for eintrag in liste: + if eintrag["id"] not in gesehen: + gesehen.add(eintrag["id"]) + results.append(eintrag) # Ohne Poster taugt eine Kachel nichts, und Namenlose sind fast immer # Dubletten oder Making-ofs diff --git a/frontend/src/components/AehnlichTab.vue b/frontend/src/components/AehnlichTab.vue index 23d2d56..9783462 100644 --- a/frontend/src/components/AehnlichTab.vue +++ b/frontend/src/components/AehnlichTab.vue @@ -1,11 +1,15 @@