Added toggle for task handler.
This commit is contained in:
parent
dcaeb7acc8
commit
584d4e107e
6 changed files with 80 additions and 23 deletions
2
.vscode/settings.json
vendored
2
.vscode/settings.json
vendored
|
|
@ -111,7 +111,7 @@
|
|||
"youtu"
|
||||
],
|
||||
"css.styleSheets": [
|
||||
"ui/assets/css/*.css"
|
||||
"ui/app/assets/css/*.css"
|
||||
],
|
||||
"spellright.language": [
|
||||
"en"
|
||||
|
|
|
|||
|
|
@ -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}'.")
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -215,6 +215,28 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="column is-6-tablet is-12-mobile">
|
||||
<div class="field">
|
||||
<label class="label is-inline" for="output_template">
|
||||
<span class="icon"><i class="fa-solid fa-rss" /></span>
|
||||
Enable Handler
|
||||
</label>
|
||||
<div class="control is-unselectable">
|
||||
<input id="auto_start" type="checkbox" v-model="form.enabled_handler" :disabled="addInProgress"
|
||||
class="switch is-success" />
|
||||
<label for="auto_start" class="is-unselectable">
|
||||
{{ form.enabled_handler ? 'Yes' : 'No' }}
|
||||
</label>
|
||||
</div>
|
||||
<span class="help">
|
||||
<span class="icon"><i class="fa-solid fa-info" /></span>
|
||||
<span>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.</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="column is-12">
|
||||
<div class="field">
|
||||
<label class="label is-inline" for="cli_options">
|
||||
|
|
@ -260,22 +282,19 @@
|
|||
</div>
|
||||
|
||||
<div class="column is-12">
|
||||
<Message title="Tips" class="is-background-info-80 has-text-dark" icon="fas fa-info-circle">
|
||||
<Message title="Tips" class="is-info is-background-info-80 has-text-dark" icon="fas fa-info-circle">
|
||||
<span>
|
||||
<ul>
|
||||
<li>To enable YouTube RSS feed monitoring, The task URL must include a <code>channel_id</code> or
|
||||
<code>playlist_id</code>. Other link types won’t work.
|
||||
</li>
|
||||
<li>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.</li>
|
||||
<li>To opt out of RSS monitoring for a specific task, append <code>[no_handler]</code> to that task’s name.
|
||||
</li>
|
||||
<li>To have the task only monitor RSS feed, do not set timer and add <code>[only_handler]</code> to that
|
||||
task’s name.</li>
|
||||
<li>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 <code>Enable Handler</code>
|
||||
option. To have the task only monitor RSS feed, <b>do not set timer</b>.</li>
|
||||
<li>RSS Feed monitoring will only work if you have <code>--download-archive</code> set in command options
|
||||
for ytdlp.cli, preset or task.</li>
|
||||
<li>If you don't have <code>--download-archive</code> set but <code>YTP_KEEP_ARCHIVE</code> environment
|
||||
option is set to <code>true</code> which is the default, It will also work.
|
||||
for ytdlp.cli, preset or task. If you don't have <code>--download-archive</code> set but
|
||||
<code>YTP_KEEP_ARCHIVE</code> environment option is set to <code>true</code> which is the default, It will
|
||||
also work.
|
||||
</li>
|
||||
</ul>
|
||||
</span>
|
||||
|
|
@ -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<void> => {
|
||||
|
|
|
|||
|
|
@ -66,8 +66,8 @@ div.is-centered {
|
|||
|
||||
<div class="columns is-multiline" v-if="toggleForm">
|
||||
<div class="column is-12">
|
||||
<TaskForm :addInProgress="addInProgress" :reference="taskRef" :task="task" @cancel="resetForm(true);"
|
||||
@submit="updateItem" />
|
||||
<TaskForm :addInProgress="addInProgress" :reference="taskRef" :task="task as task_item"
|
||||
@cancel="resetForm(true);" @submit="updateItem" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -149,7 +149,7 @@ div.is-centered {
|
|||
{{ remove_tags(item.name) }}
|
||||
</NuxtLink>
|
||||
</div>
|
||||
<div>
|
||||
<div class="is-unselectable">
|
||||
<span class="icon-text">
|
||||
<span class="icon">
|
||||
<i class="fa-solid"
|
||||
|
|
@ -160,6 +160,11 @@ div.is-centered {
|
|||
</span>
|
||||
</span>
|
||||
|
||||
<span class="icon-text">
|
||||
<span class="icon"><i class="fa-solid fa-rss" /></span>
|
||||
<span>{{ item.enabled_handler ? 'Enabled' : 'Disabled' }}</span>
|
||||
</span>
|
||||
|
||||
<span class="icon-text" v-if="item.preset">
|
||||
<span class="icon"><i class="fa-solid fa-tv" /></span>
|
||||
<span>{{ item.preset ?? config.app.default_preset }}</span>
|
||||
|
|
@ -233,6 +238,11 @@ div.is-centered {
|
|||
:class="{ 'fa-circle-pause': item.auto_start, 'fa-circle-play': !item.auto_start }" />
|
||||
</span>
|
||||
</div>
|
||||
<div class="control">
|
||||
<span class="icon" v-tooltip="`RSS monitoring is ${item.enabled_handler ? 'enabled' : 'disabled'}`">
|
||||
<i class="fa-solid fa-rss has-text-success" />
|
||||
</span>
|
||||
</div>
|
||||
<div class="control">
|
||||
<a class="has-text-primary" v-tooltip="'Export task.'" @click.prevent="exportItem(item)">
|
||||
<span class="icon"><i class="fa-solid fa-file-export" /></span>
|
||||
|
|
@ -544,7 +554,7 @@ const deleteItem = async (item: task_item) => {
|
|||
toast.success('Task deleted.')
|
||||
}
|
||||
|
||||
const updateItem = async ({ reference, task }: { reference?: string, task: task_item }) => {
|
||||
const updateItem = async ({ reference, task }: { reference?: string | null | undefined, task: task_item }) => {
|
||||
if (reference) {
|
||||
// -- find the task index.
|
||||
const index = tasks.value.findIndex((t) => t?.id === reference)
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ type task_item = {
|
|||
timer?: string,
|
||||
in_progress?: boolean,
|
||||
auto_start?: boolean,
|
||||
enabled_handler?: boolean,
|
||||
}
|
||||
|
||||
type exported_task = task_item & { _type: string, _version: string }
|
||||
|
|
|
|||
Loading…
Reference in a new issue