Merge pull request #346 from arabcoders/dev
Remove duplicate notifications, and improve yt-dlp opts handling
This commit is contained in:
commit
b7cb89f656
7 changed files with 23 additions and 70 deletions
|
|
@ -16,7 +16,7 @@ LOG = logging.getLogger("datastore")
|
||||||
|
|
||||||
|
|
||||||
class StoreType(str, Enum):
|
class StoreType(str, Enum):
|
||||||
DONE = "done"
|
HISTORY = "done"
|
||||||
QUEUE = "queue"
|
QUEUE = "queue"
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,7 @@ class DownloadQueue(metaclass=Singleton):
|
||||||
|
|
||||||
self.config = config or Config.get_instance()
|
self.config = config or Config.get_instance()
|
||||||
self._notify = EventBus.get_instance()
|
self._notify = EventBus.get_instance()
|
||||||
self.done = DataStore(type=StoreType.DONE, connection=connection)
|
self.done = DataStore(type=StoreType.HISTORY, connection=connection)
|
||||||
self.queue = DataStore(type=StoreType.QUEUE, connection=connection)
|
self.queue = DataStore(type=StoreType.QUEUE, connection=connection)
|
||||||
self.done.load()
|
self.done.load()
|
||||||
self.queue.load()
|
self.queue.load()
|
||||||
|
|
@ -981,13 +981,13 @@ class DownloadQueue(metaclass=Singleton):
|
||||||
|
|
||||||
if entry.is_cancelled() is True:
|
if entry.is_cancelled() is True:
|
||||||
nTitle = "Download Cancelled"
|
nTitle = "Download Cancelled"
|
||||||
nMessage = f"Download '{entry.info.title}' has been cancelled."
|
nMessage = f"Cancelled '{entry.info.title}' download."
|
||||||
await self._notify.emit(Events.ITEM_CANCELLED, data=entry.info, title=nTitle, message=nMessage)
|
await self._notify.emit(Events.ITEM_CANCELLED, data=entry.info, title=nTitle, message=nMessage)
|
||||||
entry.info.status = "cancelled"
|
entry.info.status = "cancelled"
|
||||||
|
|
||||||
if entry.info.status == "finished" and entry.info.filename:
|
if entry.info.status == "finished" and entry.info.filename:
|
||||||
nTitle = "Download Completed"
|
nTitle = "Download Completed"
|
||||||
nMessage = f"Download '{entry.info.title}' has been finished."
|
nMessage = f"Completed '{entry.info.title}' download."
|
||||||
_tasks.append(self._notify.emit(Events.ITEM_COMPLETED, data=entry.info, title=nTitle, message=nMessage))
|
_tasks.append(self._notify.emit(Events.ITEM_COMPLETED, data=entry.info, title=nTitle, message=nMessage))
|
||||||
|
|
||||||
self.done.put(value=entry)
|
self.done.put(value=entry)
|
||||||
|
|
|
||||||
|
|
@ -161,7 +161,6 @@ class Item:
|
||||||
data["template"] = item.get("template")
|
data["template"] = item.get("template")
|
||||||
|
|
||||||
if "auto_start" in item and isinstance(item.get("auto_start"), bool):
|
if "auto_start" in item and isinstance(item.get("auto_start"), bool):
|
||||||
LOG.info("Item '%s' auto_start is set to %s.", url, item.get("auto_start"))
|
|
||||||
data["auto_start"] = bool(item.get("auto_start"))
|
data["auto_start"] = bool(item.get("auto_start"))
|
||||||
|
|
||||||
extras = item.get("extras")
|
extras = item.get("extras")
|
||||||
|
|
|
||||||
|
|
@ -3,13 +3,12 @@ from pathlib import Path
|
||||||
|
|
||||||
from .config import Config
|
from .config import Config
|
||||||
from .Presets import Preset, Presets
|
from .Presets import Preset, Presets
|
||||||
from .Singleton import Singleton
|
|
||||||
from .Utils import REMOVE_KEYS, arg_converter, calc_download_path, load_cookies, merge_dict
|
from .Utils import REMOVE_KEYS, arg_converter, calc_download_path, load_cookies, merge_dict
|
||||||
|
|
||||||
LOG: logging.Logger = logging.getLogger("YTDLPOpts")
|
LOG: logging.Logger = logging.getLogger("YTDLPOpts")
|
||||||
|
|
||||||
|
|
||||||
class YTDLPOpts(metaclass=Singleton):
|
class YTDLPOpts:
|
||||||
_item_opts: dict = {}
|
_item_opts: dict = {}
|
||||||
"""The item options."""
|
"""The item options."""
|
||||||
|
|
||||||
|
|
@ -22,9 +21,6 @@ class YTDLPOpts(metaclass=Singleton):
|
||||||
_preset_cli: str = ""
|
_preset_cli: str = ""
|
||||||
"""The command options for yt-dlp from preset."""
|
"""The command options for yt-dlp from preset."""
|
||||||
|
|
||||||
_instance = None
|
|
||||||
"""The instance of the class."""
|
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self._config = Config.get_instance()
|
self._config = Config.get_instance()
|
||||||
|
|
||||||
|
|
@ -37,10 +33,7 @@ class YTDLPOpts(metaclass=Singleton):
|
||||||
Presets: The instance of the class
|
Presets: The instance of the class
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if not YTDLPOpts._instance:
|
return YTDLPOpts()
|
||||||
YTDLPOpts._instance = YTDLPOpts()
|
|
||||||
|
|
||||||
return YTDLPOpts._instance
|
|
||||||
|
|
||||||
def add_cli(self, args: str, from_user: int | bool = False) -> "YTDLPOpts":
|
def add_cli(self, args: str, from_user: int | bool = False) -> "YTDLPOpts":
|
||||||
"""
|
"""
|
||||||
|
|
@ -133,7 +126,7 @@ class YTDLPOpts(metaclass=Singleton):
|
||||||
load_cookies(file)
|
load_cookies(file)
|
||||||
self._preset_opts["cookiefile"] = str(file)
|
self._preset_opts["cookiefile"] = str(file)
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
LOG.error(str(e))
|
LOG.error(f"Failed to load '{preset.name}' cookies from '{file}'. {e!s}")
|
||||||
|
|
||||||
if preset.template:
|
if preset.template:
|
||||||
self._preset_opts["outtmpl"] = {"default": preset.template, "chapter": self._config.output_template_chapter}
|
self._preset_opts["outtmpl"] = {"default": preset.template, "chapter": self._config.output_template_chapter}
|
||||||
|
|
@ -210,6 +203,6 @@ class YTDLPOpts(metaclass=Singleton):
|
||||||
if data["format"] == "-best":
|
if data["format"] == "-best":
|
||||||
data["format"] = data["format"][1:]
|
data["format"] = data["format"][1:]
|
||||||
|
|
||||||
LOG.debug(f"Parsed yt-dlp options are: '{data!s}'.")
|
LOG.debug(f"Final yt-dlp options: '{data!s}'.")
|
||||||
|
|
||||||
return data
|
return data
|
||||||
|
|
|
||||||
|
|
@ -40,15 +40,9 @@ async def resume(notify: EventBus, queue: DownloadQueue):
|
||||||
|
|
||||||
@route(RouteType.SOCKET, "add_url", "add_url")
|
@route(RouteType.SOCKET, "add_url", "add_url")
|
||||||
async def add_url(queue: DownloadQueue, notify: EventBus, sid: str, data: dict):
|
async def add_url(queue: DownloadQueue, notify: EventBus, sid: str, data: dict):
|
||||||
url: str | None = data.get("url")
|
data = data if isinstance(data, dict) else {}
|
||||||
|
if not (url := data.get("url", None)):
|
||||||
if not url:
|
await notify.emit(Events.LOG_ERROR, title="Invalid request", message="No URL provided.", to=sid)
|
||||||
await notify.emit(
|
|
||||||
Events.LOG_ERROR,
|
|
||||||
title="Invalid URL",
|
|
||||||
message="Please provide a valid URL to add to the download queue.",
|
|
||||||
to=sid,
|
|
||||||
)
|
|
||||||
return
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
@ -67,57 +61,19 @@ async def add_url(queue: DownloadQueue, notify: EventBus, sid: str, data: dict):
|
||||||
|
|
||||||
@route(RouteType.SOCKET, "item_cancel", "item_cancel")
|
@route(RouteType.SOCKET, "item_cancel", "item_cancel")
|
||||||
async def item_cancel(queue: DownloadQueue, notify: EventBus, sid: str, data: str):
|
async def item_cancel(queue: DownloadQueue, notify: EventBus, sid: str, data: str):
|
||||||
if not data:
|
if not (data := data if isinstance(data, str) else None):
|
||||||
await notify.emit(
|
await notify.emit(Events.LOG_ERROR, title="Invalid Request", message="No item ID provided.", to=sid)
|
||||||
Events.LOG_ERROR,
|
|
||||||
title="Invalid Request",
|
|
||||||
message="No item ID provided to cancel.",
|
|
||||||
to=sid,
|
|
||||||
)
|
|
||||||
return
|
return
|
||||||
|
|
||||||
try:
|
await queue.cancel([data])
|
||||||
item = queue.get_item(id=data)
|
|
||||||
except KeyError:
|
|
||||||
await notify.emit(
|
|
||||||
Events.LOG_ERROR,
|
|
||||||
title="Item Not Found",
|
|
||||||
message=f"Item with ID '{data}' not found.",
|
|
||||||
to=sid,
|
|
||||||
)
|
|
||||||
return
|
|
||||||
|
|
||||||
status: dict[str, str] = {}
|
|
||||||
status = await queue.cancel([data])
|
|
||||||
status.update({"identifier": data})
|
|
||||||
|
|
||||||
await notify.emit(
|
|
||||||
Events.ITEM_CANCELLED,
|
|
||||||
data=item.info,
|
|
||||||
title="Item Cancelled",
|
|
||||||
message=f"Cancelled '{item.info.title}'.",
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@route(RouteType.SOCKET, "item_delete", "item_delete")
|
@route(RouteType.SOCKET, "item_delete", "item_delete")
|
||||||
async def item_delete(queue: DownloadQueue, notify: EventBus, sid: str, data: dict):
|
async def item_delete(queue: DownloadQueue, notify: EventBus, sid: str, data: dict):
|
||||||
if not data:
|
data = data if isinstance(data, dict) else {}
|
||||||
await notify.emit(
|
|
||||||
Events.LOG_ERROR,
|
|
||||||
title="Invalid Request",
|
|
||||||
message="No item ID provided to delete.",
|
|
||||||
to=sid,
|
|
||||||
)
|
|
||||||
return
|
|
||||||
|
|
||||||
id: str | None = data.get("id")
|
if not (id := data.get("id", None)):
|
||||||
if not id:
|
await notify.emit(Events.LOG_ERROR, title="Invalid Request", message="No item ID provided.", to=sid)
|
||||||
await notify.emit(
|
|
||||||
Events.LOG_ERROR,
|
|
||||||
title="Invalid Request",
|
|
||||||
message="No item ID provided to delete.",
|
|
||||||
to=sid,
|
|
||||||
)
|
|
||||||
return
|
return
|
||||||
|
|
||||||
await queue.clear([id], remove_file=bool(data.get("remove_file", False)))
|
await queue.clear([id], remove_file=bool(data.get("remove_file", False)))
|
||||||
|
|
|
||||||
|
|
@ -340,3 +340,8 @@ hr {
|
||||||
.Vue-Toastification__toast-body {
|
.Vue-Toastification__toast-body {
|
||||||
user-select: none;
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.is-word-break {
|
||||||
|
word-break: break-word;
|
||||||
|
text-wrap: auto;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -889,7 +889,7 @@ const downloadSelected = async () => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const toggle_class = e => e.currentTarget.classList.toggle('is-text-overflow')
|
const toggle_class = e => ['is-text-overflow', 'is-word-break'].forEach(c => e.currentTarget.classList.toggle(c))
|
||||||
|
|
||||||
const removeFromArchiveDialog = (item) => {
|
const removeFromArchiveDialog = (item) => {
|
||||||
dialog_confirm.value.visible = true
|
dialog_confirm.value.visible = true
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue