Merge pull request #480 from arabcoders/dev

[FIX] implement --max-downloads arg. Ref #479
This commit is contained in:
Abdulmohsen 2025-11-10 00:35:48 +03:00 committed by GitHub
commit f0b5e20af8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 761 additions and 839 deletions

View file

@ -203,10 +203,7 @@
},
"eslint.format.enable": true,
"eslint.ignoreUntitled": true,
"python.testing.pytestArgs": [
"app/tests"
],
"python.testing.unittestEnabled": true,
"python.testing.unittestEnabled": false,
"python.testing.pytestEnabled": true,
"json.schemas": [
{
@ -245,5 +242,6 @@
],
"url": "./app/schema/tasks.json"
}
]
],
"python.testing.cwd": "app/tests"
}

View file

@ -10,7 +10,7 @@ from datetime import UTC, datetime, timedelta
from email.utils import formatdate
from pathlib import Path
from sqlite3 import Connection
from typing import TYPE_CHECKING
from typing import TYPE_CHECKING, Any
import yt_dlp.utils
from aiohttp import web
@ -305,14 +305,16 @@ class DownloadQueue(metaclass=Singleton):
entries = entry.get("entries", [])
LOG.info(f"Processing '{entry.get('id')}: {entry.get('title')} ({len(entries)})' Playlist.")
playlist_name: str = f"{entry.get('id')}: {entry.get('title')}"
LOG.info(f"Processing '{playlist_name} ({len(entries)})' Playlist.")
playlistCount = entry.get("playlist_count")
playlistCount = int(playlistCount) if playlistCount else len(entries)
playlistCount: int = int(playlistCount) if playlistCount else len(entries)
results = []
playlist_keys = {
playlist_keys: dict[str, Any] = {
"playlist_count": playlistCount,
"playlist": entry.get("title") or entry.get("id"),
"playlist_id": entry.get("id"),
@ -328,7 +330,7 @@ class DownloadQueue(metaclass=Singleton):
async def playlist_processor(i: int, etr: dict):
try:
item_name = (
item_name: str = (
f"'{entry.get('title')}: {i}/{playlist_keys['n_entries']}' - '{etr.get('id')}: {etr.get('title')}'"
)
LOG.debug(f"Waiting to acquire lock for {item_name}")
@ -345,7 +347,7 @@ class DownloadQueue(metaclass=Singleton):
if not _status:
return {"status": "error", "msg": _msg}
extras = {
extras: dict[str, Any] = {
**playlist_keys,
"playlist_index": i,
"playlist_index_number": i,
@ -359,7 +361,7 @@ class DownloadQueue(metaclass=Singleton):
if "thumbnail" not in etr and "youtube:" in entry.get("extractor", ""):
extras["thumbnail"] = f"https://img.youtube.com/vi/{etr['id']}/maxresdefault.jpg"
newItem = item.new_with(url=etr.get("url") or etr.get("webpage_url"), extras=extras)
newItem: Item = item.new_with(url=etr.get("url") or etr.get("webpage_url"), extras=extras)
if "formats" in etr and isinstance(etr["formats"], list) and len(etr["formats"]) > 0:
LOG.warning(f"Unexpected formats entries in --flat-playlist for {item_name}, treating as video.")
@ -371,8 +373,16 @@ class DownloadQueue(metaclass=Singleton):
finally:
self.processors.release()
max_downloads: int = -1
ytdlp_opts: dict[str, Any] = item.get_ytdlp_opts().get_all()
if ytdlp_opts.get("max_downloads") and isinstance(ytdlp_opts.get("max_downloads"), int):
max_downloads: int = ytdlp_opts.get("max_downloads")
tasks: list[asyncio.Task] = []
for i, etr in enumerate(entries, start=1):
if max_downloads > 0 and i > max_downloads:
break
task = asyncio.create_task(
playlist_processor(i, etr),
name=f"playlist_processor_{etr.get('id')}_{i}",
@ -382,9 +392,12 @@ class DownloadQueue(metaclass=Singleton):
results: list[dict] = await asyncio.gather(*tasks)
LOG.info(
f"Playlist '{entry.get('id')}: {entry.get('title')}' processing completed with '{len(results)}' entries."
)
log_msg: str = f"Playlist '{playlist_name}' processing completed with '{len(results)}' entries."
if max_downloads > 0 and len(entries) > max_downloads:
skipped: int = len(entries) - max_downloads
log_msg += f" Limited to '{max_downloads}' items, skipped '{skipped}' remaining items."
LOG.info(log_msg)
if any("error" == res["status"] for res in results):
return {

View file

@ -18,7 +18,7 @@
},
"web-types": "./web-types.json",
"dependencies": {
"@pinia/nuxt": "^0.11.2",
"@pinia/nuxt": "^0.11.3",
"@vueuse/core": "^14.0.0",
"@vueuse/nuxt": "^14.0.0",
"@xterm/addon-fit": "^0.10.0",
@ -26,16 +26,16 @@
"cron-parser": "^5.4.0",
"cronstrue": "^3.9.0",
"floating-vue": "^5.2.2",
"hls.js": "^1.6.13",
"hls.js": "^1.6.14",
"marked": "^16.4.1",
"marked-alert": "^2.1.2",
"marked-base-url": "^1.1.7",
"marked-gfm-heading-id": "^4.1.2",
"moment": "^2.30.1",
"nuxt": "^4.2.0",
"pinia": "^3.0.3",
"pinia": "^3.0.4",
"socket.io-client": "^4.8.1",
"vue": "^3.5.22",
"vue": "^3.5.23",
"vue-router": "^4.6.3",
"vue-toastification": "2.0.0-rc.5"
},
@ -54,11 +54,11 @@
"devDependencies": {
"@nuxt/eslint": "^1.10.0",
"@nuxt/eslint-config": "^1.10.0",
"@typescript-eslint/parser": "^8.46.2",
"eslint": "^9.38.0",
"@typescript-eslint/parser": "^8.46.3",
"eslint": "^9.39.1",
"typescript": "^5.9.3",
"vitest": "^4.0.5",
"vitest": "^4.0.7",
"vue-eslint-parser": "^10.2.0",
"vue-tsc": "^3.1.2"
"vue-tsc": "^3.1.3"
}
}

File diff suppressed because it is too large Load diff