This commit is contained in:
team3
2026-09-08 23:50:25 +02:00
parent 08c2e8f885
commit 00cb299f31
2 changed files with 49 additions and 11 deletions

View File

@@ -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

View File

@@ -1,11 +1,15 @@
<script setup>
import { ref, watch } from 'vue'
import { computed, ref, watch } from 'vue'
import MovieCard from './MovieCard.vue'
import { filterParameter } from '../filter.js'
// Der Ausgangsfilm steht als erste Karte davor, macht einundzwanzig
const TREFFER = 20
// Eine Detailkarte nimmt die halbe Breite ein, eine kompakte ein Achtel.
// Gleich viele Vorschläge wären mal eine Reihe, mal zehn.
const VORSCHLAEGE = { kompakt: 20, details: 8 }
const props = defineProps({
filter: { type: Object, default: () => ({}) },
ansicht: { type: String, default: 'kompakt' },
@@ -16,7 +20,11 @@ const props = defineProps({
const emit = defineEmits(['open', 'gestartet'])
const query = ref('')
const vorschlaege = ref([])
const gefunden = ref([])
// Beim Wechsel der Ansicht wird nur neu geschnitten, nicht neu gesucht
const vorschlaege = computed(() =>
gefunden.value.slice(0, VORSCHLAEGE[props.ansicht] ?? 8)
)
const gewaehlt = ref(null)
const treffer = ref([])
const laden = ref(false)
@@ -32,7 +40,7 @@ let laufendeTreffer = 0
// dazu passt.
async function suchen(term) {
if (term.trim().length < 2) {
vorschlaege.value = []
gefunden.value = []
return
}
const meine = ++laufende
@@ -41,7 +49,7 @@ async function suchen(term) {
if (!resp.ok) throw new Error('Suche fehlgeschlagen')
const daten = await resp.json()
if (meine !== laufende) return
vorschlaege.value = daten.slice(0, 8)
gefunden.value = daten
} catch (err) {
if (meine === laufende) fehler.value = err.message
}
@@ -50,7 +58,7 @@ async function suchen(term) {
async function waehlen(film) {
const meine = ++laufendeWahl
gewaehlt.value = film
vorschlaege.value = []
gefunden.value = []
query.value = ''
nachladen()