fix(backend): Zahlen im Titel sind Pflicht-Keywords, Abkuerzungen erlaubt
"700 Main Street" lud "777 Main Street" eines fremden Artists: buildTitleKeywords behielt nur die zwei laengsten Woerter (Street, Main), die unterscheidende 700 fiel als zu kurz raus — und Schritt 3 der Kaskade prueft den Kuenstler-Channel nicht mehr. Zahlen werden jetzt immer als \b<n>\b gefordert. Dazu eine kleine Abkuerzungstabelle (street/st, saint/st, mount/mt, doctor/dr, versus/vs, number/no), denn der korrekte Art Track heisst "700 Main st" und scheiterte bisher an jedem Schritt. Tests in backend/test/ytdlp.test.js. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
9f0d4c3153
commit
02b590505a
4 files changed
+75
-4
No files matched your search
+18
-4
@@ -26,9 +26,23 @@ function buildTitleKeywords(title) {
|
||||
.replace(/[^\w\s]/g, ' ')
|
||||
.split(/\s+/)
|
||||
.filter(w => w.length >= 3 && !VARIANT_WORDS.has(w.toLowerCase()) && !STOPWORDS.has(w.toLowerCase()));
|
||||
const top2 = words.sort((a, b) => b.length - a.length).slice(0, 2);
|
||||
const toPattern = w => (w.length >= 4 && w.endsWith('s')) ? w + '?' : w;
|
||||
const result = top2.map(toPattern);
|
||||
// Numbers are the most distinctive token a title has and they are usually SHORT, so the
|
||||
// longest-two rule threw them away: "700 Main Street" kept only Street+Main and happily matched
|
||||
// "777 Main Street" by a different artist. Numbers are therefore always required, on top of the
|
||||
// two longest words.
|
||||
const numbers = words.filter(w => /^\d+$/.test(w));
|
||||
const wordsNoNum = words.filter(w => !/^\d+$/.test(w));
|
||||
const top2 = wordsNoNum.sort((a, b) => b.length - a.length).slice(0, 2);
|
||||
// Uploaders abbreviate the same word the release spells out ("700 Main St" vs "700 Main Street"),
|
||||
// which rejected the official Art Track in every cascade step. Accept either spelling; \b keeps
|
||||
// the short form from matching inside another word.
|
||||
const ABBREV = { street: 'st', saint: 'st', mount: 'mt', doctor: 'dr', versus: 'vs', number: 'no' };
|
||||
const toPattern = w => {
|
||||
const abbr = ABBREV[w.toLowerCase()];
|
||||
if (abbr) return `\\b(?:${w}|${abbr})\\b`;
|
||||
return (w.length >= 4 && w.endsWith('s')) ? w + '?' : w;
|
||||
};
|
||||
const result = [...numbers.map(n => `\\b${n}\\b`), ...top2.map(toPattern)];
|
||||
const qualifier = lower.includes('mix') ? MIX_QUALIFIERS.find(q => lower.includes(q)) : null;
|
||||
if (qualifier && !top2.some(w => w.toLowerCase() === qualifier)) result.push(qualifier);
|
||||
return result;
|
||||
@@ -424,4 +438,4 @@ async function embedMetadata({ jobId, audioFile, dir, trackPrefix, safeTitle, ra
|
||||
return { success: true, dir };
|
||||
}
|
||||
|
||||
module.exports = { downloadTrack, embedMetadata };
|
||||
module.exports = { downloadTrack, embedMetadata, buildTitleKeywords };
|
||||
Reference in new issue
Block a user