diff --git a/core/config.py b/core/config.py
index 92cf644..cc8c07b 100644
--- a/core/config.py
+++ b/core/config.py
@@ -5,7 +5,7 @@ import os
import sys
from pathlib import Path
-VERSION = "v1.5.1"
+VERSION = "v1.5.2"
APP_NAME = "MusicTools"
diff --git a/core/downloader.py b/core/downloader.py
index 2376e4e..e28151f 100644
--- a/core/downloader.py
+++ b/core/downloader.py
@@ -146,8 +146,10 @@ def download_playlist(
progress_callback(i, total, "", "stopped", 0)
return
- query = f"{track['name']} - {track['artist']}"
- track_only = track['name']
+ artist = (track.get('artist') or "").strip()
+ name = (track.get('name') or "").strip()
+ query = f"{name} - {artist}" if artist else name
+ track_only = name
# Salta brani gia scaricati in precedenza (file di tracking)
if query in done_set:
diff --git a/webui/index.html b/webui/index.html
index 6ce2cb8..a1cfc62 100644
--- a/webui/index.html
+++ b/webui/index.html
@@ -75,15 +75,22 @@
-
+
+
+ ⓘ
+
+ Puoi incollare un link (Spotify, YouTube, SoundCloud…) oppure scrivere direttamente
+ Artista - Titolo o solo il titolo del brano: l'app cerca il match migliore su YouTube e scarica in MP3.
+
+
diff --git a/webui/js/app.js b/webui/js/app.js
index d4b6cc1..17d7cf4 100644
--- a/webui/js/app.js
+++ b/webui/js/app.js
@@ -27,6 +27,24 @@ function waitApi() {
});
}
+// Riconosce se una stringa e un URL (incluso schema spotify:)
+function looksLikeUrl(s) {
+ if (!s) return false;
+ if (/^(https?|spotify):/i.test(s)) return true;
+ if (s.includes("://")) return true;
+ // Domini comuni anche senza http (es. "youtube.com/...")
+ return /^(www\.)?(youtube\.com|youtu\.be|spotify\.com|soundcloud\.com|tiktok\.com|instagram\.com|facebook\.com|fb\.watch)\//i.test(s);
+}
+
+// Trasforma una query libera in {name, artist}.
+// Formati riconosciuti: "Artista - Titolo" (anche con – o —) oppure solo "Titolo".
+function parseQueryToTrack(q) {
+ const s = (q || "").trim();
+ const m = s.match(/^(.+?)\s+[-–—]\s+(.+)$/);
+ if (m) return { artist: m[1].trim(), name: m[2].trim() };
+ return { artist: "", name: s };
+}
+
// ============================================================
// Bridge — eventi spinti dal backend
// ============================================================
@@ -340,11 +358,25 @@ $("#downloadBtn").addEventListener("click", async () => {
if (!urls.length) {
const single = $("#urlInput").value.trim();
if (!single) {
- toast("Inserisci un URL o carica una lista", "error");
+ toast("Inserisci un URL, un titolo o carica una lista", "error");
bridgeHandlers["download:done"]();
return;
}
- urls = [single];
+ if (looksLikeUrl(single)) {
+ urls = [single];
+ } else {
+ const track = parseQueryToTrack(single);
+ res = await window.pywebview.api.start_tracks_download({
+ tracks: [track],
+ output_dir: state.dlOutputDir,
+ subfolder: "",
+ });
+ if (!res.ok) {
+ toast(res.error || "Errore", "error");
+ bridgeHandlers["download:done"]();
+ }
+ return;
+ }
}
res = await window.pywebview.api.start_download({
urls,