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 });
|
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 ────────────────────────────────────────────────────────────────────
|
// ─── QUEUE ────────────────────────────────────────────────────────────────────
|
||||||
let activeDownloads = 0;
|
let activeDownloads = 0;
|
||||||
const downloadQueue = [];
|
const downloadQueue = [];
|
||||||
@@ -420,6 +436,7 @@ app.post('/api/soundcloud/resolve', async (req, res) => {
|
|||||||
artworkUrl: e.thumbnail || '',
|
artworkUrl: e.thumbnail || '',
|
||||||
duration: e.duration || 0,
|
duration: e.duration || 0,
|
||||||
genre: e.genre || '',
|
genre: e.genre || '',
|
||||||
|
album: (e.album && !e.album.startsWith('[')) ? e.album : (e.title || ''),
|
||||||
sourceUrl: e.url || e.webpage_url || '',
|
sourceUrl: e.url || e.webpage_url || '',
|
||||||
}));
|
}));
|
||||||
res.json({
|
res.json({
|
||||||
@@ -430,13 +447,16 @@ app.post('/api/soundcloud/resolve', async (req, res) => {
|
|||||||
tracks,
|
tracks,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
// Filter yt-dlp placeholder values — treat them as empty
|
||||||
|
const scAlbum = (data.album && !data.album.startsWith('[')) ? data.album : '';
|
||||||
const track = {
|
const track = {
|
||||||
trackName: data.title || '',
|
trackName: data.title || '',
|
||||||
artistName: data.uploader || data.artist || '',
|
artistName: data.uploader || data.artist || '',
|
||||||
artworkUrl: data.thumbnail || '',
|
artworkUrl: data.thumbnail || '',
|
||||||
duration: data.duration || 0,
|
duration: data.duration || 0,
|
||||||
genre: data.genre || '',
|
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,
|
year: data.upload_date ? parseInt(data.upload_date.slice(0, 4), 10) : undefined,
|
||||||
sourceUrl: url,
|
sourceUrl: url,
|
||||||
};
|
};
|
||||||
@@ -516,7 +536,14 @@ app.post('/api/edit-metadata', async (req, res) => {
|
|||||||
|
|
||||||
// If not absolute, try relative to music root
|
// If not absolute, try relative to music root
|
||||||
if (!path.isAbsolute(filePath)) filePath = path.join(CONFIG.musicPath, filePath);
|
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
|
// Resolve artwork: base64 > URL
|
||||||
let artFile = null;
|
let artFile = null;
|
||||||
|
|||||||
Reference in new issue
Block a user