Adds the ability to change season and episode ordering using override variables, like so:
```
"~Kids Toys Play":
url: "https://www.youtube.com/@KidsToysPlayChannel"
tv_show_by_date_season_ordering: "upload-year-month"
tv_show_by_date_episode_ordering: "upload-day"
```
In addition, adds support for release-date based episode ordering (and culling if using Only Recent).
More info here: https://ytdl-sub.readthedocs.io/en/latest/prebuilt_presets/tv_shows.html
Closes https://github.com/jmbannon/ytdl-sub/issues/1182
216 lines
6 KiB
Python
216 lines
6 KiB
Python
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
|
|
|
|
|
|
class StringFunctions:
|
|
@staticmethod
|
|
def string(value: AnyArgument) -> String:
|
|
"""
|
|
:description:
|
|
Cast to String.
|
|
"""
|
|
return String(value=str(value.value))
|
|
|
|
@staticmethod
|
|
def contains(string: String, contains: String) -> Boolean:
|
|
"""
|
|
:description:
|
|
Returns True if ``contains`` is in ``string``. False otherwise.
|
|
"""
|
|
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 contains_all(string: String, contains_array: Array) -> Boolean:
|
|
"""
|
|
:description:
|
|
Returns true if all elements in ``contains_array`` are in ``string``. False otherwise.
|
|
"""
|
|
return Boolean(
|
|
all(
|
|
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:
|
|
"""
|
|
:description:
|
|
Returns the slice of the Array.
|
|
"""
|
|
if end is not None:
|
|
return String(string.value[start.value : end.value])
|
|
return String(string.value[start.value :])
|
|
|
|
@staticmethod
|
|
def lower(string: String) -> String:
|
|
"""
|
|
:description:
|
|
Lower-case the entire String.
|
|
"""
|
|
return String(string.value.lower())
|
|
|
|
@staticmethod
|
|
def upper(string: String) -> String:
|
|
"""
|
|
:description:
|
|
Upper-case the entire String.
|
|
"""
|
|
return String(string.value.upper())
|
|
|
|
@staticmethod
|
|
def capitalize(string: String) -> String:
|
|
"""
|
|
:description:
|
|
Capitalize the first character in the string.
|
|
"""
|
|
return String(string.value.capitalize())
|
|
|
|
@staticmethod
|
|
def titlecase(string: String) -> String:
|
|
"""
|
|
:description:
|
|
Capitalize each word in the string.
|
|
"""
|
|
return String(string.value.title())
|
|
|
|
@staticmethod
|
|
def replace(
|
|
string: String, old: String, new: String, count: Optional[Integer] = None
|
|
) -> String:
|
|
"""
|
|
:description:
|
|
Replace the ``old`` part of the String with the ``new``. Optionally only replace it
|
|
``count`` number of times.
|
|
"""
|
|
if count:
|
|
return String(string.value.replace(old.value, new.value, count.value))
|
|
|
|
return String(string.value.replace(old.value, new.value))
|
|
|
|
@staticmethod
|
|
def split(string: String, sep: String, max_split: Optional[Integer] = None) -> Array:
|
|
"""
|
|
:description:
|
|
Splits the input string into multiple strings.
|
|
"""
|
|
if max_split is not None:
|
|
return Array(
|
|
[
|
|
String(split_val)
|
|
for split_val in string.value.split(sep=sep.value, maxsplit=max_split.value)
|
|
]
|
|
)
|
|
|
|
return Array([String(split_val) for split_val in string.value.split(sep=sep.value)])
|
|
|
|
@staticmethod
|
|
def concat(*values: AnyArgument) -> String:
|
|
"""
|
|
:description:
|
|
Concatenate multiple Strings into a single String.
|
|
"""
|
|
return String("".join(str(val.value) for val in values))
|
|
|
|
@staticmethod
|
|
def pad(string: String, length: Integer, char: String) -> String:
|
|
"""
|
|
:description:
|
|
Pads the string to the given length
|
|
"""
|
|
output = string.value
|
|
while len(output) < length.value:
|
|
output = f"{char}{output}"
|
|
|
|
return String(output)
|
|
|
|
@staticmethod
|
|
def pad_zero(numeric: Numeric, length: Integer) -> String:
|
|
"""
|
|
:description:
|
|
Pads a numeric with zeros to the given length
|
|
"""
|
|
return StringFunctions.pad(
|
|
string=String(str(numeric.value)),
|
|
length=length,
|
|
char=String("0"),
|
|
)
|
|
|
|
@staticmethod
|
|
def unescape(string: String) -> String:
|
|
"""
|
|
:description:
|
|
Unescape symbols like newlines or tabs to their true form.
|
|
|
|
:usage:
|
|
|
|
.. code-block:: python
|
|
|
|
{
|
|
%unescape( "Hello\\nWorld" )
|
|
}
|
|
|
|
# Hello
|
|
# World
|
|
"""
|
|
return String(string.value.encode("utf-8").decode("unicode_escape"))
|
|
|
|
@staticmethod
|
|
def join(separator: String, array: Array) -> String:
|
|
"""
|
|
:description:
|
|
Join all elements in the array together as a string, and insert the
|
|
separator between them.
|
|
|
|
:usage:
|
|
|
|
.. code-block:: python
|
|
|
|
{
|
|
%join( ", ", ["item1", "item2"] )
|
|
}
|
|
|
|
# "item1, item2"
|
|
"""
|
|
|
|
return String(separator.value.join(str(val) for val in array.value))
|
|
|
|
@staticmethod
|
|
def strip(string: String) -> String:
|
|
"""
|
|
:description:
|
|
Strip a string of all its whitespace at the beginning and end.
|
|
|
|
:usage:
|
|
|
|
.. code-block:: python
|
|
|
|
{
|
|
%trim(" delete the outer! ")
|
|
}
|
|
|
|
# "delete the outer!"
|
|
"""
|
|
return String(string.value.strip())
|