YouTube playlist support: /api/youtube/playlist-preview za pred-confirm, /api/youtube zaznava 'list=' URL in kreira batch (1 job/video). Qnet auto-match na YT naslovu, Confirm dialog v UI z prvih 5 naslovov.
This commit is contained in:
@@ -74,6 +74,69 @@ def get_info(url, cookies_file=None):
|
||||
return json.loads(result.stdout.strip().split("\n")[0])
|
||||
|
||||
|
||||
def get_playlist(url, cookies_file=None):
|
||||
"""Vrni listo videov v playlistu (samo metadata, ne pobere).
|
||||
|
||||
Returns:
|
||||
{
|
||||
"is_playlist": bool,
|
||||
"playlist_title": str,
|
||||
"items": [
|
||||
{"id": "VIDEO_ID", "title": "...", "url": "https://...", "duration": 234},
|
||||
...
|
||||
]
|
||||
}
|
||||
|
||||
Če URL ni playlist, vrne is_playlist=False in samo en item.
|
||||
"""
|
||||
cmd = ["yt-dlp", "--flat-playlist", "--dump-json"]
|
||||
if cookies_file is None:
|
||||
for candidate in ["/data/cookies/youtube.txt", os.environ.get("YT_COOKIES_FILE", "")]:
|
||||
if candidate and Path(candidate).exists():
|
||||
cookies_file = candidate
|
||||
break
|
||||
if cookies_file and Path(cookies_file).exists():
|
||||
cmd += ["--cookies", str(cookies_file)]
|
||||
cmd.append(url)
|
||||
print(f"📋 Resolving playlist: {url}", file=sys.stderr)
|
||||
result = subprocess.run(cmd, capture_output=True, text=True, timeout=120)
|
||||
if result.returncode != 0:
|
||||
print(f"❌ yt-dlp playlist napaka:\n{result.stderr[-1500:]}", file=sys.stderr)
|
||||
return {"is_playlist": False, "playlist_title": "", "items": [], "error": result.stderr[-500:]}
|
||||
|
||||
items = []
|
||||
playlist_title = ""
|
||||
for line in result.stdout.strip().split("\n"):
|
||||
if not line.strip():
|
||||
continue
|
||||
try:
|
||||
entry = json.loads(line)
|
||||
except json.JSONDecodeError:
|
||||
continue
|
||||
# Playlist header (typ=playlist)
|
||||
if entry.get("_type") == "playlist":
|
||||
playlist_title = entry.get("title", "")
|
||||
continue
|
||||
# Video entry
|
||||
vid = entry.get("id")
|
||||
if not vid:
|
||||
continue
|
||||
items.append({
|
||||
"id": vid,
|
||||
"title": entry.get("title", "") or "",
|
||||
"url": entry.get("url") or f"https://www.youtube.com/watch?v={vid}",
|
||||
"duration": entry.get("duration"),
|
||||
"uploader": entry.get("uploader") or entry.get("channel") or "",
|
||||
})
|
||||
|
||||
is_playlist = len(items) > 1 or ("list=" in url)
|
||||
return {
|
||||
"is_playlist": is_playlist,
|
||||
"playlist_title": playlist_title or (items[0]["title"] if items else ""),
|
||||
"items": items,
|
||||
}
|
||||
|
||||
|
||||
def main():
|
||||
ap = argparse.ArgumentParser()
|
||||
ap.add_argument("url")
|
||||
|
||||
Reference in New Issue
Block a user