diff --git a/.vscode/settings.json b/.vscode/settings.json index 9211c3a5..29dfa3b4 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -111,7 +111,7 @@ "youtu" ], "css.styleSheets": [ - "ui/assets/css/*.css" + "ui/app/assets/css/*.css" ], "spellright.language": [ "en" diff --git a/app/library/Scheduler.py b/app/library/Scheduler.py index 4b03b509..fd7c425b 100644 --- a/app/library/Scheduler.py +++ b/app/library/Scheduler.py @@ -58,6 +58,7 @@ class Scheduler(metaclass=Singleton): for job in self._jobs: try: self._jobs[job].stop() + LOG.debug(f"Stopped job '{job}'.") except Exception as e: LOG.exception(e) LOG.error(f"Failed to stop job '{job}'. Error message '{e!s}'.") diff --git a/app/library/Tasks.py b/app/library/Tasks.py index 5e0d54c2..8e68bdc4 100644 --- a/app/library/Tasks.py +++ b/app/library/Tasks.py @@ -35,6 +35,7 @@ class Task: template: str = "" cli: str = "" auto_start: bool = True + enabled_handler: bool = True def serialize(self) -> dict: return self.__dict__ @@ -100,7 +101,8 @@ class Tasks(metaclass=Singleton): return Tasks._instance async def on_shutdown(self, _: web.Application): - pass + self.clear(shutdown=True) + self._task_handler.on_shutdown(_) def attach(self, _: web.Application): """ @@ -116,6 +118,7 @@ class Tasks(metaclass=Singleton): lambda data, _, **kwargs: self.save(**data.data), # noqa: ARG005 f"{__class__.__name__}.add", ) + self._task_handler.load() def get_all(self) -> list[Task]: """Return the tasks.""" @@ -155,7 +158,7 @@ class Tasks(metaclass=Singleton): self._tasks.append(task) - if not task.timer or "[only_handler]" in task.name: + if not task.timer: continue try: @@ -361,12 +364,21 @@ class Tasks(metaclass=Singleton): class HandleTask: _tasks: Tasks + _handlers: list[type] + _scheduler: Scheduler + _config: Config + _task_name: str def __init__(self, scheduler: Scheduler, tasks: Tasks, config: Config) -> None: self._tasks = tasks + self._scheduler = scheduler + self._config = config + self._task_name: str = f"{__class__.__name__}._dispatcher" + + def load(self) -> None: self._handlers: list[type] = self._discover() - timer = config.tasks_handler_timer + timer: str = self._config.tasks_handler_timer try: from cronsim import CronSim @@ -375,18 +387,26 @@ class HandleTask: timer = "15 */1 * * *" LOG.error(f"Invalid timer format. '{e!s}'. Defaulting to '{timer}'.") - scheduler.add( + self._scheduler.add( timer=timer, func=self._dispatcher, id=f"{__class__.__name__}._dispatcher", ) + def on_shutdown(self, _: web.Application) -> None: + """ + Handle shutdown event. + + Args: + _: web.Application: The aiohttp application. + + """ + if self._scheduler.has(self._task_name): + self._scheduler.remove(self._task_name) + def _dispatcher(self): for task in self._tasks.get_all(): - if "[no_handler]" in task.name: - continue - - if not task.timer and "[only_handler]" not in task.name: + if not task.enabled_handler: continue try: diff --git a/ui/app/components/TaskForm.vue b/ui/app/components/TaskForm.vue index 1c5d32b7..4d22abaf 100644 --- a/ui/app/components/TaskForm.vue +++ b/ui/app/components/TaskForm.vue @@ -215,6 +215,28 @@ +
+
+ +
+ + +
+ + + Some URLs like YouTube channels and playlists can be monitored for new videos using RSS + feed independent of the timer. If enabled, the task will monitor the RSS feed for new videos and + automatically queue them for download if they are not already downloaded. + +
+
+
- +
  • To enable YouTube RSS feed monitoring, The task URL must include a channel_id or playlist_id. Other link types won’t work.
  • -
  • RSS monitoring runs every hour alongside the actual task execution. It checks each feed for new videos - and automatically queues any you haven’t downloaded yet.
  • -
  • To opt out of RSS monitoring for a specific task, append [no_handler] to that task’s name. -
  • -
  • To have the task only monitor RSS feed, do not set timer and add [only_handler] to that - task’s name.
  • +
  • RSS monitoring runs every hour alongside the actual task execution. Regardless if the task has timer set + or not. To opt out of RSS monitoring for a specific task, simply disable the Enable Handler + option. To have the task only monitor RSS feed, do not set timer.
  • RSS Feed monitoring will only work if you have --download-archive set in command options - for ytdlp.cli, preset or task.
  • -
  • If you don't have --download-archive set but YTP_KEEP_ARCHIVE environment - option is set to true which is the default, It will also work. + for ytdlp.cli, preset or task. If you don't have --download-archive set but + YTP_KEEP_ARCHIVE environment option is set to true which is the default, It will + also work.
@@ -320,9 +339,15 @@ onMounted(() => { if (!props.task?.preset || '' === props.task.preset) { form.preset = toRaw(config.app.default_preset) } + if (typeof form.auto_start === 'undefined' || null === form.auto_start) { form.auto_start = true } + + if (typeof form.enabled_handler === 'undefined' || null === form.enabled_handler) { + form.enabled_handler = true + } + }) const checkInfo = async (): Promise => { diff --git a/ui/app/pages/tasks.vue b/ui/app/pages/tasks.vue index 90efa8bd..71b58756 100644 --- a/ui/app/pages/tasks.vue +++ b/ui/app/pages/tasks.vue @@ -66,8 +66,8 @@ div.is-centered {
- +
@@ -149,7 +149,7 @@ div.is-centered { {{ remove_tags(item.name) }}
-
+
  + + + {{ item.enabled_handler ? 'Enabled' : 'Disabled' }} + +   {{ item.preset ?? config.app.default_preset }} @@ -233,6 +238,11 @@ div.is-centered { :class="{ 'fa-circle-pause': item.auto_start, 'fa-circle-play': !item.auto_start }" />
+
+ + + +