Added support for pausing adding items from playlist.
This commit is contained in:
parent
32bebcaf46
commit
19b9f8dc6c
6 changed files with 39 additions and 18 deletions
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
|
|
@ -80,6 +80,9 @@
|
||||||
"onefile",
|
"onefile",
|
||||||
"pathex",
|
"pathex",
|
||||||
"platformdirs",
|
"platformdirs",
|
||||||
|
"playlistend",
|
||||||
|
"playlistrandom",
|
||||||
|
"playlistreverse",
|
||||||
"plexmatch",
|
"plexmatch",
|
||||||
"postprocessor",
|
"postprocessor",
|
||||||
"preferredcodec",
|
"preferredcodec",
|
||||||
|
|
|
||||||
|
|
@ -305,7 +305,7 @@ class DownloadQueue(metaclass=Singleton):
|
||||||
|
|
||||||
entries = entry.get("entries", [])
|
entries = entry.get("entries", [])
|
||||||
|
|
||||||
LOG.info(f"Processing '{entry.get('id')}: {entry.get('title')}' Playlist.")
|
LOG.info(f"Processing '{entry.get('id')}: {entry.get('title')} ({len(entries)})' Playlist.")
|
||||||
|
|
||||||
playlistCount = int(entry.get("playlist_count", len(entries)))
|
playlistCount = int(entry.get("playlist_count", len(entries)))
|
||||||
results = []
|
results = []
|
||||||
|
|
@ -325,11 +325,19 @@ class DownloadQueue(metaclass=Singleton):
|
||||||
}
|
}
|
||||||
|
|
||||||
async def playlist_processor(i: int, etr: dict):
|
async def playlist_processor(i: int, etr: dict):
|
||||||
await self.processors.acquire()
|
|
||||||
try:
|
try:
|
||||||
LOG.info(
|
item_name = (
|
||||||
f"Processing '{entry.get('title')}: {i}/{playlistCount}' - ID: {etr.get('id')} - Title: {etr.get('title')}"
|
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}")
|
||||||
|
await self.processors.acquire()
|
||||||
|
LOG.debug(f"Acquired lock for {item_name}")
|
||||||
|
|
||||||
|
if self.is_paused():
|
||||||
|
LOG.warning(f"Download is paused. Skipping processing of '{item_name}'.")
|
||||||
|
return {"status": "ok"}
|
||||||
|
|
||||||
|
LOG.info(f"Processing '{item_name}'.")
|
||||||
|
|
||||||
_status, _msg = ytdlp_reject(entry=etr, yt_params=yt_params)
|
_status, _msg = ytdlp_reject(entry=etr, yt_params=yt_params)
|
||||||
if not _status:
|
if not _status:
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,7 @@ REMOVE_KEYS: list = [
|
||||||
"opt_list_format": "-F, --list-formats",
|
"opt_list_format": "-F, --list-formats",
|
||||||
"opt_dump_agent": "--dump-user-agent",
|
"opt_dump_agent": "--dump-user-agent",
|
||||||
"opt_extractor_descriptions": "--extractor-descriptions",
|
"opt_extractor_descriptions": "--extractor-descriptions",
|
||||||
"opt_list_impersonate_targets": "--list-impersonate-targets"
|
"opt_list_impersonate_targets": "--list-impersonate-targets",
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
@ -459,6 +459,7 @@ def arg_converter(
|
||||||
level: int | bool | None = None,
|
level: int | bool | None = None,
|
||||||
dumps: bool = False,
|
dumps: bool = False,
|
||||||
removed_options: list | None = None,
|
removed_options: list | None = None,
|
||||||
|
keep_defaults: bool = False,
|
||||||
) -> dict:
|
) -> dict:
|
||||||
"""
|
"""
|
||||||
Convert yt-dlp options to a dictionary.
|
Convert yt-dlp options to a dictionary.
|
||||||
|
|
@ -468,6 +469,7 @@ def arg_converter(
|
||||||
level (int|bool|None): Level of options to remove, True for all.
|
level (int|bool|None): Level of options to remove, True for all.
|
||||||
dumps (bool): Dump options as JSON.
|
dumps (bool): Dump options as JSON.
|
||||||
removed_options (list|None): List of removed options.
|
removed_options (list|None): List of removed options.
|
||||||
|
keep_defaults (bool): Keep default options.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
dict: yt-dlp options dictionary.
|
dict: yt-dlp options dictionary.
|
||||||
|
|
@ -488,8 +490,7 @@ def arg_converter(
|
||||||
default_opts = _default_opts([]).ydl_opts
|
default_opts = _default_opts([]).ydl_opts
|
||||||
|
|
||||||
opts = yt_dlp.parse_options(shlex.split(args)).ydl_opts
|
opts = yt_dlp.parse_options(shlex.split(args)).ydl_opts
|
||||||
|
diff = {k: v for k, v in opts.items() if default_opts[k] != v} if not keep_defaults else opts.items()
|
||||||
diff = {k: v for k, v in opts.items() if default_opts[k] != v}
|
|
||||||
if "postprocessors" in diff:
|
if "postprocessors" in diff:
|
||||||
diff["postprocessors"] = [pp for pp in diff["postprocessors"] if pp not in default_opts["postprocessors"]]
|
diff["postprocessors"] = [pp for pp in diff["postprocessors"] if pp not in default_opts["postprocessors"]]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,3 @@
|
||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
import yt_dlp
|
import yt_dlp
|
||||||
|
|
@ -47,13 +45,16 @@ def ytdlp_options() -> list[dict[str, Any]]:
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
for opt in opts
|
for opt in opts
|
||||||
if (
|
if (getattr(opt, "_long_opts", []) and getattr(opt, "help", None))
|
||||||
(getattr(opt, "_short_opts", []) or getattr(opt, "_long_opts", []))
|
|
||||||
and getattr(opt, "help", None)
|
|
||||||
and "SUPPRESSHELP" not in getattr(opt, "help", "")
|
|
||||||
)
|
|
||||||
]
|
]
|
||||||
|
|
||||||
return collect(parser.option_list, "root") + [
|
opts = collect(parser.option_list, "root") + [
|
||||||
entry for grp in parser.option_groups for entry in collect(grp.option_list, grp.title or "other")
|
entry for grp in parser.option_groups for entry in collect(grp.option_list, grp.title or "other")
|
||||||
]
|
]
|
||||||
|
|
||||||
|
for opt in opts:
|
||||||
|
if "SUPPRESSHELP" in opt.get("description", ""):
|
||||||
|
opt["description"] = "No description available from yt-dlp."
|
||||||
|
|
||||||
|
return opts
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -523,6 +523,7 @@ const cancelSelected = () => {
|
||||||
}
|
}
|
||||||
cancelItems(selectedElms.value)
|
cancelItems(selectedElms.value)
|
||||||
selectedElms.value = []
|
selectedElms.value = []
|
||||||
|
masterSelectAll.value = false
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -141,10 +141,17 @@ watch(() => stateStore.queue, () => {
|
||||||
|
|
||||||
const pauseDownload = () => {
|
const pauseDownload = () => {
|
||||||
dialog_confirm.value.visible = true
|
dialog_confirm.value.visible = true
|
||||||
dialog_confirm.value.html_message = `<span class="is-bold">Pause All non-active downloads?</span><br>
|
dialog_confirm.value.html_message = `
|
||||||
<span class="has-text-danger">
|
<span class="icon-text">
|
||||||
<span class="icon"><i class="fa-solid fa-exclamation-triangle"></i></span>
|
<span class="icon"><i class="fa-solid fa-exclamation-triangle"></i></span>
|
||||||
<span>This will not stop downloads that are currently in progress.</span>
|
<span class="is-bold">Pause All non-active downloads?</span>
|
||||||
|
</span>
|
||||||
|
<br>
|
||||||
|
<span class="has-text-danger">
|
||||||
|
<ul>
|
||||||
|
<li>This will not stop downloads that are currently in progress.</li>
|
||||||
|
<li>If you are in middle of adding a playlist/channel, it will break and stop adding more items.</li>
|
||||||
|
</ul>
|
||||||
</span>`
|
</span>`
|
||||||
dialog_confirm.value.confirm = () => {
|
dialog_confirm.value.confirm = () => {
|
||||||
socket.emit('pause', {})
|
socket.emit('pause', {})
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue