fix: SC metadata fields, albumartist & separator, importer clear, folder rename on album edit
- SC tracks: use artworkUrl/album/genre fields (not iTunes artworkUrl100/collectionName/primaryGenreName) - Playlist handler: same SC field fallbacks for artwork, album, genre, year - ytdlp.js: convert & to , in album_artist tag so Navidrome albumartist.Split works - Importer: clear both previews on any URL input change, not just on clear - edit-metadata: rename album folder on disk when album name changes Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
62fefbb5e7
commit
d785a4c09a
3 files changed
+28
-16
No files matched your search
@@ -312,7 +312,7 @@ async function embedMetadata({ jobId, audioFile, dir, trackPrefix, safeTitle, ar
|
||||
'-id3v2_version', '3',
|
||||
'-metadata', `title=${title}`,
|
||||
'-metadata', `artist=${navidromeArtist(artist)}`,
|
||||
'-metadata', `album_artist=${mainArtist}`,
|
||||
'-metadata', `album_artist=${mainArtist.replace(/\s+&\s+/g, ', ')}`,
|
||||
);
|
||||
if (album) ffArgs.push('-metadata', `album=${album}`);
|
||||
if (year) ffArgs.push('-metadata', `date=${String(year)}`);
|
||||
|
||||
@@ -17,7 +17,7 @@ const crypto = require('crypto');
|
||||
|
||||
const CONFIG = require('./lib/config');
|
||||
const { jobs, updateJob, log } = require('./lib/jobs');
|
||||
const { lookupItunesTrackMeta, fetchItunesTracks, searchItunesAlbumTracks } = require('./lib/metadata');
|
||||
const { sanitize, lookupItunesTrackMeta, fetchItunesTracks, searchItunesAlbumTracks } = require('./lib/metadata');
|
||||
const { downloadTrack, downloadAlbumTracks } = require('./lib/downloader');
|
||||
const { buildRomajiIndex, clearRomajiCache, isTokenizerReady, fetchNdSongs } = require('./lib/romaji');
|
||||
|
||||
@@ -243,15 +243,16 @@ app.post('/api/download', async (req, res) => {
|
||||
try {
|
||||
if (type === 'track') {
|
||||
const sp = req.body.tracks?.[0] || {};
|
||||
const spAlbum = sp.collectionName || album || '';
|
||||
const spArt = sp.artworkUrl100 || artworkUrl || '';
|
||||
const spYear = sp.releaseDate ? new Date(sp.releaseDate).getFullYear() : undefined;
|
||||
const spAlbum = sp.collectionName || sp.album || album || '';
|
||||
const spArt = sp.artworkUrl100 || sp.artworkUrl || artworkUrl || '';
|
||||
const spYear = sp.releaseDate ? new Date(sp.releaseDate).getFullYear() : (sp.year || undefined);
|
||||
let meta = {
|
||||
album: spAlbum, year: spYear,
|
||||
trackNum: sp.trackNumber || bodyTrackNum || undefined,
|
||||
totalTracks: sp.trackCount || bodyTotalTracks || undefined,
|
||||
discNum: sp.discNumber || bodyDiscNum || undefined,
|
||||
discTotal: sp.discCount || bodyDiscTotal || undefined,
|
||||
genre: sp.primaryGenreName || sp.genre || undefined,
|
||||
artworkUrl: spArt, explicit: sp.trackExplicitness === 'explicit' || !!explicit,
|
||||
durationMs: sp.durationMs || undefined,
|
||||
};
|
||||
@@ -260,7 +261,7 @@ app.post('/api/download', async (req, res) => {
|
||||
log(jobId, '📋 Suche Album-Metadaten von iTunes…');
|
||||
const extra = await lookupItunesTrackMeta(searchArtist, title);
|
||||
if (extra.album) log(jobId, `📋 Album: "${extra.album}" (${extra.year || '?'})`);
|
||||
meta = { ...meta, ...extra, artworkUrl: spArt || extra.artworkUrl || '' };
|
||||
meta = { ...meta, ...extra, artworkUrl: spArt || extra.artworkUrl || '', genre: meta.genre || extra.genre || undefined };
|
||||
} else {
|
||||
log(jobId, `📋 Album aus Spotify: "${meta.album}"`);
|
||||
}
|
||||
@@ -343,12 +344,12 @@ app.post('/api/download', async (req, res) => {
|
||||
artist: trackArtist,
|
||||
albumArtist: trackArtist,
|
||||
title: trackTitle,
|
||||
album: itunes.album || track.collectionName || '',
|
||||
year: itunes.year || (track.releaseDate ? new Date(track.releaseDate).getFullYear() : undefined),
|
||||
album: itunes.album || track.collectionName || track.album || '',
|
||||
year: itunes.year || (track.releaseDate ? new Date(track.releaseDate).getFullYear() : undefined) || track.year,
|
||||
trackNum: itunes.trackNum || track.trackNumber || undefined,
|
||||
totalTracks: itunes.totalTracks || undefined,
|
||||
genre: itunes.genre || track.primaryGenreName || undefined,
|
||||
artworkUrl: itunes.artworkUrl || track.artworkUrl100 || artworkUrl || '',
|
||||
genre: itunes.genre || track.primaryGenreName || track.genre || undefined,
|
||||
artworkUrl: itunes.artworkUrl || track.artworkUrl100 || track.artworkUrl || artworkUrl || '',
|
||||
explicit: track.trackExplicitness === 'explicit',
|
||||
durationMs: itunes.durationMs || track.durationMs || undefined,
|
||||
sourceUrl: track.sourceUrl || undefined,
|
||||
@@ -578,6 +579,18 @@ app.post('/api/edit-metadata', async (req, res) => {
|
||||
fs.renameSync(tmpFile, filePath);
|
||||
if (artFile) try { fs.unlinkSync(artFile); } catch {}
|
||||
|
||||
// Rename album folder if album changed and folder name matches old album dir
|
||||
if (album) {
|
||||
const dir = path.dirname(filePath);
|
||||
const newDirName = sanitize(album);
|
||||
if (path.basename(dir) !== newDirName) {
|
||||
const newDir = path.join(path.dirname(dir), newDirName);
|
||||
if (!fs.existsSync(newDir)) {
|
||||
try { fs.renameSync(dir, newDir); } catch (e) { console.error('[edit-metadata] folder rename:', e.message); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Trigger Navidrome rescan
|
||||
try {
|
||||
const salt2 = Math.random().toString(36).slice(2, 10);
|
||||
|
||||
+5
-6
@@ -7,6 +7,11 @@ import { openDlModal } from './ui.js';
|
||||
|
||||
// ─── UNIFIED IMPORTER INPUT ───
|
||||
export function onImporterInput(val) {
|
||||
// Always clear results when URL changes
|
||||
document.getElementById('spotify-preview').style.display = 'none';
|
||||
document.getElementById('sc-preview').style.display = 'none';
|
||||
document.getElementById('importer-hint').style.display = val ? 'none' : '';
|
||||
|
||||
const badge = document.getElementById('importer-badge');
|
||||
const btn = document.getElementById('importer-btn');
|
||||
if (!badge || !btn) return;
|
||||
@@ -32,12 +37,6 @@ export function onImporterInput(val) {
|
||||
btn.style.color = '';
|
||||
btn.style.borderColor = '';
|
||||
}
|
||||
// Hide results when input is cleared
|
||||
if (!val) {
|
||||
document.getElementById('spotify-preview').style.display = 'none';
|
||||
document.getElementById('sc-preview').style.display = 'none';
|
||||
document.getElementById('importer-hint').style.display = '';
|
||||
}
|
||||
}
|
||||
|
||||
export async function resolveImporterLink() {
|
||||
|
||||
Reference in new issue
Block a user