fix: xREL 3 Suchstrategien, normalisierte Queries, debug-xrel3 Endpoint
This commit is contained in:
@@ -126,36 +126,64 @@ async function getXrelData(tmdbId, imdbId, title, originalTitle) {
|
|||||||
const cached = cacheGet(cacheKey);
|
const cached = cacheGet(cacheKey);
|
||||||
if (cached !== undefined) return cached;
|
if (cached !== undefined) return cached;
|
||||||
|
|
||||||
// Alle Suchen parallel – originaltitel und deutsch gleichzeitig
|
const clean = (s) => normalizeUmlauts(s||'').replace(/[*#!?:]/g,'').trim().toLowerCase();
|
||||||
const clean = (s) => (s||'').replace(/[*#!?:]/g,'').trim().toLowerCase();
|
|
||||||
const queries = [originalTitle, title].filter(Boolean).filter((v,i,a) => a.indexOf(v)===i);
|
|
||||||
|
|
||||||
const searchResults = await Promise.all(queries.map(async q => {
|
// Suchqueries: original, deutsch, und normalisierte Varianten
|
||||||
|
// Wichtig: xREL nutzt oft den englischen Originaltitel auch bei deutschen Filmen
|
||||||
|
const rawQueries = [originalTitle, title].filter(Boolean).filter((v,i,a) => a.indexOf(v)===i);
|
||||||
|
// Normalisierte Versionen (Umlaute) als zusätzliche Queries
|
||||||
|
const normQueries = rawQueries.map(q => normalizeUmlauts(q).replace(/[*#!?:]/g,'').trim())
|
||||||
|
.filter(q => !rawQueries.map(r => r.replace(/[*#!?:]/g,'').trim()).includes(q));
|
||||||
|
const allQueries = [...rawQueries, ...normQueries].filter(Boolean).filter((v,i,a) => a.indexOf(v)===i);
|
||||||
|
|
||||||
|
// Alle parallel suchen
|
||||||
|
const searchResults = await Promise.all(allQueries.map(async q => {
|
||||||
try {
|
try {
|
||||||
return await xrelFetch('/search/ext_info.json', {
|
return {
|
||||||
|
q,
|
||||||
|
data: await xrelFetch('/search/ext_info.json', {
|
||||||
q: normalizeUmlauts(q).replace(/[*#!?:]/g,''), type:'movie', limit:10
|
q: normalizeUmlauts(q).replace(/[*#!?:]/g,''), type:'movie', limit:10
|
||||||
});
|
})
|
||||||
|
};
|
||||||
} catch(_) { return null; }
|
} catch(_) { return null; }
|
||||||
}));
|
}));
|
||||||
|
|
||||||
let extInfoId = null;
|
let extInfoId = null;
|
||||||
// IMDb-URI Match zuerst
|
|
||||||
|
// Strategie 1: IMDb-URI exakter Match (zuverlässigste Methode)
|
||||||
if (imdbId) {
|
if (imdbId) {
|
||||||
for (const data of searchResults) {
|
for (const r of searchResults) {
|
||||||
const hit = (data?.results||[]).find(h => (h.uris||[]).includes(`imdb:${imdbId}`));
|
if (!r) continue;
|
||||||
if (hit?.id) { extInfoId = hit.id; break; }
|
const hit = (r.data?.results||[]).find(h => (h.uris||[]).includes(`imdb:${imdbId}`));
|
||||||
}
|
|
||||||
}
|
|
||||||
// Exakter Titel-Match als Fallback
|
|
||||||
if (!extInfoId) {
|
|
||||||
for (const data of searchResults) {
|
|
||||||
const hit = (data?.results||[]).find(h => clean(h.title)===clean(queries[0]) || clean(h.alt_title)===clean(queries[0]));
|
|
||||||
if (hit?.id) { extInfoId = hit.id; break; }
|
if (hit?.id) { extInfoId = hit.id; break; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Strategie 2: Exakter Titel-Match
|
||||||
if (!extInfoId) {
|
if (!extInfoId) {
|
||||||
cacheSet(cacheKey, [], 60*60*1000); // 1h für nicht gefunden
|
for (const r of searchResults) {
|
||||||
|
if (!r) continue;
|
||||||
|
const hit = (r.data?.results||[]).find(h =>
|
||||||
|
clean(h.title) === clean(r.q) || clean(h.alt_title) === clean(r.q)
|
||||||
|
);
|
||||||
|
if (hit?.id) { extInfoId = hit.id; break; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Strategie 3: Einziger Treffer bei IMDb-Suche (nur wenn exakt 1 Ergebnis)
|
||||||
|
if (!extInfoId && imdbId) {
|
||||||
|
for (const r of searchResults) {
|
||||||
|
if (!r) continue;
|
||||||
|
const results = r.data?.results || [];
|
||||||
|
if (results.length === 1 && results[0].type === 'movie') {
|
||||||
|
extInfoId = results[0].id;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!extInfoId) {
|
||||||
|
cacheSet(cacheKey, [], 60*60*1000);
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -331,4 +359,36 @@ router.put('/settings', authenticate, requireAdmin, (req, res) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// DEBUG – nach Test entfernen
|
||||||
|
router.get('/debug-xrel3', authenticate, async (req, res) => {
|
||||||
|
const title = req.query.title || '';
|
||||||
|
const orig = req.query.orig || '';
|
||||||
|
const imdb_id = req.query.imdb_id || null;
|
||||||
|
const log = { title, orig, imdb_id };
|
||||||
|
try {
|
||||||
|
const clean = (s) => normalizeUmlauts(s||'').replace(/[*#!?:]/g,'').trim().toLowerCase();
|
||||||
|
const rawQueries = [orig, title].filter(Boolean).filter((v,i,a) => a.indexOf(v)===i);
|
||||||
|
const normQueries = rawQueries.map(q => normalizeUmlauts(q).replace(/[*#!?:]/g,'').trim())
|
||||||
|
.filter(q => !rawQueries.map(r => r.replace(/[*#!?:]/g,'').trim()).includes(q));
|
||||||
|
log.rawQueries = rawQueries;
|
||||||
|
log.normQueries = normQueries;
|
||||||
|
log.allQueries = [...rawQueries, ...normQueries].filter(Boolean).filter((v,i,a) => a.indexOf(v)===i);
|
||||||
|
|
||||||
|
const results = [];
|
||||||
|
for (const q of log.allQueries) {
|
||||||
|
try {
|
||||||
|
const data = await xrelFetch('/search/ext_info.json', {
|
||||||
|
q: normalizeUmlauts(q).replace(/[*#!?:]/g,''), type:'movie', limit:5
|
||||||
|
});
|
||||||
|
results.push({
|
||||||
|
query: normalizeUmlauts(q).replace(/[*#!?:]/g,''),
|
||||||
|
hits: (data.results||[]).map(h => ({ id: h.id, title: h.title, alt_title: h.alt_title, uris: h.uris }))
|
||||||
|
});
|
||||||
|
} catch(e) { results.push({ query: q, error: e.message }); }
|
||||||
|
}
|
||||||
|
log.searchResults = results;
|
||||||
|
} catch(e) { log.error = e.message; }
|
||||||
|
res.json(log);
|
||||||
|
});
|
||||||
|
|
||||||
module.exports = router;
|
module.exports = router;
|
||||||
|
|||||||
Reference in New Issue
Block a user