fix: SC album defaults to title, filter [Unknown Album] placeholder, fallback file search
- SC resolve: strip yt-dlp placeholder albums (starting with '['), use track title as album for singles - edit-metadata: if Navidrome path stale, search music root recursively for file by name - Both single and playlist SC track handling updated Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
98ad8ed579
commit
52ba73506f
1 file changed
+29
-2
@@ -46,6 +46,22 @@ if (!fs.existsSync(CONFIG.musicPath)) {
|
||||
fs.mkdirSync(CONFIG.musicPath, { recursive: true });
|
||||
}
|
||||
|
||||
// Search for a file by exact name anywhere under a directory (max depth 5)
|
||||
function _findFileRecursive(dir, name, depth = 0) {
|
||||
if (depth > 5) return null;
|
||||
try {
|
||||
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
||||
if (entry.isDirectory()) {
|
||||
const found = _findFileRecursive(path.join(dir, entry.name), name, depth + 1);
|
||||
if (found) return found;
|
||||
} else if (entry.name === name) {
|
||||
return path.join(dir, entry.name);
|
||||
}
|
||||
}
|
||||
} catch {}
|
||||
return null;
|
||||
}
|
||||
|
||||
// ─── QUEUE ────────────────────────────────────────────────────────────────────
|
||||
let activeDownloads = 0;
|
||||
const downloadQueue = [];
|
||||
@@ -420,6 +436,7 @@ app.post('/api/soundcloud/resolve', async (req, res) => {
|
||||
artworkUrl: e.thumbnail || '',
|
||||
duration: e.duration || 0,
|
||||
genre: e.genre || '',
|
||||
album: (e.album && !e.album.startsWith('[')) ? e.album : (e.title || ''),
|
||||
sourceUrl: e.url || e.webpage_url || '',
|
||||
}));
|
||||
res.json({
|
||||
@@ -430,13 +447,16 @@ app.post('/api/soundcloud/resolve', async (req, res) => {
|
||||
tracks,
|
||||
});
|
||||
} else {
|
||||
// Filter yt-dlp placeholder values — treat them as empty
|
||||
const scAlbum = (data.album && !data.album.startsWith('[')) ? data.album : '';
|
||||
const track = {
|
||||
trackName: data.title || '',
|
||||
artistName: data.uploader || data.artist || '',
|
||||
artworkUrl: data.thumbnail || '',
|
||||
duration: data.duration || 0,
|
||||
genre: data.genre || '',
|
||||
album: data.album || '',
|
||||
// Use track title as album for singles with no real album
|
||||
album: scAlbum || data.title || '',
|
||||
year: data.upload_date ? parseInt(data.upload_date.slice(0, 4), 10) : undefined,
|
||||
sourceUrl: url,
|
||||
};
|
||||
@@ -516,7 +536,14 @@ app.post('/api/edit-metadata', async (req, res) => {
|
||||
|
||||
// If not absolute, try relative to music root
|
||||
if (!path.isAbsolute(filePath)) filePath = path.join(CONFIG.musicPath, filePath);
|
||||
if (!fs.existsSync(filePath)) return res.status(404).json({ error: `File not found: ${filePath}` });
|
||||
|
||||
// Fallback: if Navidrome path stale/wrong, search for the file by name under music root
|
||||
if (!fs.existsSync(filePath)) {
|
||||
const fileName = path.basename(filePath);
|
||||
const found = _findFileRecursive(CONFIG.musicPath, fileName);
|
||||
if (found) { filePath = found; }
|
||||
else return res.status(404).json({ error: `File not found: ${filePath}` });
|
||||
}
|
||||
|
||||
// Resolve artwork: base64 > URL
|
||||
let artFile = null;
|
||||
|
||||
Reference in new issue
Block a user