ugh
This commit is contained in:
parent
e6ee337f20
commit
98bd2df447
6 changed files with 160 additions and 145 deletions
|
|
@ -1 +1,100 @@
|
||||||
|
from yt_dlp.utils import sanitize_filename
|
||||||
|
|
||||||
|
from ytdl_sub.script.types.map import Map
|
||||||
|
from ytdl_sub.script.types.resolvable import Integer
|
||||||
|
from ytdl_sub.script.types.resolvable import String
|
||||||
|
from ytdl_sub.script.utils.exceptions import RuntimeException
|
||||||
|
|
||||||
|
|
||||||
|
def _pad(num: int, width: int):
|
||||||
|
return str(num).zfill(width)
|
||||||
|
|
||||||
|
|
||||||
|
_days_in_month = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
|
||||||
|
|
||||||
|
|
||||||
|
class CustomFunctions:
|
||||||
|
@staticmethod
|
||||||
|
def sanitize(string: String) -> String:
|
||||||
|
return String(sanitize_filename(string.value))
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def sanitize_plex_episode(string: String) -> String:
|
||||||
|
out = CustomFunctions.sanitize(string).value
|
||||||
|
for char in out:
|
||||||
|
match char:
|
||||||
|
case "0":
|
||||||
|
out += "0"
|
||||||
|
case "1":
|
||||||
|
out += "1"
|
||||||
|
case "2":
|
||||||
|
out += "2"
|
||||||
|
case "3":
|
||||||
|
out += "3"
|
||||||
|
case "4":
|
||||||
|
out += "4"
|
||||||
|
case "5":
|
||||||
|
out += "5"
|
||||||
|
case "6":
|
||||||
|
out += "6"
|
||||||
|
case "7":
|
||||||
|
out += "7"
|
||||||
|
case "8":
|
||||||
|
out += "8"
|
||||||
|
case "9":
|
||||||
|
out += "9"
|
||||||
|
case _:
|
||||||
|
out += char
|
||||||
|
return String(out)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def date_metadata(yyyymmdd: String) -> Map:
|
||||||
|
date_str = yyyymmdd.value
|
||||||
|
if not (date_str.isnumeric() and len(date_str) == 6):
|
||||||
|
raise RuntimeException(
|
||||||
|
f"Expected input of date_metadata to be YYYYMMDD, but received {date_str}"
|
||||||
|
)
|
||||||
|
|
||||||
|
year: int = int(date_str[:4])
|
||||||
|
month_padded: str = date_str[4:6]
|
||||||
|
day_padded: str = date_str[6:8]
|
||||||
|
|
||||||
|
month: int = int(month_padded)
|
||||||
|
day: int = int(day_padded)
|
||||||
|
year_truncated: int = int(str(year)[-2:])
|
||||||
|
|
||||||
|
day_of_year: int = sum(_days_in_month[:month]) + day
|
||||||
|
total_days_in_month: int = _days_in_month[month]
|
||||||
|
total_days_in_year: int = 365
|
||||||
|
if year % 4 == 0:
|
||||||
|
total_days_in_year += 1
|
||||||
|
if month == 2:
|
||||||
|
total_days_in_month += 1
|
||||||
|
if month > 2:
|
||||||
|
day_of_year += 1
|
||||||
|
|
||||||
|
day_of_year_reversed: int = total_days_in_year + 1 - day_of_year
|
||||||
|
month_reversed: int = 13 - month
|
||||||
|
day_reversed: int = total_days_in_month + 1 - day
|
||||||
|
|
||||||
|
return Map(
|
||||||
|
{
|
||||||
|
String("date"): yyyymmdd,
|
||||||
|
String("date_standardized"): String(f"{year}-{month_padded}-{day_padded}"),
|
||||||
|
String("year"): Integer(year),
|
||||||
|
String("month"): Integer(month),
|
||||||
|
String("day"): Integer(day),
|
||||||
|
String("year_truncated"): String(year_truncated),
|
||||||
|
String("month_padded"): String(month_padded),
|
||||||
|
String("day_padded"): String(day_padded),
|
||||||
|
String("year_truncated_reversed"): Integer(100 - year_truncated),
|
||||||
|
String("month_reversed"): Integer(month_reversed),
|
||||||
|
String("month_reversed_padded"): String(_pad(month_reversed, width=2)),
|
||||||
|
String("day_reversed"): Integer(day_reversed),
|
||||||
|
String("day_reversed_padded"): String(_pad(day_reversed, width=2)),
|
||||||
|
String("day_of_year"): Integer(day_of_year),
|
||||||
|
String("day_of_year_padded"): String(_pad(day_of_year, width=3)),
|
||||||
|
String("day_of_year_reversed"): Integer(day_of_year_reversed),
|
||||||
|
String("day_of_year_reversed_padded"): String(_pad(day_of_year_reversed, width=3)),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
|
||||||
|
|
@ -1,82 +0,0 @@
|
||||||
from dataclasses import dataclass
|
|
||||||
from typing import List
|
|
||||||
from typing import Optional
|
|
||||||
|
|
||||||
|
|
||||||
class KwargKeys:
|
|
||||||
keys: List[str] = []
|
|
||||||
backend_keys: List[str] = []
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass(frozen=True)
|
|
||||||
class KwargKey:
|
|
||||||
entry_key: str
|
|
||||||
variable_name: str
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def init(cls, entry_key: str, variable_name: Optional[str] = None) -> "KwargKey":
|
|
||||||
return cls(entry_key=entry_key, variable_name=variable_name if variable_name else entry_key)
|
|
||||||
|
|
||||||
|
|
||||||
def _(entry_key: str, variable_name: Optional[str] = None, backend: bool = False) -> KwargKey:
|
|
||||||
if backend:
|
|
||||||
assert entry_key not in KwargKeys.backend_keys
|
|
||||||
KwargKeys.backend_keys.append(entry_key)
|
|
||||||
else:
|
|
||||||
assert entry_key not in KwargKeys.keys
|
|
||||||
KwargKeys.keys.append(entry_key)
|
|
||||||
return KwargKey(
|
|
||||||
entry_key=entry_key, variable_name=variable_name if variable_name is not None else entry_key
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
SOURCE_ENTRY = _("source_entry", backend=True)
|
|
||||||
SOURCE_INDEX = _("source_index")
|
|
||||||
SOURCE_COUNT = _("source_count")
|
|
||||||
SOURCE_TITLE = _("source_title")
|
|
||||||
SOURCE_UID = _("source_uid")
|
|
||||||
SOURCE_DESCRIPTION = _("source_description")
|
|
||||||
SOURCE_WEBPAGE_URL = _("source_webpage_url")
|
|
||||||
SOURCE_UPLOADER = _("source_uploader")
|
|
||||||
SOURCE_UPLOADER_ID = _("source_uploader_id")
|
|
||||||
SOURCE_UPLOADER_URL = _("source_uploader_url")
|
|
||||||
|
|
||||||
PLAYLIST_ENTRY = _("playlist_entry", backend=True)
|
|
||||||
PLAYLIST_WEBPAGE_URL = _("playlist_webpage_url")
|
|
||||||
PLAYLIST_INDEX = _("playlist_index")
|
|
||||||
PLAYLIST_COUNT = _("playlist_count")
|
|
||||||
PLAYLIST_MAX_UPLOAD_YEAR = _("playlist_max_upload_year")
|
|
||||||
PLAYLIST_MAX_UPLOAD_YEAR_TRUNCATED = _("playlist_max_upload_year_truncated")
|
|
||||||
PLAYLIST_TITLE = _("playlist_title")
|
|
||||||
PLAYLIST_DESCRIPTION = _("playlist_description")
|
|
||||||
PLAYLIST_UID = _("playlist_uid")
|
|
||||||
PLAYLIST_UPLOADER = _("playlist_uploader")
|
|
||||||
PLAYLIST_UPLOADER_ID = _("playlist_uploader_id")
|
|
||||||
PLAYLIST_UPLOADER_URL = _("playlist_uploader_url")
|
|
||||||
|
|
||||||
COLLECTION_URL = _("collection_url", backend=True)
|
|
||||||
DOWNLOAD_INDEX = _("download_index", backend=True)
|
|
||||||
UPLOAD_DATE_INDEX = _("upload_date_index", backend=True)
|
|
||||||
REQUESTED_SUBTITLES = _("requested_subtitles", backend=True)
|
|
||||||
CHAPTERS = _("chapters", backend=True)
|
|
||||||
YTDL_SUB_CUSTOM_CHAPTERS = _("ytdl_sub_custom_chapters", backend=True)
|
|
||||||
YTDL_SUB_REGEX_SOURCE_VARS = _("ytdl_sub_regex_source_vars", backend=True)
|
|
||||||
SPONSORBLOCK_CHAPTERS = _("sponsorblock_chapters", backend=True)
|
|
||||||
SPLIT_BY_CHAPTERS_PARENT_ENTRY = _("split_by_chapters_parent_entry", backend=True)
|
|
||||||
COMMENTS = _("comments", backend=True)
|
|
||||||
UID = _(entry_key="id", variable_name="uid")
|
|
||||||
EXTRACTOR = _("extractor")
|
|
||||||
IE_KEY = _("ie_key")
|
|
||||||
EPOCH = _("epoch")
|
|
||||||
CHANNEL = _("channel")
|
|
||||||
CHANNEL_ID = _("channel_id")
|
|
||||||
CREATOR = _("creator")
|
|
||||||
EXT = _("ext")
|
|
||||||
TITLE = _("title")
|
|
||||||
DESCRIPTION = _("description")
|
|
||||||
WEBPAGE_URL = _("webpage_url")
|
|
||||||
RELEASE_DATE = _("release_date")
|
|
||||||
UPLOAD_DATE = _("upload_date")
|
|
||||||
UPLOADER = _("uploader")
|
|
||||||
UPLOADER_ID = _("uploader_id")
|
|
||||||
UPLOADER_URL = _("uploader_url")
|
|
||||||
|
|
@ -1,10 +1,21 @@
|
||||||
from ytdl_sub.entries.script.kwargs import KwargKey
|
from dataclasses import dataclass
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
# This file contains mixins to a BaseEntry subclass. Ignore pylint's "no kwargs member" suggestion
|
# This file contains mixins to a BaseEntry subclass. Ignore pylint's "no kwargs member" suggestion
|
||||||
# pylint: disable=no-member
|
# pylint: disable=no-member
|
||||||
# pylint: disable=too-many-public-methods
|
# pylint: disable=too-many-public-methods
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class KwargKey:
|
||||||
|
entry_key: str
|
||||||
|
variable_name: str
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def init(cls, entry_key: str, variable_name: Optional[str] = None) -> "KwargKey":
|
||||||
|
return cls(entry_key=entry_key, variable_name=variable_name if variable_name else entry_key)
|
||||||
|
|
||||||
|
|
||||||
class Variables:
|
class Variables:
|
||||||
@property
|
@property
|
||||||
def uid(self) -> KwargKey:
|
def uid(self) -> KwargKey:
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from ytdl_sub.entries.script.kwargs import KwargKey
|
from ytdl_sub.entries.script.variable_definitions import KwargKey
|
||||||
from ytdl_sub.entries.script.variables import Variables
|
from ytdl_sub.entries.script.variable_definitions import Variables
|
||||||
|
|
||||||
ENTRY_MAP_VARIABLE = "entry"
|
ENTRY_MAP_VARIABLE = "entry"
|
||||||
|
|
||||||
|
|
@ -32,8 +32,11 @@ def sanitized(key: KwargKey) -> str:
|
||||||
|
|
||||||
|
|
||||||
def sanitized_plex(key: KwargKey) -> str:
|
def sanitized_plex(key: KwargKey) -> str:
|
||||||
return f"""{{
|
return f"{{%sanitize_plex_episode({key.variable_name})}}"
|
||||||
}}"""
|
|
||||||
|
|
||||||
|
def date_metadata(date_key: KwargKey, metadata_key: str) -> str:
|
||||||
|
return f"{{%map_get(%date_metadata({date_key.variable_name}), '{metadata_key}')}}"
|
||||||
|
|
||||||
|
|
||||||
# singleton to produce variable keys
|
# singleton to produce variable keys
|
||||||
|
|
@ -62,10 +65,12 @@ ENTRY_DEFAULT_VARIABLES: Dict[KwargKey, str] = {
|
||||||
}
|
}
|
||||||
|
|
||||||
ENTRY_DERIVED_VARIABLES: Dict[KwargKey, str] = {
|
ENTRY_DERIVED_VARIABLES: Dict[KwargKey, str] = {
|
||||||
# UID_SANITIZED
|
v.uid_sanitized: sanitized(v.uid),
|
||||||
# UID_SANITIZED_PLEX
|
v.uid_sanitized_plex: sanitized_plex(v.uid_sanitized_plex),
|
||||||
# title_sanitized
|
v.title_sanitized: sanitized(v.title),
|
||||||
# title_sanitized_plex
|
v.title_sanitized_plex: sanitized_plex(v.title),
|
||||||
|
v.upload_date: entry_get(v.upload_date, "TODO CURRENT TIME"),
|
||||||
|
v.release_date: entry_get(v.release_date, "TODO CURRENT TIME"),
|
||||||
# epoch_date
|
# epoch_date
|
||||||
# epoch_hour
|
# epoch_hour
|
||||||
# creator
|
# creator
|
||||||
|
|
@ -86,43 +91,45 @@ ENTRY_ARCHIVE_VARIABLES: Dict[KwargKey, str] = {
|
||||||
}
|
}
|
||||||
|
|
||||||
ENTRY_UPLOAD_DATE_VARIABLES: Dict[KwargKey, str] = {
|
ENTRY_UPLOAD_DATE_VARIABLES: Dict[KwargKey, str] = {
|
||||||
# upload_date
|
v.upload_year: date_metadata(v.upload_date, "year"),
|
||||||
# upload_year
|
v.upload_year_truncated: date_metadata(v.upload_date, "year_truncated"),
|
||||||
# upload_year_truncated
|
v.upload_year_truncated_reversed: date_metadata(v.upload_date, "year_truncated_reversed"),
|
||||||
# upload_year_truncated_reversed
|
v.upload_month_reversed: date_metadata(v.upload_date, "month_reversed"),
|
||||||
# upload_month_reversed
|
v.upload_month_reversed_padded: date_metadata(v.upload_date, "month_reversed_padded"),
|
||||||
# upload_month_reversed_padded
|
v.upload_month_padded: date_metadata(v.upload_date, "month_padded"),
|
||||||
# upload_month_padded
|
v.upload_day_padded: date_metadata(v.upload_date, "day_padded"),
|
||||||
# upload_day_padded
|
v.upload_month: date_metadata(v.upload_date, "month"),
|
||||||
# upload_month
|
v.upload_day: date_metadata(v.upload_date, "day"),
|
||||||
# upload_day
|
v.upload_day_reversed: date_metadata(v.upload_date, "day_reversed"),
|
||||||
# upload_day_reversed
|
v.upload_day_reversed_padded: date_metadata(v.upload_date, "day_reversed_padded"),
|
||||||
# upload_day_reversed_padded
|
v.upload_day_of_year: date_metadata(v.upload_date, "day_of_year"),
|
||||||
# upload_day_of_year
|
v.upload_day_of_year_padded: date_metadata(v.upload_date, "day_of_year_padded"),
|
||||||
# upload_day_of_year_padded
|
v.upload_day_of_year_reversed: date_metadata(v.upload_date, "day_of_year_reversed"),
|
||||||
# upload_day_of_year_reversed
|
v.upload_day_of_year_reversed_padded: date_metadata(
|
||||||
# upload_day_of_year_reversed_padded
|
v.upload_date, "day_of_year_reversed_padded"
|
||||||
# upload_date_standardized
|
),
|
||||||
|
v.upload_date_standardized: date_metadata(v.upload_date, "date_standardized"),
|
||||||
}
|
}
|
||||||
|
|
||||||
ENTRY_RELEASE_DATE_VARIABLES: Dict[KwargKey, str] = {
|
ENTRY_RELEASE_DATE_VARIABLES: Dict[KwargKey, str] = {
|
||||||
# release_date
|
v.release_year: date_metadata(v.release_date, "year"),
|
||||||
# release_year
|
v.release_year_truncated: date_metadata(v.release_date, "year_truncated"),
|
||||||
# release_year_truncated
|
v.release_year_truncated_reversed: date_metadata(v.release_date, "year_truncated_reversed"),
|
||||||
# release_year_truncated_reversed
|
v.release_month_reversed: date_metadata(v.release_date, "month_reversed"),
|
||||||
# release_month_reversed
|
v.release_month_reversed_padded: date_metadata(v.release_date, "month_reversed_padded"),
|
||||||
# release_month_reversed_padded
|
v.release_month_padded: date_metadata(v.release_date, "month_padded"),
|
||||||
# release_month_padded
|
v.release_day_padded: date_metadata(v.release_date, "day_padded"),
|
||||||
# release_day_padded
|
v.release_month: date_metadata(v.release_date, "month"),
|
||||||
# release_month
|
v.release_day: date_metadata(v.release_date, "day"),
|
||||||
# release_day
|
v.release_day_reversed: date_metadata(v.release_date, "day_reversed"),
|
||||||
# release_day_reversed
|
v.release_day_reversed_padded: date_metadata(v.release_date, "day_reversed_padded"),
|
||||||
# release_day_reversed_padded
|
v.release_day_of_year: date_metadata(v.release_date, "day_of_year"),
|
||||||
# release_day_of_year
|
v.release_day_of_year_padded: date_metadata(v.release_date, "day_of_year_padded"),
|
||||||
# release_day_of_year_padded
|
v.release_day_of_year_reversed: date_metadata(v.release_date, "day_of_year_reversed"),
|
||||||
# release_day_of_year_reversed
|
v.release_day_of_year_reversed_padded: date_metadata(
|
||||||
# release_day_of_year_reversed_padded
|
v.release_date, "day_of_year_reversed_padded"
|
||||||
# release_date_standardized
|
),
|
||||||
|
v.release_date_standardized: date_metadata(v.release_date, "date_standardized"),
|
||||||
}
|
}
|
||||||
|
|
||||||
ENTRY_SOURCE_VARIABLES: Dict[KwargKey, str] = {
|
ENTRY_SOURCE_VARIABLES: Dict[KwargKey, str] = {
|
||||||
|
|
|
||||||
|
|
@ -85,11 +85,3 @@ class StringFunctions:
|
||||||
length=length,
|
length=length,
|
||||||
char=String("0"),
|
char=String("0"),
|
||||||
)
|
)
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def sanitize(string: String) -> String:
|
|
||||||
"""
|
|
||||||
Returns a sanitized string that is safe to use in file paths (Windows, OSX, Unix).
|
|
||||||
"""
|
|
||||||
# TODO: Move this out of script before making it a separate library
|
|
||||||
return String(sanitize_filename(string.value))
|
|
||||||
|
|
|
||||||
|
|
@ -98,15 +98,3 @@ class TestNumericFunctions:
|
||||||
def test_pad_zero(self, values: str, expected_output: str):
|
def test_pad_zero(self, values: str, expected_output: str):
|
||||||
output = single_variable_output(f"{{%pad_zero({values})}}")
|
output = single_variable_output(f"{{%pad_zero({values})}}")
|
||||||
assert output == expected_output
|
assert output == expected_output
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
|
||||||
"values, expected_output",
|
|
||||||
[
|
|
||||||
("'2012'", "2012"),
|
|
||||||
("'$?ahh'", "$?ahh"),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
def test_sanitize(self, values: str, expected_output: str):
|
|
||||||
# TODO: Move this out once it is its own library
|
|
||||||
output = single_variable_output(f"{{%sanitize({values})}}")
|
|
||||||
assert output == expected_output
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue