feat: load actual file sort tags in edit modal + remove settings hints
- backend: new GET /api/song-sorttags reads TITLESORT/ARTISTSORT/ALBUMARTISTSORT/ ALBUMSORT directly from the file via ffprobe - ui.js: pre-fill sort fields from romaji index, then overwrite with real file tags from the backend (shows actual values even if manually set) - index.html: remove redundant hint texts in settings Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
5dda1a7101
commit
255ea1969c
3 files changed
+48
-3
No files matched your search
@@ -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,
|
||||
|
||||
Reference in new issue
Block a user