fix(backend): Schraegstrich im Namen und zu lockere Titelsuche fuehrten auf die falsche Datei
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
eb72e5c27d
commit
24558497da
4 files changed
+193
-53
No files matched your search
@@ -118,6 +118,70 @@ function findExistingTrack(musicRoot, firstArtist, cleanTitle) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const AUDIO_EXT_RE = /\.(mp3|flac|opus|m4a|ogg|wav)$/i;
|
||||
|
||||
// Vereinheitlicht einen Dateinamen-Stamm fuer den lockeren Vergleich:
|
||||
// 1. fuehrende Track-Praefixe wie "01-15 – " oder "01 - " abschneiden
|
||||
// 2. alle Strichvarianten (en/em dash) auf " - " bringen
|
||||
function normStem(s) {
|
||||
return s
|
||||
.replace(/^\d[\d\-–—]*\s*[-–—]\s*/, '')
|
||||
.replace(/\s*[–—]\s*/g, ' - ');
|
||||
}
|
||||
|
||||
// Tiefensuche nach einer Audiodatei, deren Stamm zum Titel passt. Letzter Ausweg, wenn der von
|
||||
// Navidrome gemeldete Pfad nicht existiert (Ordner umbenannt, Tag-Pfad statt echtem Pfad).
|
||||
//
|
||||
// WICHTIG: der Titel muss ein VOLLSTAENDIGES Feld des Dateinamens sein, nie nur dessen Ende.
|
||||
// Ein blosses endsWith(titel) liess "Bad Omens - Like A Villain" als Treffer fuer den Titel
|
||||
// "VILLAIN" durchgehen — ein voellig anderer Song derselben Endsilbe. Genau solche Fehlgriffe
|
||||
// landen sonst im Metadaten-Editor oder, schlimmer, im Loeschen-Endpunkt.
|
||||
function findFileByStem(dir, titleStem, depth = 0) {
|
||||
if (depth > 4) return null;
|
||||
const normTitle = normStem(titleStem);
|
||||
try {
|
||||
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
||||
if (entry.isDirectory()) {
|
||||
const found = findFileByStem(path.join(dir, entry.name), titleStem, depth + 1);
|
||||
if (found) return found;
|
||||
} else if (AUDIO_EXT_RE.test(entry.name)) {
|
||||
const bare = entry.name.replace(AUDIO_EXT_RE, '').replace(/^\d+\s*-\s*/, '');
|
||||
const bareStem = normStem(bare.toLowerCase());
|
||||
// Treffer: exakt, "Kuenstler - Titel", oder Release-Suffix-Versatz ("… - Single").
|
||||
if (bareStem === normTitle ||
|
||||
bareStem.endsWith(' - ' + normTitle) ||
|
||||
bareStem.startsWith(normTitle + ' - ') ||
|
||||
normTitle.startsWith(bareStem + ' - ')) {
|
||||
return path.join(dir, entry.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch {}
|
||||
return null;
|
||||
}
|
||||
|
||||
// Navidrome gibt ueber die Subsonic-API standardmaessig keinen echten Pfad heraus, sondern baut
|
||||
// einen aus den Tags: {AlbumArtist}/{Album}/{DD}-{TT} - {Titel}.{Endung}. Steht ein "/" IM Namen
|
||||
// — "K/DA", "POP/STARS" —, wird daraus eine zusaetzliche Verzeichnisebene, waehrend auf der Platte
|
||||
// sanitize() ein "_" geschrieben hat ("K_DA/POP_STARS"). Der gemeldete Pfad existiert dann nicht,
|
||||
// und die Suche faellt auf Aehnlichkeit zurueck. Diese Funktion baut den Ordner stattdessen genau
|
||||
// so zusammen, wie der Downloader ihn angelegt haette.
|
||||
function albumDirFromTags(musicRoot, albumArtist, album) {
|
||||
if (!musicRoot || !albumArtist) return null;
|
||||
// Der Downloader legt den Ordner unter dem ERSTEN Kuenstler an (mainArtist.split(/[,;&]/)[0]).
|
||||
const ersterKuenstler = String(albumArtist).split(/[,;&]/)[0].trim();
|
||||
const kandidaten = [];
|
||||
for (const k of new Set([ersterKuenstler, String(albumArtist).trim()])) {
|
||||
if (!k) continue;
|
||||
if (album) kandidaten.push(path.join(musicRoot, sanitize(k), sanitize(album)));
|
||||
kandidaten.push(path.join(musicRoot, sanitize(k)));
|
||||
}
|
||||
for (const c of kandidaten) {
|
||||
try { if (fs.statSync(c).isDirectory()) return c; } catch {}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// Fetch plain + synced lyrics from LRCLIB
|
||||
async function fetchLyrics(artist, title, album) {
|
||||
try {
|
||||
@@ -140,4 +204,5 @@ async function fetchLyrics(artist, title, album) {
|
||||
module.exports = {
|
||||
sanitize, navidromeArtist,
|
||||
downloadArtwork, findExistingTrack,
|
||||
normStem, findFileByStem, albumDirFromTags,
|
||||
};
|
||||
Reference in new issue
Block a user