fix: xREL badges – sequenziell 1 Film pro Request, 400ms Pause, kein Rate-Limit

This commit is contained in:
2026-06-10 20:55:13 +02:00
parent 4333522bd6
commit 3bd8ab901e
2 changed files with 11 additions and 9 deletions

View File

@@ -246,26 +246,28 @@ router.get('/movie/:id', authenticate, async (req, res) => {
}); });
// POST /api/tools/media/xrel-check Check ob deutsche Releases existieren // POST /api/tools/media/xrel-check Check ob deutsche Releases existieren
// Nimmt max 5 Filme pro Request (Frontend schickt mehrere kleine Batches) // Filme EINZELN sequenziell prüfen um xREL Rate-Limit zu respektieren
router.post('/xrel-check', authenticate, async (req, res) => { router.post('/xrel-check', authenticate, async (req, res) => {
const movies = (req.body.movies || []).slice(0, 5); const movies = (req.body.movies || []).slice(0, 5);
if (!movies.length) return res.json({}); if (!movies.length) return res.json({});
const result = {}; const result = {};
await Promise.all(movies.map(async m => { for (const m of movies) {
try { try {
const extInfoId = await findExtInfoId(m.title, m.original_title); const extInfoId = await findExtInfoId(m.title, m.original_title);
if (!extInfoId) { result[m.id] = false; return; } if (!extInfoId) { result[m.id] = false; continue; }
// P2P zuerst main_lang ist zuverlässig // P2P zuerst main_lang ist zuverlässig
const p2p = await xrelFetch('/p2p/releases.json', { ext_info_id: extInfoId, per_page: 25 }, 8000); const p2p = await xrelFetch('/p2p/releases.json', { ext_info_id: extInfoId, per_page: 25 }, 8000);
if ((p2p.list || []).some(r => r.main_lang === 'german')) { result[m.id] = true; return; } if ((p2p.list || []).some(r => r.main_lang === 'german')) { result[m.id] = true; continue; }
// Scene als Fallback // Scene als Fallback
const scene = await xrelFetch('/release/ext_info.json', { id: extInfoId, per_page: 25 }, 8000); const scene = await xrelFetch('/release/ext_info.json', { id: extInfoId, per_page: 25 }, 8000);
result[m.id] = (scene.list || []).some(r => /german|deutsch/i.test(r.dirname || '')); result[m.id] = (scene.list || []).some(r => /german|deutsch/i.test(r.dirname || ''));
} catch (_) { } catch (_) {
result[m.id] = false; result[m.id] = false;
} }
})); // Kurze Pause zwischen Filmen xREL Rate-Limit
await new Promise(r => setTimeout(r, 400));
}
res.json(result); res.json(result);
}); });

View File

@@ -271,10 +271,10 @@ function KinoGrid({ onOpenModal }) {
let cancelled = false; let cancelled = false;
const moviesMeta = movies.map(m => ({ id: m.id, title: m.title, original_title: m.original_title })); const moviesMeta = movies.map(m => ({ id: m.id, title: m.title, original_title: m.original_title }));
(async () => { (async () => {
for (let i = 0; i < moviesMeta.length; i += 5) { for (let i = 0; i < moviesMeta.length; i += 1) {
if (cancelled) break; if (cancelled) break;
try { try {
const chunk = moviesMeta.slice(i, i + 5); const chunk = moviesMeta.slice(i, i + 1);
const result = await api('/tools/media/xrel-check', { method:'POST', body:{ movies: chunk } }); const result = await api('/tools/media/xrel-check', { method:'POST', body:{ movies: chunk } });
if (cancelled) break; if (cancelled) break;
const hits = Object.entries(result).filter(([,v]) => v).map(([k]) => Number(k)); const hits = Object.entries(result).filter(([,v]) => v).map(([k]) => Number(k));
@@ -340,10 +340,10 @@ function DemnächstGrid({ onOpenModal }) {
let cancelled = false; let cancelled = false;
const moviesMeta = allMovies.map(m => ({ id: m.id, title: m.title, original_title: m.original_title })); const moviesMeta = allMovies.map(m => ({ id: m.id, title: m.title, original_title: m.original_title }));
(async () => { (async () => {
for (let i = 0; i < moviesMeta.length; i += 5) { for (let i = 0; i < moviesMeta.length; i += 1) {
if (cancelled) break; if (cancelled) break;
try { try {
const chunk = moviesMeta.slice(i, i + 5); const chunk = moviesMeta.slice(i, i + 1);
const result = await api('/tools/media/xrel-check', { method:'POST', body:{ movies: chunk } }); const result = await api('/tools/media/xrel-check', { method:'POST', body:{ movies: chunk } });
if (cancelled) break; if (cancelled) break;
const hits = Object.entries(result).filter(([,v]) => v).map(([k]) => Number(k)); const hits = Object.entries(result).filter(([,v]) => v).map(([k]) => Number(k));