fix: media – FSK nur Top10 parallel, kein FSK-Lookup bei allen Filmen (Timeout-Fix)
This commit is contained in:
@@ -39,15 +39,17 @@ function extractFSK(releaseDates) {
|
||||
return de.release_dates.find(r => r.certification)?.certification || null;
|
||||
}
|
||||
|
||||
// Alle Seiten einer TMDb-Liste holen (bis max. maxPages)
|
||||
async function fetchAllPages(path, maxPages = 5) {
|
||||
// Alle Seiten holen (parallel)
|
||||
async function fetchAllPages(path, maxPages = 3) {
|
||||
const first = await tmdb(path, { page: 1 });
|
||||
const total = Math.min(first.total_pages || 1, maxPages);
|
||||
let results = [...first.results];
|
||||
const extra = await Promise.all(
|
||||
Array.from({ length: total - 1 }, (_, i) => tmdb(path, { page: i + 2 }))
|
||||
);
|
||||
for (const p of extra) results = results.concat(p.results);
|
||||
if (total > 1) {
|
||||
const extra = await Promise.all(
|
||||
Array.from({ length: total - 1 }, (_, i) => tmdb(path, { page: i + 2 }))
|
||||
);
|
||||
for (const p of extra) results = results.concat(p.results);
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
@@ -55,95 +57,83 @@ function enrichMovie(movie, genreMap, fsk, rank) {
|
||||
return {
|
||||
id: movie.id,
|
||||
title: movie.title || movie.original_title,
|
||||
original_title: movie.original_title,
|
||||
original_language: movie.original_language,
|
||||
poster_path: movie.poster_path,
|
||||
overview: movie.overview,
|
||||
release_date: movie.release_date,
|
||||
vote_average: movie.vote_average,
|
||||
genres: (movie.genre_ids || movie.genres?.map(g => g.id) || [])
|
||||
.map(id => genreMap[id]).filter(Boolean),
|
||||
genres: (movie.genre_ids || []).map(id => genreMap[id]).filter(Boolean),
|
||||
fsk: fsk || null,
|
||||
rank: rank || null,
|
||||
};
|
||||
}
|
||||
|
||||
// FSK für eine Liste von Filmen parallel holen
|
||||
async function withFSK(movies, genreMap, topN = 10) {
|
||||
return Promise.all(movies.map(async (m, i) => {
|
||||
let fsk = null;
|
||||
try {
|
||||
const detail = await tmdb(`/movie/${m.id}/release_dates`);
|
||||
fsk = extractFSK(detail);
|
||||
} catch (_) {}
|
||||
return enrichMovie(m, genreMap, fsk, i < topN ? i + 1 : null);
|
||||
}));
|
||||
}
|
||||
|
||||
// GET /api/tools/media/now-playing – alles was aktuell in DE läuft
|
||||
// GET /api/tools/media/now-playing
|
||||
// FSK nur für Top 10 parallel holen, Rest ohne – kein sequentielles Warten
|
||||
router.get('/now-playing', authenticate, async (req, res) => {
|
||||
try {
|
||||
const [all, genreMap] = await Promise.all([
|
||||
const [pages, genreMap] = await Promise.all([
|
||||
fetchAllPages('/movie/now_playing', 3),
|
||||
getGenreMap(),
|
||||
]);
|
||||
const filtered = all.filter(m => m.original_language !== 'tr');
|
||||
const enriched = await withFSK(filtered, genreMap, 10);
|
||||
res.json(enriched);
|
||||
|
||||
const filtered = pages.filter(m => m.original_language !== 'tr');
|
||||
|
||||
// Top 10: FSK parallel holen
|
||||
const top10raw = filtered.slice(0, 10);
|
||||
const restRaw = filtered.slice(10);
|
||||
|
||||
const top10 = await Promise.all(top10raw.map(async (m, i) => {
|
||||
let fsk = null;
|
||||
try { const d = await tmdb(`/movie/${m.id}/release_dates`); fsk = extractFSK(d); } catch (_) {}
|
||||
return enrichMovie(m, genreMap, fsk, i + 1);
|
||||
}));
|
||||
|
||||
const rest = restRaw.map(m => enrichMovie(m, genreMap, null, null));
|
||||
|
||||
res.json([...top10, ...rest]);
|
||||
} catch (e) {
|
||||
res.status(500).json({ error: e.message });
|
||||
}
|
||||
});
|
||||
|
||||
// GET /api/tools/media/upcoming – wochenweise Neustarts, alle verfügbaren
|
||||
// GET /api/tools/media/upcoming
|
||||
// Wochenweise gruppiert, kein FSK-Lookup beim Listing
|
||||
router.get('/upcoming', authenticate, async (req, res) => {
|
||||
try {
|
||||
const [all, genreMap] = await Promise.all([
|
||||
fetchAllPages('/movie/upcoming', 4),
|
||||
const [pages, genreMap] = await Promise.all([
|
||||
fetchAllPages('/movie/upcoming', 3),
|
||||
getGenreMap(),
|
||||
]);
|
||||
const filtered = all.filter(m => m.original_language !== 'tr');
|
||||
|
||||
// Deduplizieren nach ID
|
||||
const seen = new Set();
|
||||
const unique = filtered.filter(m => { if (seen.has(m.id)) return false; seen.add(m.id); return true; });
|
||||
const filtered = pages
|
||||
.filter(m => m.original_language !== 'tr')
|
||||
.filter(m => { if (seen.has(m.id)) return false; seen.add(m.id); return true; })
|
||||
.filter(m => m.release_date);
|
||||
|
||||
// Nach Erscheinungsdatum sortieren
|
||||
unique.sort((a, b) => (a.release_date || '').localeCompare(b.release_date || ''));
|
||||
filtered.sort((a, b) => a.release_date.localeCompare(b.release_date));
|
||||
|
||||
// Wochenweise gruppieren (Montag der jeweiligen Woche als Key)
|
||||
// Wochenweise gruppieren (Montag als Key)
|
||||
const groups = {};
|
||||
for (const m of unique) {
|
||||
if (!m.release_date) continue;
|
||||
const d = new Date(m.release_date);
|
||||
// Montag der Woche berechnen
|
||||
const day = d.getDay(); // 0=So
|
||||
const diff = (day === 0 ? -6 : 1 - day);
|
||||
for (const m of filtered) {
|
||||
const d = new Date(m.release_date);
|
||||
const dow = d.getDay(); // 0=So
|
||||
const diff = dow === 0 ? -6 : 1 - dow;
|
||||
const mon = new Date(d);
|
||||
mon.setDate(d.getDate() + diff);
|
||||
const key = mon.toISOString().slice(0, 10);
|
||||
if (!groups[key]) groups[key] = [];
|
||||
groups[key].push(m);
|
||||
groups[key].push(enrichMovie(m, genreMap, null, null));
|
||||
}
|
||||
|
||||
// Anreichern: nur die erste Gruppe bekommt FSK (spart API-Calls), Rest ohne
|
||||
const result = {};
|
||||
let globalRank = 0;
|
||||
for (const [week, movies] of Object.entries(groups)) {
|
||||
result[week] = await Promise.all(movies.map(async m => {
|
||||
globalRank++;
|
||||
let fsk = null;
|
||||
try { const d = await tmdb(`/movie/${m.id}/release_dates`); fsk = extractFSK(d); } catch (_) {}
|
||||
return enrichMovie(m, genreMap, fsk, null);
|
||||
}));
|
||||
}
|
||||
res.json(result); // { "2026-06-02": [...], "2026-06-09": [...], ... }
|
||||
res.json(groups);
|
||||
} catch (e) {
|
||||
res.status(500).json({ error: e.message });
|
||||
}
|
||||
});
|
||||
|
||||
// GET /api/tools/media/movie/:id – Detail + Credits für Modal
|
||||
// GET /api/tools/media/movie/:id – Details + Credits (nur für Modal)
|
||||
router.get('/movie/:id', authenticate, async (req, res) => {
|
||||
try {
|
||||
const [detail, genreMap] = await Promise.all([
|
||||
@@ -153,7 +143,6 @@ router.get('/movie/:id', authenticate, async (req, res) => {
|
||||
res.json({
|
||||
id: detail.id,
|
||||
title: detail.title || detail.original_title,
|
||||
original_title: detail.original_title,
|
||||
tagline: detail.tagline,
|
||||
overview: detail.overview,
|
||||
poster_path: detail.poster_path,
|
||||
@@ -161,7 +150,6 @@ router.get('/movie/:id', authenticate, async (req, res) => {
|
||||
release_date: detail.release_date,
|
||||
runtime: detail.runtime,
|
||||
vote_average: detail.vote_average,
|
||||
vote_count: detail.vote_count,
|
||||
genres: (detail.genres || []).map(g => g.name),
|
||||
fsk: extractFSK(detail.release_dates),
|
||||
cast: (detail.credits?.cast || []).slice(0, 8).map(a => a.name),
|
||||
|
||||
Reference in New Issue
Block a user