This commit is contained in:
Jesse Bannon 2023-12-05 00:16:00 -08:00
parent e6ee337f20
commit 98bd2df447
6 changed files with 160 additions and 145 deletions

View file

@ -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 += ""
case "1":
out += ""
case "2":
out += ""
case "3":
out += ""
case "4":
out += ""
case "5":
out += ""
case "6":
out += ""
case "7":
out += ""
case "8":
out += ""
case "9":
out += ""
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)),
}
)

View file

@ -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")

View file

@ -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
# pylint: disable=no-member
# 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:
@property
def uid(self) -> KwargKey:

View file

@ -1,8 +1,8 @@
from typing import Dict
from typing import Optional
from ytdl_sub.entries.script.kwargs import KwargKey
from ytdl_sub.entries.script.variables import Variables
from ytdl_sub.entries.script.variable_definitions import KwargKey
from ytdl_sub.entries.script.variable_definitions import Variables
ENTRY_MAP_VARIABLE = "entry"
@ -32,8 +32,11 @@ def sanitized(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
@ -62,10 +65,12 @@ ENTRY_DEFAULT_VARIABLES: Dict[KwargKey, str] = {
}
ENTRY_DERIVED_VARIABLES: Dict[KwargKey, str] = {
# UID_SANITIZED
# UID_SANITIZED_PLEX
# title_sanitized
# title_sanitized_plex
v.uid_sanitized: sanitized(v.uid),
v.uid_sanitized_plex: sanitized_plex(v.uid_sanitized_plex),
v.title_sanitized: sanitized(v.title),
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_hour
# creator
@ -86,43 +91,45 @@ ENTRY_ARCHIVE_VARIABLES: Dict[KwargKey, str] = {
}
ENTRY_UPLOAD_DATE_VARIABLES: Dict[KwargKey, str] = {
# upload_date
# upload_year
# upload_year_truncated
# upload_year_truncated_reversed
# upload_month_reversed
# upload_month_reversed_padded
# upload_month_padded
# upload_day_padded
# upload_month
# upload_day
# upload_day_reversed
# upload_day_reversed_padded
# upload_day_of_year
# upload_day_of_year_padded
# upload_day_of_year_reversed
# upload_day_of_year_reversed_padded
# upload_date_standardized
v.upload_year: date_metadata(v.upload_date, "year"),
v.upload_year_truncated: date_metadata(v.upload_date, "year_truncated"),
v.upload_year_truncated_reversed: date_metadata(v.upload_date, "year_truncated_reversed"),
v.upload_month_reversed: date_metadata(v.upload_date, "month_reversed"),
v.upload_month_reversed_padded: date_metadata(v.upload_date, "month_reversed_padded"),
v.upload_month_padded: date_metadata(v.upload_date, "month_padded"),
v.upload_day_padded: date_metadata(v.upload_date, "day_padded"),
v.upload_month: date_metadata(v.upload_date, "month"),
v.upload_day: date_metadata(v.upload_date, "day"),
v.upload_day_reversed: date_metadata(v.upload_date, "day_reversed"),
v.upload_day_reversed_padded: date_metadata(v.upload_date, "day_reversed_padded"),
v.upload_day_of_year: date_metadata(v.upload_date, "day_of_year"),
v.upload_day_of_year_padded: date_metadata(v.upload_date, "day_of_year_padded"),
v.upload_day_of_year_reversed: date_metadata(v.upload_date, "day_of_year_reversed"),
v.upload_day_of_year_reversed_padded: date_metadata(
v.upload_date, "day_of_year_reversed_padded"
),
v.upload_date_standardized: date_metadata(v.upload_date, "date_standardized"),
}
ENTRY_RELEASE_DATE_VARIABLES: Dict[KwargKey, str] = {
# release_date
# release_year
# release_year_truncated
# release_year_truncated_reversed
# release_month_reversed
# release_month_reversed_padded
# release_month_padded
# release_day_padded
# release_month
# release_day
# release_day_reversed
# release_day_reversed_padded
# release_day_of_year
# release_day_of_year_padded
# release_day_of_year_reversed
# release_day_of_year_reversed_padded
# release_date_standardized
v.release_year: date_metadata(v.release_date, "year"),
v.release_year_truncated: date_metadata(v.release_date, "year_truncated"),
v.release_year_truncated_reversed: date_metadata(v.release_date, "year_truncated_reversed"),
v.release_month_reversed: date_metadata(v.release_date, "month_reversed"),
v.release_month_reversed_padded: date_metadata(v.release_date, "month_reversed_padded"),
v.release_month_padded: date_metadata(v.release_date, "month_padded"),
v.release_day_padded: date_metadata(v.release_date, "day_padded"),
v.release_month: date_metadata(v.release_date, "month"),
v.release_day: date_metadata(v.release_date, "day"),
v.release_day_reversed: date_metadata(v.release_date, "day_reversed"),
v.release_day_reversed_padded: date_metadata(v.release_date, "day_reversed_padded"),
v.release_day_of_year: date_metadata(v.release_date, "day_of_year"),
v.release_day_of_year_padded: date_metadata(v.release_date, "day_of_year_padded"),
v.release_day_of_year_reversed: date_metadata(v.release_date, "day_of_year_reversed"),
v.release_day_of_year_reversed_padded: date_metadata(
v.release_date, "day_of_year_reversed_padded"
),
v.release_date_standardized: date_metadata(v.release_date, "date_standardized"),
}
ENTRY_SOURCE_VARIABLES: Dict[KwargKey, str] = {

View file

@ -85,11 +85,3 @@ class StringFunctions:
length=length,
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))

View file

@ -98,15 +98,3 @@ class TestNumericFunctions:
def test_pad_zero(self, values: str, expected_output: str):
output = single_variable_output(f"{{%pad_zero({values})}}")
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