diff --git a/backend/novasonic-server.js b/backend/novasonic-server.js index cfe2b5c..6ab4181 100644 --- a/backend/novasonic-server.js +++ b/backend/novasonic-server.js @@ -612,6 +612,43 @@ app.get('/api/musicbrainz/lookup', async (req, res) => { } }); +// ─── SORT TAGS READ ────────────────────────────────────────────────────────── +app.get('/api/song-sorttags', async (req, res) => { + const { ndUrl, user, pass, songId } = req.query; + if (!ndUrl || !user || !pass || !songId) return res.status(400).json({ error: 'ndUrl, user, pass, songId required' }); + let filePath; + try { + const salt = Math.random().toString(36).slice(2, 10); + const token = crypto.createHash('md5').update(pass + salt).digest('hex'); + const ndRes = await fetch(`${ndUrl}/rest/getSong?id=${songId}&u=${encodeURIComponent(user)}&t=${token}&s=${salt}&v=1.16.1&c=novasonic&f=json`, { signal: AbortSignal.timeout(8000) }); + const nd = await ndRes.json(); + filePath = nd?.['subsonic-response']?.song?.path; + if (!filePath) return res.status(404).json({ error: 'Song not found' }); + } catch (e) { return res.status(502).json({ error: e.message }); } + if (!path.isAbsolute(filePath)) filePath = path.join(CONFIG.musicPath, filePath); + if (!fs.existsSync(filePath)) { + const found = _findFileRecursive(CONFIG.musicPath, path.basename(filePath)); + if (found) filePath = found; else return res.status(404).json({ error: 'File not found' }); + } + try { + const out = await new Promise((resolve, reject) => { + const proc = spawn('ffprobe', ['-v', 'quiet', '-print_format', 'json', '-show_entries', 'format_tags', filePath]); + let buf = ''; + proc.stdout.on('data', d => buf += d); + proc.on('error', reject); + proc.on('close', () => { try { resolve(JSON.parse(buf)); } catch { resolve({}); } }); + }); + const tags = out?.format?.tags || {}; + const findTag = (...keys) => { for (const k of keys) { const v = tags[k] || tags[k.toLowerCase()] || tags[k.toUpperCase()]; if (v) return v; } return ''; }; + res.json({ + titleSort: findTag('TITLESORT', 'titlesort'), + artistSort: findTag('ARTISTSORT', 'artistsort'), + albumArtistSort: findTag('ALBUMARTISTSORT', 'albumartistsort', 'TSO2'), + albumSort: findTag('ALBUMSORT', 'albumsort'), + }); + } catch (e) { res.status(500).json({ error: e.message }); } +}); + // ─── METADATA EDIT ─────────────────────────────────────────────────────────── app.post('/api/edit-metadata', async (req, res) => { const { ndUrl, user, pass, songId, title, artist, albumArtist, album, year, trackNum, totalTracks, diff --git a/index.html b/index.html index bb9b4bc..e5997cb 100644 --- a/index.html +++ b/index.html @@ -654,12 +654,10 @@ Abspielhäufigkeit anzeigen
-