[BACKEND] %contains_any function, list + dict support for tilda overrides mode (#1054)
Adds the function `%contains_any`, and list support in a tilda override subscription. The end-goal of these features are to more easily add a title exclude list, like so:
```
__preset__:
filter_exclude:
- "{%contains_any( %lower(title), exclude_title_strings )}"
...
Jellyfin TV Show by Date:
~History Documentaries:
url: "https://..."
exclude_title_strings:
- "trailer"
- "preview"
```
A proper prebuilt preset or built-in functionality will follow this change.
This commit is contained in:
parent
759948361f
commit
10cb82a69a
5 changed files with 42 additions and 2 deletions
|
|
@ -595,6 +595,13 @@ contains
|
|||
:description:
|
||||
Returns True if ``contains`` is in ``string``. False otherwise.
|
||||
|
||||
contains_any
|
||||
~~~~~~~~~~~~
|
||||
:spec: ``contains_any(string: String, contains_array: Array) -> Boolean``
|
||||
|
||||
:description:
|
||||
Returns true if any element in ``contains_array`` is in ``string``. False otherwise.
|
||||
|
||||
lower
|
||||
~~~~~
|
||||
:spec: ``lower(string: String) -> String``
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ from typing import Optional
|
|||
from ytdl_sub.script.types.array import Array
|
||||
from ytdl_sub.script.types.resolvable import AnyArgument
|
||||
from ytdl_sub.script.types.resolvable import Boolean
|
||||
from ytdl_sub.script.types.resolvable import Float
|
||||
from ytdl_sub.script.types.resolvable import Integer
|
||||
from ytdl_sub.script.types.resolvable import Numeric
|
||||
from ytdl_sub.script.types.resolvable import String
|
||||
|
|
@ -25,6 +26,20 @@ class StringFunctions:
|
|||
"""
|
||||
return Boolean(contains.value in string.value)
|
||||
|
||||
@staticmethod
|
||||
def contains_any(string: String, contains_array: Array) -> Boolean:
|
||||
"""
|
||||
:description:
|
||||
Returns true if any element in ``contains_array`` is in ``string``. False otherwise.
|
||||
"""
|
||||
return Boolean(
|
||||
any(
|
||||
str(val) in string.value
|
||||
for val in contains_array.value
|
||||
if isinstance(val, (String, Integer, Boolean, Float))
|
||||
)
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def slice(string: String, start: Integer, end: Optional[Integer] = None) -> String:
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ from ytdl_sub.config.config_file import ConfigFile
|
|||
from ytdl_sub.config.overrides import Overrides
|
||||
from ytdl_sub.entries.variables.override_variables import SubscriptionVariables
|
||||
from ytdl_sub.utils.script import ScriptUtils
|
||||
from ytdl_sub.validators.string_formatter_validators import DictFormatterValidator
|
||||
from ytdl_sub.validators.string_formatter_validators import UnstructuredDictFormatterValidator
|
||||
from ytdl_sub.validators.validators import DictValidator
|
||||
from ytdl_sub.validators.validators import LiteralDictValidator
|
||||
from ytdl_sub.validators.validators import StringListValidator
|
||||
|
|
@ -196,7 +196,9 @@ class SubscriptionListValuesValidator(SubscriptionLeafValidator, StringListValid
|
|||
)
|
||||
|
||||
|
||||
class SubscriptionWithOverridesValidator(SubscriptionLeafValidator, DictFormatterValidator):
|
||||
class SubscriptionWithOverridesValidator(
|
||||
SubscriptionLeafValidator, UnstructuredDictFormatterValidator
|
||||
):
|
||||
def __init__(
|
||||
self,
|
||||
name,
|
||||
|
|
|
|||
|
|
@ -159,6 +159,12 @@ def preset_with_subscription_overrides_tilda(
|
|||
"parent_preset_2 | parent_preset_1": {
|
||||
"~ test_2_1": {
|
||||
"current_override": "test_2_1",
|
||||
"custom_list": [
|
||||
"elem1",
|
||||
"elem2",
|
||||
"elem3",
|
||||
],
|
||||
"passed_list_elem": "{%contains_any('elem2', custom_list)}",
|
||||
}
|
||||
},
|
||||
},
|
||||
|
|
@ -262,6 +268,8 @@ def test_subscription_overrides_tilda(
|
|||
|
||||
assert sub_2_1.get("subscription_name").native == "test_2_1"
|
||||
assert sub_2_1.get("current_override").native == "test_2_1" # tilda sub takes precedence
|
||||
assert sub_2_1.get("passed_list_elem").native is True
|
||||
assert sub_2_1.get("custom_list").native == ["elem1", "elem2", "elem3"]
|
||||
|
||||
|
||||
def test_subscription_overrides_map(
|
||||
|
|
|
|||
|
|
@ -118,6 +118,14 @@ class TestNumericFunctions:
|
|||
output = single_variable_output(f"{{%contains('a brown dog', '{value}')}}")
|
||||
assert output == expected_output
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"value, expected_output",
|
||||
[("['a', 'b', 'c']", True), ("['nope', [], {}]", False), ("['at', 'dog']", True)],
|
||||
)
|
||||
def test_contains_any(self, value, expected_output):
|
||||
output = single_variable_output(f"{{%contains_any('a brown dog', {value})}}")
|
||||
assert output == expected_output
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"input_string, split, max_split, expected_output",
|
||||
[
|
||||
|
|
|
|||
Loading…
Reference in a new issue