From 4a017500c79385266ee674863e8e9fa9dca56523 Mon Sep 17 00:00:00 2001 From: arabcoders Date: Thu, 24 Jul 2025 19:31:19 +0300 Subject: [PATCH] Fixed in browser match_str to closely match yt-dlp match_str --- ui/app/components/ConditionForm.vue | 4 +-- ui/app/utils/ytdlp.ts | 44 +++++++++++++++++++++-------- 2 files changed, 35 insertions(+), 13 deletions(-) diff --git a/ui/app/components/ConditionForm.vue b/ui/app/components/ConditionForm.vue index 0993ce81..4ede9228 100644 --- a/ui/app/components/ConditionForm.vue +++ b/ui/app/components/ConditionForm.vue @@ -290,7 +290,7 @@ const run_test = async (): Promise => { } test_data.value.in_progress = true - test_data.value.data.status = null + test_data.value.data.status = false try { const response = await request('/api/conditions/test', { @@ -361,7 +361,7 @@ const show_data = (): string => { } const logic_test = computed(() => { - if (!test_data.value.data || !test_data.value.data.data) { + if (Object.keys(test_data.value.data?.data ?? {}).length < 1) { return null } diff --git a/ui/app/utils/ytdlp.ts b/ui/app/utils/ytdlp.ts index 7308b6cc..4259c3b4 100644 --- a/ui/app/utils/ytdlp.ts +++ b/ui/app/utils/ytdlp.ts @@ -5,9 +5,28 @@ function match_str(filterStr: string, dct: Record, incomplete: bool return true; } - return filterStr - .split(/(? _match_one(filterPart.replace(/\\&/g, '&'), dct, incomplete)); + if (/\s*&\s*$/.test(filterStr)) { + return false; + } + + try { + const filterParts = filterStr + .split(/(?:(^|[^\\]))&/g) + .reduce((parts, part, index, array) => { + if (index % 2 === 0) { + parts.push((part + (array[index + 1] || '')).replace(/\\&/g, '&')); + } + return parts; + }, [] as string[]); + + if (filterParts.some(fp => !fp.trim())) { + return false; + } + + return filterParts.every(filterPart => _match_one(filterPart, dct, incomplete)); + } catch (e) { + return false; + } } function lookup_unit_table(unitTable: Record, s: string, strict = false): number | null { @@ -101,7 +120,14 @@ function _match_one(filterPart: string, dct: Record, incomplete: bo const opFn = negation ? (a: any, b: any) => !unnegatedOp(a, b) : unnegatedOp; let value = quoted ?? plain ?? ''; - if (quote) value = value.replace(new RegExp(`\\\\${quote}`, 'g'), quote); + + if (quote) { + value = value.replace(new RegExp(`\\\\${quote}`, 'g'), quote); + } + + if (!(key! in dct)) { + return isIncomplete(key!) || Boolean(noneInclusive); + } const actual = dct[key!]; let numeric: number | null = null; @@ -117,10 +143,6 @@ function _match_one(filterPart: string, dct: Record, incomplete: bo throw new Error(`Operator ${op} only supports string values!`); } - if (actual == null) { - return isIncomplete(key!) || Boolean(noneInclusive); - } - return opFn(actual, numeric !== null ? numeric : value); } @@ -133,12 +155,12 @@ function _match_one(filterPart: string, dct: Record, incomplete: bo const mu = filterPart.trim().match(unaryRe); if (mu?.groups) { const { op, key } = mu.groups; - const actual = dct[key!]; - if (actual === undefined && isIncomplete(key!)) { - return true; + if (!(key! in dct)) { + return isIncomplete(key!); } + const actual = dct[key!]; const unaryOp = UNARY_OPERATORS[op!]; if (!unaryOp) {