feat: Spotify Importer — link → yt-dlp download + optional Navidrome playlist
- New 'Spotify Importer' page under Entdecken (sidebar + mobile nav) - Backend: POST /api/spotify/resolve — resolves track/album/playlist URLs via Spotify API - Backend: new 'playlist' download type accepting pre-resolved track list (no iTunes re-fetch) - Frontend: paste Spotify link → preview with cover, type badge, track list - Track: single download or full album via iTunes fallback - Album: download all tracks with Spotify metadata - Playlist: download all tracks + optional 'Als Navidrome-Playlist speichern' checkbox - Navidrome playlist creation: searches library by title/artist after download, creates playlist - Spotify Client ID + Secret stored in app settings (setup screen + settings modal) - iTunes metadata tags kept for all downloaded files (existing pipeline unchanged) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
9f68deea94
commit
f7a5247f17
6 files changed
+398
-18
No files matched your search
+58
@@ -46,6 +46,15 @@
|
||||
<input id="backend-url" type="url" placeholder="http://192.168.1.x:3700">
|
||||
<div class="hint">Für Download-to-Server Funktion. Backend separat starten (novasonic-server.js)</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label>Spotify Client ID <span style="color:var(--text3);font-weight:400;text-transform:none">(optional)</span></label>
|
||||
<input id="spotify-client-id" type="text" placeholder="Für Spotify Importer">
|
||||
<div class="hint">Kostenlos unter developer.spotify.com/dashboard</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label>Spotify Client Secret <span style="color:var(--text3);font-weight:400;text-transform:none">(optional)</span></label>
|
||||
<input id="spotify-client-secret" type="password" placeholder="••••••••••••••••">
|
||||
</div>
|
||||
</div>
|
||||
<button class="btn-primary" id="btn-connect" onclick="doConnect()">Verbinden</button>
|
||||
<div class="setup-error" id="setup-error"></div>
|
||||
@@ -111,6 +120,9 @@
|
||||
<div class="nav-item" onclick="navigate('random')" data-page="random">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="16 3 21 3 21 8"/><line x1="4" y1="20" x2="21" y2="3"/><polyline points="21 16 21 21 16 21"/><line x1="15" y1="15" x2="21" y2="21"/></svg>Zufällig
|
||||
</div>
|
||||
<div class="nav-item" onclick="navigate('spotify-importer')" data-page="spotify-importer">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><path d="M8 11.973c2.5-1.473 5.5-.973 7.5.527M9.5 14.473c1.5-.973 3.5-.973 5 .027M7 9c3-1.5 6.5-1 9 1"/></svg>Spotify Importer
|
||||
</div>
|
||||
</div>
|
||||
<div class="nav-section">
|
||||
<div class="nav-section-title">Player</div>
|
||||
@@ -320,6 +332,39 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- SPOTIFY IMPORTER -->
|
||||
<div class="page" id="page-spotify-importer">
|
||||
<div class="page-header">
|
||||
<div class="page-title">Spotify <em>Importer</em></div>
|
||||
<span style="background:rgba(29,185,84,.15);color:#1DB954;border:1px solid rgba(29,185,84,.3);font-size:11px;padding:4px 10px;border-radius:20px;font-weight:600;flex-shrink:0">Spotify</span>
|
||||
</div>
|
||||
<div class="search-wrap" style="padding:0 0 20px">
|
||||
<div style="display:flex;gap:8px">
|
||||
<div class="search-box" style="background:var(--surface);border-color:var(--border2);flex:1">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><path d="M8 11.973c2.5-1.473 5.5-.973 7.5.527M9.5 14.473c1.5-.973 3.5-.973 5 .027M7 9c3-1.5 6.5-1 9 1"/></svg>
|
||||
<input id="spotify-link-input" type="url" placeholder="Spotify Link einfügen (Track, Album oder Playlist)…" style="font-size:15px" oninput="clearSpotifyPreview()">
|
||||
</div>
|
||||
<button class="btn-primary" style="padding:0 18px;font-size:14px;white-space:nowrap;flex-shrink:0" onclick="resolveSpotifyLink()">Importieren</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="spotify-importer-hint" style="background:var(--surface);border:1px solid var(--border);border-radius:12px;padding:16px;font-size:13px;color:var(--text2);line-height:1.8">
|
||||
<div style="font-weight:700;color:var(--text);margin-bottom:8px">So funktioniert's</div>
|
||||
<div>1. Spotify Link für Track, Album oder Playlist einfügen</div>
|
||||
<div>2. Metadaten werden direkt von Spotify geladen</div>
|
||||
<div>3. Songs via yt-dlp herunterladen → direkt in Navidrome Library</div>
|
||||
<div style="margin-top:10px;color:var(--text3);font-size:12px">Spotify Client ID + Secret in den Einstellungen → Discover APIs eintragen.<br>Kostenlos unter <strong style="color:var(--text2)">developer.spotify.com/dashboard</strong></div>
|
||||
</div>
|
||||
<div id="spotify-preview" style="display:none;margin-top:20px">
|
||||
<div id="spotify-preview-inner"></div>
|
||||
<div id="spotify-tracks-section" style="display:none">
|
||||
<div class="section-header" style="margin-top:8px">
|
||||
<span class="section-title" id="spotify-tracks-title">Tracks</span>
|
||||
</div>
|
||||
<div id="spotify-tracks-list" class="song-list"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</main>
|
||||
</div>
|
||||
|
||||
@@ -473,6 +518,15 @@
|
||||
<input id="s-backend" type="url" placeholder="http://192.168.x.x:3700">
|
||||
<div class="hint">Für Download-to-Server via yt-dlp</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label>Spotify Client ID</label>
|
||||
<input id="s-spotify-id" type="text" placeholder="Für Spotify Importer">
|
||||
<div class="hint">Kostenlos unter developer.spotify.com/dashboard</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label>Spotify Client Secret</label>
|
||||
<input id="s-spotify-secret" type="password" placeholder="(unverändert lassen)">
|
||||
</div>
|
||||
<div class="settings-row" style="margin-top:8px;border-radius:9px">
|
||||
<div>
|
||||
<div style="font-size:13px;font-weight:500">Backend Status</div>
|
||||
@@ -708,6 +762,10 @@
|
||||
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="16 3 21 3 21 8"/><line x1="4" y1="20" x2="21" y2="3"/><polyline points="21 16 21 21 16 21"/><line x1="15" y1="15" x2="21" y2="21"/></svg>
|
||||
Zufällig
|
||||
</button>
|
||||
<button class="bnav-item" onclick="navigate('spotify-importer')" data-page="spotify-importer">
|
||||
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><path d="M8 11.973c2.5-1.473 5.5-.973 7.5.527M9.5 14.473c1.5-.973 3.5-.973 5 .027M7 9c3-1.5 6.5-1 9 1"/></svg>
|
||||
Importer
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
Reference in new issue
Block a user