Khaneja commited on
Commit ·
fbc4e93
1
Parent(s): f373b09
feat: intelligent filename construction using yt-dlp metadata (Artist, Track, Channel)
Browse files- app.py +34 -6
- templates/index.html +5 -0
app.py
CHANGED
|
@@ -60,11 +60,23 @@ def run_download(job_id, url, format_choice, format_id):
|
|
| 60 |
job["status"] = "done"
|
| 61 |
job["file"] = chosen
|
| 62 |
ext = os.path.splitext(chosen)[1]
|
| 63 |
-
|
| 64 |
-
|
| 65 |
-
|
| 66 |
-
|
| 67 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 68 |
else:
|
| 69 |
job["filename"] = os.path.basename(chosen)
|
| 70 |
except subprocess.TimeoutExpired:
|
|
@@ -131,11 +143,16 @@ def get_info():
|
|
| 131 |
})
|
| 132 |
audio_formats.sort(key=lambda x: x["abr"], reverse=True)
|
| 133 |
|
|
|
|
|
|
|
|
|
|
| 134 |
return jsonify({
|
| 135 |
"title": info.get("title", ""),
|
| 136 |
"thumbnail": info.get("thumbnail", ""),
|
| 137 |
"duration": info.get("duration"),
|
| 138 |
"uploader": info.get("uploader", ""),
|
|
|
|
|
|
|
| 139 |
"formats": formats,
|
| 140 |
"audioFormats": audio_formats,
|
| 141 |
})
|
|
@@ -152,12 +169,23 @@ def start_download():
|
|
| 152 |
format_choice = data.get("format", "video")
|
| 153 |
format_id = data.get("format_id")
|
| 154 |
title = data.get("title", "")
|
|
|
|
|
|
|
|
|
|
| 155 |
|
| 156 |
if not url:
|
| 157 |
return jsonify({"error": "No URL provided"}), 400
|
| 158 |
|
| 159 |
job_id = uuid.uuid4().hex[:10]
|
| 160 |
-
jobs[job_id] = {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 161 |
|
| 162 |
thread = threading.Thread(target=run_download, args=(job_id, url, format_choice, format_id))
|
| 163 |
thread.daemon = True
|
|
|
|
| 60 |
job["status"] = "done"
|
| 61 |
job["file"] = chosen
|
| 62 |
ext = os.path.splitext(chosen)[1]
|
| 63 |
+
|
| 64 |
+
is_audio = job.get("format_choice") == "audio"
|
| 65 |
+
artist = job.get("artist", "")
|
| 66 |
+
track = job.get("track", "")
|
| 67 |
+
uploader = job.get("uploader", "")
|
| 68 |
+
title = job.get("title", "")
|
| 69 |
+
|
| 70 |
+
if is_audio and artist and track:
|
| 71 |
+
raw_name = f"{artist} - {track}"
|
| 72 |
+
elif uploader and title:
|
| 73 |
+
raw_name = f"{uploader} - {title}"
|
| 74 |
+
else:
|
| 75 |
+
raw_name = title.strip()
|
| 76 |
+
|
| 77 |
+
if raw_name:
|
| 78 |
+
safe_name = "".join(c for c in raw_name if c not in r'\/:*?"<>|').strip()[:80].strip()
|
| 79 |
+
job["filename"] = f"{safe_name}{ext}" if safe_name else os.path.basename(chosen)
|
| 80 |
else:
|
| 81 |
job["filename"] = os.path.basename(chosen)
|
| 82 |
except subprocess.TimeoutExpired:
|
|
|
|
| 143 |
})
|
| 144 |
audio_formats.sort(key=lambda x: x["abr"], reverse=True)
|
| 145 |
|
| 146 |
+
art = info.get("artist")
|
| 147 |
+
artist_str = ", ".join(art) if isinstance(art, list) else str(art or "").strip()
|
| 148 |
+
|
| 149 |
return jsonify({
|
| 150 |
"title": info.get("title", ""),
|
| 151 |
"thumbnail": info.get("thumbnail", ""),
|
| 152 |
"duration": info.get("duration"),
|
| 153 |
"uploader": info.get("uploader", ""),
|
| 154 |
+
"artist": artist_str,
|
| 155 |
+
"track": str(info.get("track") or "").strip(),
|
| 156 |
"formats": formats,
|
| 157 |
"audioFormats": audio_formats,
|
| 158 |
})
|
|
|
|
| 169 |
format_choice = data.get("format", "video")
|
| 170 |
format_id = data.get("format_id")
|
| 171 |
title = data.get("title", "")
|
| 172 |
+
artist = data.get("artist", "")
|
| 173 |
+
track = data.get("track", "")
|
| 174 |
+
uploader = data.get("uploader", "")
|
| 175 |
|
| 176 |
if not url:
|
| 177 |
return jsonify({"error": "No URL provided"}), 400
|
| 178 |
|
| 179 |
job_id = uuid.uuid4().hex[:10]
|
| 180 |
+
jobs[job_id] = {
|
| 181 |
+
"status": "downloading",
|
| 182 |
+
"url": url,
|
| 183 |
+
"title": title,
|
| 184 |
+
"artist": artist,
|
| 185 |
+
"track": track,
|
| 186 |
+
"uploader": uploader,
|
| 187 |
+
"format_choice": format_choice
|
| 188 |
+
}
|
| 189 |
|
| 190 |
thread = threading.Thread(target=run_download, args=(job_id, url, format_choice, format_id))
|
| 191 |
thread.daemon = True
|
templates/index.html
CHANGED
|
@@ -595,6 +595,8 @@
|
|
| 595 |
thumbnail: data.thumbnail || '',
|
| 596 |
duration: data.duration,
|
| 597 |
uploader: data.uploader || '',
|
|
|
|
|
|
|
| 598 |
formats: data.formats || [],
|
| 599 |
selectedFormatId: data.formats?.[0]?.id || null,
|
| 600 |
audioFormats: data.audioFormats || [],
|
|
@@ -739,6 +741,9 @@
|
|
| 739 |
format: currentFormat,
|
| 740 |
format_id: payloadFormatId,
|
| 741 |
title: c.title || '',
|
|
|
|
|
|
|
|
|
|
| 742 |
}),
|
| 743 |
});
|
| 744 |
const data = await res.json();
|
|
|
|
| 595 |
thumbnail: data.thumbnail || '',
|
| 596 |
duration: data.duration,
|
| 597 |
uploader: data.uploader || '',
|
| 598 |
+
artist: data.artist || '',
|
| 599 |
+
track: data.track || '',
|
| 600 |
formats: data.formats || [],
|
| 601 |
selectedFormatId: data.formats?.[0]?.id || null,
|
| 602 |
audioFormats: data.audioFormats || [],
|
|
|
|
| 741 |
format: currentFormat,
|
| 742 |
format_id: payloadFormatId,
|
| 743 |
title: c.title || '',
|
| 744 |
+
artist: c.artist || '',
|
| 745 |
+
track: c.track || '',
|
| 746 |
+
uploader: c.uploader || ''
|
| 747 |
}),
|
| 748 |
});
|
| 749 |
const data = await res.json();
|