make it possible to ignore item download via conditions

This commit is contained in:
arabcoders 2025-09-08 17:25:36 +03:00
parent 0d6532df5d
commit d0a11cbcd6
4 changed files with 77 additions and 35 deletions

View file

@ -24,6 +24,7 @@ from .Presets import Presets
from .Scheduler import Scheduler
from .Singleton import Singleton
from .Utils import (
archive_add,
arg_converter,
calc_download_path,
dt_delta,
@ -675,8 +676,10 @@ class DownloadQueue(metaclass=Singleton):
LOG.warning(f"Using external downloader '{yt_conf.get('external_downloader')}' for '{item.url}'.")
item.extras.update({"external_downloader": True})
archive_id = item.get_archive_id()
if item.is_archived():
if archive_id := item.get_archive_id():
if archive_id:
store_type, _ = self.get_item(archive_id=archive_id)
if not store_type:
dlInfo = Download(
@ -750,7 +753,55 @@ class DownloadQueue(metaclass=Singleton):
if not item.requeued and (condition := Conditions.get_instance().match(info=entry)):
already.pop()
LOG.info(f"Matched '{condition.name}' for '{item.url}' Adding '{condition.cli}' to request.")
item_title = entry.get("title") or entry.get("id") or item.url
message = f"Condition '{condition.name}' matched for '{item_title}'."
if condition.cli:
message += f" Re-queuing with '{condition.cli}'."
LOG.info(message)
if condition.extras.get("ignore_download", False):
extra_msg: str = ""
if yt_conf.get("download_archive") and not condition.extras.get("no_archive", False):
archive_add(yt_conf.get("download_archive"), [archive_id])
extra_msg = f" and added to archive '{yt_conf.get('download_archive')}'"
log_message = f"Ignoring download of '{item_title}' as per condition '{condition.name}'{extra_msg}."
store_type, _ = self.get_item(archive_id=archive_id)
if not store_type:
dlInfo = Download(
info=ItemDTO(
id=entry.get("id"),
title=item_title,
url=item.url,
preset=item.preset,
folder=item.folder,
status="skip",
cookies=item.cookies,
template=item.template,
msg=log_message,
extras=item.extras,
)
)
self.done.put(dlInfo)
LOG.info(log_message)
await asyncio.gather(
*[
self._notify.emit(Events.LOG_INFO, data={}, title="Ignored Download", message=log_message),
self._notify.emit(
Events.ITEM_MOVED,
data={"to": "history", "preset": dlInfo.info.preset, "item": dlInfo.info},
title="Download History Update",
message=f"Download history updated with '{item.url}'.",
),
]
)
return {"status": "ok"}
return await self.add(item=item.new_with(requeued=True, cli=condition.cli), already=already)
_status, _msg = ytdlp_reject(entry=entry, yt_params=yt_conf)

View file

@ -210,15 +210,12 @@ class Conditions(metaclass=Singleton):
msg = f"Invalid filter. '{e!s}'."
raise ValueError(msg) from e
if not item.get("cli"):
msg = "No command options for yt-dlp were found."
raise ValueError(msg)
try:
arg_converter(args=item.get("cli"))
except Exception as e:
msg = f"Invalid command options for yt-dlp. '{e!s}'."
raise ValueError(msg) from e
if item.get("cli"):
try:
arg_converter(args=item.get("cli"))
except Exception as e:
msg = f"Invalid command options for yt-dlp. '{e!s}'."
raise ValueError(msg) from e
if not isinstance(item.get("extras"), dict):
msg = "Extras must be a dictionary."

View file

@ -304,8 +304,7 @@ if (!form.extras) {
watch(() => config.ytdlp_options, newOptions => ytDlpOpt.value = newOptions
.filter(opt => !opt.ignored)
.flatMap(opt => opt.flags
.filter(flag => flag.startsWith('--'))
.flatMap(opt => opt.flags.filter(flag => flag.startsWith('--'))
.map(flag => ({ value: flag, description: opt.description || '' }))),
{ immediate: true }
)
@ -313,7 +312,7 @@ watch(() => config.ytdlp_options, newOptions => ytDlpOpt.value = newOptions
watch(() => form.filter, () => test_data.value.changed = true)
const checkInfo = async (): Promise<void> => {
const required: (keyof ConditionItem)[] = ['name', 'filter', 'cli']
const required: (keyof ConditionItem)[] = ['name', 'filter']
for (const key of required) {
if (!form[key]) {
@ -457,27 +456,20 @@ const logic_test = computed(() => {
}
})
// Extras management functions
const validateKey = (key: string): boolean => {
// Key must be lowercase with underscores only
return /^[a-z][a-z0-9_]*$/.test(key)
}
const validateKey = (key: string): boolean => /^[a-z][a-z0-9_]*$/.test(key)
const parseValue = (value: string): string | number | boolean => {
// Try to parse as number
if (!isNaN(Number(value)) && !isNaN(parseFloat(value))) {
return Number(value)
}
// Try to parse as boolean
if (value.toLowerCase() === 'true') {
if ('true' === value.toLowerCase()) {
return true
}
if (value.toLowerCase() === 'false') {
if ('false' === value.toLowerCase()) {
return false
}
// Return as string
return value
}
@ -491,7 +483,7 @@ const addExtra = (): void => {
}
if (!validateKey(key)) {
toast.error('Key must be lowercase and contain only letters, numbers, and underscores (e.g., custom_field).')
toast.error('Key must be lower_case.')
return
}
@ -519,18 +511,17 @@ const updateExtraKey = (event: Event, oldKey: string): void => {
if (!validateKey(newKey)) {
toast.error('Key must be lowercase and contain only letters, numbers, and underscores.')
target.value = oldKey // Reset to old value
target.value = oldKey
return
}
if (newKey !== oldKey) {
if (form.extras[newKey]) {
toast.error(`Key '${newKey}' already exists.`)
target.value = oldKey // Reset to old value
target.value = oldKey
return
}
// Move the value to the new key
const value = form.extras[oldKey]
delete form.extras[oldKey]
form.extras[newKey] = value
@ -540,11 +531,6 @@ const updateExtraKey = (event: Event, oldKey: string): void => {
const updateExtraValue = (key: string, event: Event): void => {
const target = event.target as HTMLInputElement
const value = target.value.trim()
if (value) {
form.extras[key] = parseValue(value)
} else {
form.extras[key] = ''
}
form.extras[key] = value ? parseValue(value) : ''
}
</script>

View file

@ -64,6 +64,14 @@
<span class="icon"><i class="fa-solid fa-terminal" /></span>
<span>{{ cond.cli }}</span>
</p>
<p class="is-text-overflow" v-if="cond.extras && Object.keys(cond.extras).length > 0">
<span class="icon"><i class="fa-solid fa-list" /></span>
<span>Extras:
<span v-for="(value, key) in cond.extras" :key="key" class="tag is-info mr-2">
<strong>{{ key }}</strong>: {{ value }}
</span>
</span>
</p>
</div>
</div>
<div class="card-content" v-if="cond?.raw">
@ -278,7 +286,7 @@ const exportItem = (cond: ConditionItem): void => {
const userData: ImportedConditionItem = {
...Object.fromEntries(Object.entries(clone).filter(([_, v]) => !!v)),
_type: 'condition',
_version: '1.0',
_version: '1.1',
} as ImportedConditionItem
copyText(encode(userData))