[REFACTOR] Organize variable definitions (#860)

This commit is contained in:
Jesse Bannon 2023-12-29 14:39:19 -08:00 committed by GitHub
parent 189e897888
commit f2d55fdb23
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 1532 additions and 917 deletions

View file

@ -7,110 +7,163 @@ Entry Variables
channel channel
~~~~~~~ ~~~~~~~
The channel name if it exists, otherwise returns the uploader. :type: ``String``
:description:
The channel name if it exists, otherwise returns the uploader.
channel_id channel_id
~~~~~~~~~~ ~~~~~~~~~~
The channel id if it exists, otherwise returns the entry uploader ID. :type: ``String``
:description:
The channel id if it exists, otherwise returns the entry uploader ID.
chapters chapters
~~~~~~~~ ~~~~~~~~
Chapters if they exist :type: ``Array``
:description:
Chapters if they exist
comments comments
~~~~~~~~ ~~~~~~~~
Comments if they are requested :type: ``Array``
:description:
Comments if they are requested
creator creator
~~~~~~~ ~~~~~~~
The creator name if it exists, otherwise returns the channel. :type: ``String``
:description:
The creator name if it exists, otherwise returns the channel.
description description
~~~~~~~~~~~ ~~~~~~~~~~~
The description if it exists. Otherwise, returns an emtpy string. :type: ``String``
:description:
The description if it exists. Otherwise, returns an emtpy string.
duration duration
~~~~~~~~ ~~~~~~~~
The duration of the entry in seconds :type: ``Integer``
:description:
The duration of the entry in seconds if it exists. Defaults to zero otherwise.
epoch epoch
~~~~~ ~~~~~
The unix epoch of when the metadata was scraped by yt-dlp. :type: ``Integer``
:description:
The unix epoch of when the metadata was scraped by yt-dlp.
epoch_date epoch_date
~~~~~~~~~~ ~~~~~~~~~~
The epoch's date, in YYYYMMDD format. :type: ``String``
:description:
The epoch's date, in YYYYMMDD format.
epoch_hour epoch_hour
~~~~~~~~~~ ~~~~~~~~~~
The epoch's hour :type: ``String``
:description:
The epoch's hour
ext ext
~~~ ~~~
The downloaded entry's file extension :type: ``String``
:description:
The downloaded entry's file extension
extractor extractor
~~~~~~~~~ ~~~~~~~~~
The yt-dlp extractor name :type: ``String``
:description:
The yt-dlp extractor name
extractor_key extractor_key
~~~~~~~~~~~~~ ~~~~~~~~~~~~~
The yt-dlp extractor key :type: ``String``
:description:
The yt-dlp extractor key
ie_key ie_key
~~~~~~ ~~~~~~
The ie_key, used in legacy yt-dlp things as the 'info-extractor key' :type: ``String``
:description:
The ie_key, used in legacy yt-dlp things as the 'info-extractor key'.
If it does not exist, return ``extractor_key``
info_json_ext info_json_ext
~~~~~~~~~~~~~ ~~~~~~~~~~~~~
The "info.json" extension :type: ``String``
:description:
The "info.json" extension
requested_subtitles requested_subtitles
~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~
Subtitles if they are requested and exist :type: ``Map``
:description:
Subtitles if they are requested and exist
sponsorblock_chapters sponsorblock_chapters
~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~
Sponsorblock Chapters if they are requested and exist :type: ``Array``
:description:
Sponsorblock Chapters if they are requested and exist
thumbnail_ext thumbnail_ext
~~~~~~~~~~~~~ ~~~~~~~~~~~~~
The download entry's thumbnail extension. Will always return 'jpg'. Until there is a :type: ``String``
need to support other image types, we always convert to jpg. :description:
The download entry's thumbnail extension. Will always return 'jpg'. Until there is a
need to support other image types, we always convert to jpg.
title title
~~~~~ ~~~~~
The title of the entry. If a title does not exist, returns its unique ID. :type: ``String``
:description:
The title of the entry. If a title does not exist, returns its unique ID.
title_sanitized_plex title_sanitized_plex
~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~
The sanitized title with additional sanitizing for Plex. It replaces numbers with :type: ``String``
fixed-width numbers so Plex does not recognize them as season or episode numbers. :description:
The sanitized title with additional sanitizing for Plex. It replaces numbers with
fixed-width numbers so Plex does not recognize them as season or episode numbers.
uid uid
~~~ ~~~
The entry's unique ID :type: ``String``
:description:
The entry's unique ID
uid_sanitized_plex uid_sanitized_plex
~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~
The sanitized uid with additional sanitizing for Plex. Replaces numbers with :type: ``String``
fixed-width numbers so Plex does not recognize them as season or episode numbers. :description:
The sanitized uid with additional sanitizing for Plex. Replaces numbers with
fixed-width numbers so Plex does not recognize them as season or episode numbers.
uploader uploader
~~~~~~~~ ~~~~~~~~
The uploader if it exists, otherwise return the uploader ID. :type: ``String``
:description:
The uploader if it exists, otherwise return the uploader ID.
uploader_id uploader_id
~~~~~~~~~~~ ~~~~~~~~~~~
The uploader id if it exists, otherwise return the unique ID. :type: ``String``
:description:
The uploader id if it exists, otherwise return the unique ID.
uploader_url uploader_url
~~~~~~~~~~~~ ~~~~~~~~~~~~
The uploader url if it exists, otherwise returns the webpage_url. :type: ``String``
:description:
The uploader url if it exists, otherwise returns the webpage_url.
webpage_url webpage_url
~~~~~~~~~~~ ~~~~~~~~~~~
The url to the webpage. :type: ``String``
:description:
The url to the webpage.
---------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------
@ -119,19 +172,28 @@ Metadata Variables
entry_metadata entry_metadata
~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~
The entry's info.json :type: ``Map``
:description:
The entry's info.json
playlist_metadata playlist_metadata
~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~
Metadata from the playlist (i.e. the parent metadata, like playlist -> entry) :type: ``Map``
:description:
Metadata from the playlist (i.e. the parent metadata, like playlist -> entry)
sibling_metadata sibling_metadata
~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~
Metadata from any sibling entries that reside in the same playlist as this entry. :type: ``Array``
:description:
Metadata from any sibling entries that reside in the same playlist as this entry.
source_metadata source_metadata
~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~
Metadata from the source (i.e. the grandparent metadata, like channel -> playlist -> entry) :type: ``Map``
:description:
Metadata from the source
(i.e. the grandparent metadata, like channel -> playlist -> entry)
---------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------
@ -140,80 +202,114 @@ Playlist Variables
playlist_count playlist_count
~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~
Playlist count if it exists, otherwise returns ``1``. :type: ``Integer``
:description:
Playlist count if it exists, otherwise returns ``1``.
Note that for channels/playlists, any change (i.e. adding or removing a video) will make Note that for channels/playlists, any change (i.e. adding or removing a video) will make
this value change. Use with caution. this value change. Use with caution.
playlist_description playlist_description
~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~
The playlist description if it exists, otherwise returns the entry's description. :type: ``String``
:description:
The playlist description if it exists, otherwise returns the entry's description.
playlist_index playlist_index
~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~
Playlist index if it exists, otherwise returns ``1``. :type: ``Integer``
:description:
Playlist index if it exists, otherwise returns ``1``.
Note that for channels/playlists, any change (i.e. adding or removing a video) will make Note that for channels/playlists, any change (i.e. adding or removing a video) will make
this value change. Use with caution. this value change. Use with caution.
playlist_index_padded playlist_index_padded
~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~
playlist_index padded two digits :type: ``String``
:description:
playlist_index padded two digits
playlist_index_padded6 playlist_index_padded6
~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~
playlist_index padded six digits. :type: ``String``
:description:
playlist_index padded six digits.
playlist_index_reversed playlist_index_reversed
~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~
Playlist index reversed via ``playlist_count - playlist_index + 1`` :type: ``Integer``
:description:
Playlist index reversed via ``playlist_count - playlist_index + 1``
playlist_index_reversed_padded playlist_index_reversed_padded
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
playlist_index_reversed padded two digits :type: ``String``
:description:
playlist_index_reversed padded two digits
playlist_index_reversed_padded6 playlist_index_reversed_padded6
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
playlist_index_reversed padded six digits. :type: ``String``
:description:
playlist_index_reversed padded six digits.
playlist_max_upload_date playlist_max_upload_date
~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~
Max upload_date for all entries in this entry's playlist if it exists, otherwise returns :type: ``String``
``upload_date`` :description:
Max upload_date for all entries in this entry's playlist if it exists, otherwise returns
``upload_date``
playlist_max_upload_year playlist_max_upload_year
~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~
Max upload_year for all entries in this entry's playlist if it exists, otherwise returns :type: ``Integer``
``upload_year`` :description:
Max upload_year for all entries in this entry's playlist if it exists, otherwise returns
``upload_year``
playlist_max_upload_year_truncated playlist_max_upload_year_truncated
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The max playlist truncated upload year for all entries in this entry's playlist if it :type: ``Integer``
exists, otherwise returns ``upload_year_truncated``. :description:
The max playlist truncated upload year for all entries in this entry's playlist if it
exists, otherwise returns ``upload_year_truncated``.
playlist_title playlist_title
~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~
Name of its parent playlist/channel if it exists, otherwise returns its title. :type: ``String``
:description:
Name of its parent playlist/channel if it exists, otherwise returns its title.
playlist_uid playlist_uid
~~~~~~~~~~~~ ~~~~~~~~~~~~
The playlist unique ID if it exists, otherwise return the entry unique ID. :type: ``String``
:description:
The playlist unique ID if it exists, otherwise return the entry unique ID.
playlist_uploader playlist_uploader
~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~
The playlist uploader if it exists, otherwise return the entry uploader. :type: ``String``
:description:
The playlist uploader if it exists, otherwise return the entry uploader.
playlist_uploader_id playlist_uploader_id
~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~
The playlist uploader id if it exists, otherwise returns the entry uploader ID. :type: ``String``
:description:
The playlist uploader id if it exists, otherwise returns the entry uploader ID.
playlist_uploader_url playlist_uploader_url
~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~
The playlist uploader url if it exists, otherwise returns the playlist webpage_url. :type: ``String``
:description:
The playlist uploader url if it exists, otherwise returns the playlist webpage_url.
playlist_webpage_url playlist_webpage_url
~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~
The playlist webpage url if it exists. Otherwise, returns the entry webpage url. :type: ``String``
:description:
The playlist webpage url if it exists. Otherwise, returns the entry webpage url.
---------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------
@ -222,75 +318,108 @@ Release Date Variables
release_date release_date
~~~~~~~~~~~~ ~~~~~~~~~~~~
The entrys release date, in YYYYMMDD format. If not present, return the upload date. :type: ``String``
:description:
The entrys release date, in YYYYMMDD format. If not present, return the upload date.
release_date_standardized release_date_standardized
~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~
The release date formatted as YYYY-MM-DD :type: ``String``
:description:
The uploaded date formatted as YYYY-MM-DD
release_day release_day
~~~~~~~~~~~ ~~~~~~~~~~~
The release day as an integer (no padding). :type: ``Integer``
:description:
The upload day as an integer (no padding).
release_day_of_year release_day_of_year
~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~
The day of the year, i.e. February 1st returns ``32`` :type: ``Integer``
:description:
The day of the year, i.e. February 1st returns ``32``
release_day_of_year_padded release_day_of_year_padded
~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~
The release day of year, but padded i.e. February 1st returns "032" :type: ``String``
:description:
The upload day of year, but padded i.e. February 1st returns "032"
release_day_of_year_reversed release_day_of_year_reversed
~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The release day, but reversed using ``{total_days_in_year} + 1 - {release_day}``, :type: ``Integer``
i.e. February 2nd would have release_day_of_year_reversed of ``365 + 1 - 32`` = ``334`` :description:
The upload day, but reversed using ``{total_days_in_year} + 1 - {release_day}``,
i.e. February 2nd would have release_day_of_year_reversed of ``365 + 1 - 32`` = ``334``
release_day_of_year_reversed_padded release_day_of_year_reversed_padded
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The reversed release day of year, but padded i.e. December 31st returns "001" :type: ``String``
:description:
The reversed upload day of year, but padded i.e. December 31st returns "001"
release_day_padded release_day_padded
~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~
The entry's release day padded to two digits, i.e. the fifth returns "05" :type: ``String``
:description:
The entry's upload day padded to two digits, i.e. the fifth returns "05"
release_day_reversed release_day_reversed
~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~
The release day, but reversed using ``{total_days_in_month} + 1 - {release_day}``, :type: ``Integer``
i.e. August 8th would have release_day_reversed of ``31 + 1 - 8`` = ``24`` :description:
The upload day, but reversed using ``{total_days_in_month} + 1 - {release_day}``,
i.e. August 8th would have release_day_reversed of ``31 + 1 - 8`` = ``24``
release_day_reversed_padded release_day_reversed_padded
~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
The reversed release day, but padded. i.e. August 30th returns "02". :type: ``String``
:description:
The reversed upload day, but padded. i.e. August 30th returns "02".
release_month release_month
~~~~~~~~~~~~~ ~~~~~~~~~~~~~
The release month as an integer (no padding). :type: ``Integer``
:description:
The upload month as an integer (no padding).
release_month_padded release_month_padded
~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~
The entry's release month padded to two digits, i.e. March returns "03" :type: ``String``
:description:
The entry's upload month padded to two digits, i.e. March returns "03"
release_month_reversed release_month_reversed
~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~
The release month, but reversed :type: ``Integer``
using ``13 - {release_month}``, i.e. March returns ``10`` :description:
The upload month, but reversed using ``13 - {release_month}``, i.e. March returns ``10``
release_month_reversed_padded release_month_reversed_padded
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The reversed release month, but padded. i.e. November returns "02" :type: ``String``
:description:
The reversed upload month, but padded. i.e. November returns "02"
release_year release_year
~~~~~~~~~~~~ ~~~~~~~~~~~~
The entry's release year :type: ``Integer``
:description:
The entry's upload year
release_year_truncated release_year_truncated
~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~
The last two digits of the release year, i.e. 22 in 2022 :type: ``Integer``
:description:
The last two digits of the upload year, i.e. 22 in 2022
release_year_truncated_reversed release_year_truncated_reversed
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The release year truncated, but reversed using ``100 - {release_year_truncated}``, i.e. :type: ``Integer``
2022 returns ``100 - 22`` = ``78`` :description:
The upload year truncated, but reversed using ``100 - {release_year_truncated}``, i.e.
2022 returns ``100 - 22`` = ``78``
---------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------
@ -299,47 +428,67 @@ Source Variables
source_count source_count
~~~~~~~~~~~~ ~~~~~~~~~~~~
The source count if it exists, otherwise returns the playlist count. :type: ``Integer``
:description:
The source count if it exists, otherwise returns ``1``.
source_description source_description
~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~
The source description if it exists, otherwise returns the playlist description. :type: ``String``
:description:
The source description if it exists, otherwise returns the playlist description.
source_index source_index
~~~~~~~~~~~~ ~~~~~~~~~~~~
Source index if it exists, otherwise returns ``1``. :type: ``Integer``
:description:
Source index if it exists, otherwise returns ``1``.
It is recommended to not use this unless you know the source will never add new content It is recommended to not use this unless you know the source will never add new content
(it is easy for this value to change). (it is easy for this value to change).
source_index_padded source_index_padded
~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~
The source index, padded. :type: ``String``
:description:
The source index, padded two digits.
source_title source_title
~~~~~~~~~~~~ ~~~~~~~~~~~~
Name of the source (i.e. channel with multiple playlists) if it exists, otherwise :type: ``String``
returns its playlist_title. :description:
Name of the source (i.e. channel with multiple playlists) if it exists, otherwise
returns its playlist_title.
source_uid source_uid
~~~~~~~~~~ ~~~~~~~~~~
The source unique id if it exists, otherwise returns the playlist unique ID. :type: ``String``
:description:
The source unique id if it exists, otherwise returns the playlist unique ID.
source_uploader source_uploader
~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~
The source uploader if it exists, otherwise return the playlist_uploader :type: ``String``
:description:
The source uploader if it exists, otherwise return the playlist_uploader
source_uploader_id source_uploader_id
~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~
The source uploader id if it exists, otherwise returns the playlist_uploader_id :type: ``String``
:description:
The source uploader id if it exists, otherwise returns the playlist_uploader_id
source_uploader_url source_uploader_url
~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~
The source uploader url if it exists, otherwise returns the source webpage_url. :type: ``String``
:description:
The source uploader url if it exists, otherwise returns the source webpage_url.
source_webpage_url source_webpage_url
~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~
The source webpage url if it exists, otherwise returns the playlist webpage url. :type: ``String``
:description:
The source webpage url if it exists, otherwise returns the playlist webpage url.
---------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------
@ -348,74 +497,108 @@ Upload Date Variables
upload_date upload_date
~~~~~~~~~~~ ~~~~~~~~~~~
The entrys uploaded date, in YYYYMMDD format. If not present, return todays date. :type: ``String``
:description:
The entrys uploaded date, in YYYYMMDD format. If not present, return todays date.
upload_date_standardized upload_date_standardized
~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~
The uploaded date formatted as YYYY-MM-DD :type: ``String``
:description:
The uploaded date formatted as YYYY-MM-DD
upload_day upload_day
~~~~~~~~~~ ~~~~~~~~~~
The upload day as an integer (no padding). :type: ``Integer``
:description:
The upload day as an integer (no padding).
upload_day_of_year upload_day_of_year
~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~
The day of the year, i.e. February 1st returns ``32`` :type: ``Integer``
:description:
The day of the year, i.e. February 1st returns ``32``
upload_day_of_year_padded upload_day_of_year_padded
~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~
The upload day of year, but padded i.e. February 1st returns "032" :type: ``String``
:description:
The upload day of year, but padded i.e. February 1st returns "032"
upload_day_of_year_reversed upload_day_of_year_reversed
~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
The upload day, but reversed using ``{total_days_in_year} + 1 - {upload_day}``, :type: ``Integer``
i.e. February 2nd would have upload_day_of_year_reversed of ``365 + 1 - 32`` = ``334`` :description:
The upload day, but reversed using ``{total_days_in_year} + 1 - {upload_day}``,
i.e. February 2nd would have upload_day_of_year_reversed of ``365 + 1 - 32`` = ``334``
upload_day_of_year_reversed_padded upload_day_of_year_reversed_padded
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The reversed upload day of year, but padded i.e. December 31st returns "001" :type: ``String``
:description:
The reversed upload day of year, but padded i.e. December 31st returns "001"
upload_day_padded upload_day_padded
~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~
The entry's upload day padded to two digits, i.e. the fifth returns "05" :type: ``String``
:description:
The entry's upload day padded to two digits, i.e. the fifth returns "05"
upload_day_reversed upload_day_reversed
~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~
The upload day, but reversed using ``{total_days_in_month} + 1 - {upload_day}``, :type: ``Integer``
i.e. August 8th would have upload_day_reversed of ``31 + 1 - 8`` = ``24`` :description:
The upload day, but reversed using ``{total_days_in_month} + 1 - {upload_day}``,
i.e. August 8th would have upload_day_reversed of ``31 + 1 - 8`` = ``24``
upload_day_reversed_padded upload_day_reversed_padded
~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~
The reversed upload day, but padded. i.e. August 30th returns "02". :type: ``String``
:description:
The reversed upload day, but padded. i.e. August 30th returns "02".
upload_month upload_month
~~~~~~~~~~~~ ~~~~~~~~~~~~
The upload month as an integer (no padding). :type: ``Integer``
:description:
The upload month as an integer (no padding).
upload_month_padded upload_month_padded
~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~
The entry's upload month padded to two digits, i.e. March returns "03" :type: ``String``
:description:
The entry's upload month padded to two digits, i.e. March returns "03"
upload_month_reversed upload_month_reversed
~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~
The upload month, but reversed using ``13 - {upload_month}``, i.e. March returns ``10`` :type: ``Integer``
:description:
The upload month, but reversed using ``13 - {upload_month}``, i.e. March returns ``10``
upload_month_reversed_padded upload_month_reversed_padded
~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The reversed upload month, but padded. i.e. November returns "02" :type: ``String``
:description:
The reversed upload month, but padded. i.e. November returns "02"
upload_year upload_year
~~~~~~~~~~~ ~~~~~~~~~~~
The entry's upload year :type: ``Integer``
:description:
The entry's upload year
upload_year_truncated upload_year_truncated
~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~
The last two digits of the upload year, i.e. 22 in 2022 :type: ``Integer``
:description:
The last two digits of the upload year, i.e. 22 in 2022
upload_year_truncated_reversed upload_year_truncated_reversed
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The upload year truncated, but reversed using ``100 - {upload_year_truncated}``, i.e. :type: ``Integer``
2022 returns ``100 - 22`` = ``78`` :description:
The upload year truncated, but reversed using ``100 - {upload_year_truncated}``, i.e.
2022 returns ``100 - 22`` = ``78``
---------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------
@ -424,29 +607,43 @@ Ytdl-Sub Variables
download_index download_index
~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~
The i'th entry downloaded. NOTE that this is fetched dynamically from the download :type: ``Integer``
archive. :description:
The i'th entry downloaded. NOTE that this is fetched dynamically from the download
archive.
download_index_padded6 download_index_padded6
~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~
The download_index padded six digits :type: ``String``
:description:
The download_index padded six digits
upload_date_index upload_date_index
~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~
The i'th entry downloaded with this upload date. :type: ``Integer``
:description:
The i'th entry downloaded with this upload date.
upload_date_index_padded upload_date_index_padded
~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~
The upload_date_index padded two digits :type: ``String``
:description:
The upload_date_index padded two digits
upload_date_index_reversed upload_date_index_reversed
~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~
100 - upload_date_index :type: ``Integer``
:description:
100 - upload_date_index
upload_date_index_reversed_padded upload_date_index_reversed_padded
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The upload_date_index padded two digits :type: ``String``
:description:
The upload_date_index padded two digits
ytdl_sub_input_url ytdl_sub_input_url
~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~
The input URL used in ytdl-sub to create this entry. :type: ``String``
:description:
The input URL used in ytdl-sub to create this entry.

View file

@ -603,7 +603,7 @@ Takes a date in the form of YYYYMMDD and returns a Map containing:
- year (Integer) - year (Integer)
- month (Integer) - month (Integer)
- day (Integer) - day (Integer)
- year_truncated (String, YY from YY[YY]) - year_truncated (Integer, YY from YY[YY])
- month_padded (String) - month_padded (String)
- day_padded (String) - day_padded (String)
- year_truncated_reversed (Integer, 100 - year_truncated) - year_truncated_reversed (Integer, 100 - year_truncated)

View file

@ -13,7 +13,7 @@ from ytdl_sub.config.plugin.preset_plugins import PresetPlugins
from ytdl_sub.config.preset_options import OutputOptions from ytdl_sub.config.preset_options import OutputOptions
from ytdl_sub.config.validators.options import OptionsValidator from ytdl_sub.config.validators.options import OptionsValidator
from ytdl_sub.downloaders.url.validators import MultiUrlValidator from ytdl_sub.downloaders.url.validators import MultiUrlValidator
from ytdl_sub.entries.script.variable_scripts import VARIABLE_SCRIPTS from ytdl_sub.entries.script.variable_definitions import VARIABLE_SCRIPTS
from ytdl_sub.script.script import Script from ytdl_sub.script.script import Script
from ytdl_sub.validators.string_formatter_validators import validate_formatters from ytdl_sub.validators.string_formatter_validators import validate_formatters

View file

@ -11,10 +11,9 @@ from ytdl_sub.config.validators.options import OptionsDictValidator
from ytdl_sub.downloaders.source_plugin import SourcePlugin from ytdl_sub.downloaders.source_plugin import SourcePlugin
from ytdl_sub.downloaders.ytdl_options_builder import YTDLOptionsBuilder from ytdl_sub.downloaders.ytdl_options_builder import YTDLOptionsBuilder
from ytdl_sub.entries.entry import Entry from ytdl_sub.entries.entry import Entry
from ytdl_sub.entries.script.variable_definitions import VARIABLE_SCRIPTS
from ytdl_sub.entries.script.variable_definitions import VARIABLES from ytdl_sub.entries.script.variable_definitions import VARIABLES
from ytdl_sub.entries.script.variable_definitions import VariableDefinitions from ytdl_sub.entries.script.variable_definitions import VariableDefinitions
from ytdl_sub.entries.script.variable_scripts import DOWNLOADER_INJECTED_VARIABLES
from ytdl_sub.entries.script.variable_scripts import VARIABLE_SCRIPTS
from ytdl_sub.utils.exceptions import ValidationException from ytdl_sub.utils.exceptions import ValidationException
from ytdl_sub.utils.file_handler import FileHandler from ytdl_sub.utils.file_handler import FileHandler
from ytdl_sub.utils.file_handler import get_file_extension from ytdl_sub.utils.file_handler import get_file_extension
@ -114,7 +113,7 @@ class InfoJsonDownloader(SourcePlugin[InfoJsonDownloaderOptions]):
inj.variable_name, inj.variable_name,
VARIABLE_SCRIPTS[inj.variable_name], VARIABLE_SCRIPTS[inj.variable_name],
) )
for inj in DOWNLOADER_INJECTED_VARIABLES for inj in v.injected_variables()
} }
) )
entries.append(entry) entries.append(entry)

View file

@ -12,8 +12,10 @@ from typing import final
from ytdl_sub.entries.base_entry import BaseEntry from ytdl_sub.entries.base_entry import BaseEntry
from ytdl_sub.entries.script.variable_definitions import VARIABLES from ytdl_sub.entries.script.variable_definitions import VARIABLES
from ytdl_sub.entries.script.variable_definitions import Variable
from ytdl_sub.entries.script.variable_definitions import VariableDefinitions from ytdl_sub.entries.script.variable_definitions import VariableDefinitions
from ytdl_sub.entries.script.variable_types import ArrayVariable
from ytdl_sub.entries.script.variable_types import StringVariable
from ytdl_sub.entries.script.variable_types import Variable
from ytdl_sub.script.utils.exceptions import ScriptVariableNotResolved from ytdl_sub.script.utils.exceptions import ScriptVariableNotResolved
from ytdl_sub.utils.script import ScriptUtils from ytdl_sub.utils.script import ScriptUtils
from ytdl_sub.utils.scriptable import Scriptable from ytdl_sub.utils.scriptable import Scriptable
@ -23,8 +25,12 @@ from ytdl_sub.validators.audo_codec_validator import VIDEO_CODEC_EXTS
v: VariableDefinitions = VARIABLES v: VariableDefinitions = VARIABLES
_YTDL_SUB_ENTRY_VARIABLES_KWARG_KEY: str = "ytdl_sub_entry_variables" _YTDL_SUB_ENTRY_VARIABLES_KWARG_KEY: str = "ytdl_sub_entry_variables"
ytdl_sub_chapters_from_comments = Variable("ytdl_sub_chapters_from_comments") ytdl_sub_chapters_from_comments = ArrayVariable(
ytdl_sub_split_by_chapters_parent_uid = Variable("ytdl_sub_split_by_chapters_parent_uid") "ytdl_sub_chapters_from_comments", definition="{ [] }"
)
ytdl_sub_split_by_chapters_parent_uid = StringVariable(
"ytdl_sub_split_by_chapters_parent_uid", definition="{ %string('') }"
)
TypeT = TypeVar("TypeT") TypeT = TypeVar("TypeT")

View file

@ -3,15 +3,14 @@ from typing import Any
from typing import Dict from typing import Dict
from typing import List from typing import List
from typing import Optional from typing import Optional
from typing import Set
from ytdl_sub.entries.base_entry import BaseEntry from ytdl_sub.entries.base_entry import BaseEntry
from ytdl_sub.entries.base_entry import TBaseEntry from ytdl_sub.entries.base_entry import TBaseEntry
from ytdl_sub.entries.entry import Entry from ytdl_sub.entries.entry import Entry
from ytdl_sub.entries.script.variable_definitions import VARIABLES from ytdl_sub.entries.script.variable_definitions import VARIABLES
from ytdl_sub.entries.script.variable_definitions import MetadataVariable
from ytdl_sub.entries.script.variable_definitions import VariableDefinitions from ytdl_sub.entries.script.variable_definitions import VariableDefinitions
from ytdl_sub.entries.script.variable_scripts import ENTRY_DEFAULT_VARIABLES from ytdl_sub.entries.script.variable_types import MetadataVariable
from ytdl_sub.entries.script.variable_scripts import ENTRY_REQUIRED_VARIABLES
v: VariableDefinitions = VARIABLES v: VariableDefinitions = VARIABLES
@ -53,8 +52,8 @@ class EntryParent(BaseEntry):
def _sibling_entry_metadata(self) -> List[Dict[str, Any]]: def _sibling_entry_metadata(self) -> List[Dict[str, Any]]:
sibling_entry_metadata: List[Dict[str, Any]] = [] sibling_entry_metadata: List[Dict[str, Any]] = []
variable_filter: List[MetadataVariable] = list(ENTRY_REQUIRED_VARIABLES.keys()) + list( variable_filter: Set[MetadataVariable] = (
ENTRY_DEFAULT_VARIABLES.keys() v.required_entry_variables() | v.default_entry_variables()
) )
for entry in self.entry_children(): for entry in self.entry_children():
sibling_entry_metadata.append( sibling_entry_metadata.append(

View file

@ -101,7 +101,7 @@ class CustomFunctions:
- year (Integer) - year (Integer)
- month (Integer) - month (Integer)
- day (Integer) - day (Integer)
- year_truncated (String, YY from YY[YY]) - year_truncated (Integer, YY from YY[YY])
- month_padded (String) - month_padded (String)
- day_padded (String) - day_padded (String)
- year_truncated_reversed (Integer, 100 - year_truncated) - year_truncated_reversed (Integer, 100 - year_truncated)
@ -149,7 +149,7 @@ class CustomFunctions:
String("year"): Integer(year), String("year"): Integer(year),
String("month"): Integer(month), String("month"): Integer(month),
String("day"): Integer(day), String("day"): Integer(day),
String("year_truncated"): String(year_truncated), String("year_truncated"): Integer(year_truncated),
String("month_padded"): String(month_padded), String("month_padded"): String(month_padded),
String("day_padded"): String(day_padded), String("day_padded"): String(day_padded),
String("year_truncated_reversed"): Integer(100 - year_truncated), String("year_truncated_reversed"): Integer(100 - year_truncated),

File diff suppressed because it is too large Load diff

View file

@ -1,296 +0,0 @@
from typing import Dict
from typing import List
from typing import Optional
from typing import Set
import mergedeep
from ytdl_sub.entries.script.custom_functions import CustomFunctions
from ytdl_sub.entries.script.variable_definitions import VARIABLES
from ytdl_sub.entries.script.variable_definitions import Metadata
from ytdl_sub.entries.script.variable_definitions import MetadataVariable
from ytdl_sub.entries.script.variable_definitions import Variable
from ytdl_sub.entries.script.variable_definitions import VariableDefinitions
###############################################################################################
# Helpers
v: VariableDefinitions = VARIABLES
def _pad_int(key: Variable, pad: int) -> str:
return f"{{%pad_zero({key.variable_name}, {pad})}}"
def _sanitized_plex(key: Variable) -> str:
return f"{{%sanitize_plex_episode({key.variable_name})}}"
def _date_metadata(date_key: Variable, metadata_key: str) -> str:
return f"{{%map_get(%to_date_metadata({date_key.variable_name}), '{metadata_key}')}}"
###############################################################################################
# Metadata Getters
def _get(
cast: str,
metadata: Metadata,
key: MetadataVariable,
default: Optional[Variable | str | int | Dict | List],
) -> str:
if default is None:
# TODO: assert with good error message if key DNE
out = f"%map_get({metadata.variable_name}, '{key.metadata_key}')"
elif isinstance(default, Variable):
args = f"{metadata.variable_name}, '{key.metadata_key}', {default.variable_name}"
out = f"%map_get_non_empty({args})"
elif isinstance(default, str):
out = f"%map_get_non_empty({metadata.variable_name}, '{key.metadata_key}', '{default}')"
elif isinstance(default, dict):
out = f"%map_get_non_empty({metadata.variable_name}, '{key.metadata_key}', {{}})"
elif isinstance(default, list):
out = f"%map_get_non_empty({metadata.variable_name}, '{key.metadata_key}', [])"
else:
out = f"%map_get_non_empty({metadata.variable_name}, '{key.metadata_key}', {default})"
return f"{{ %legacy_bracket_safety(%{cast}({out})) }}"
###############################################################################################
# Entry Getters
def _entry_get_str(key: MetadataVariable, default: Optional[Variable | str] = None) -> str:
return _get("string", metadata=v.entry_metadata, key=key, default=default)
def _entry_get_int(key: MetadataVariable, default: Optional[Variable | int] = None) -> str:
return _get("int", metadata=v.entry_metadata, key=key, default=default)
def _entry_get_map(key: MetadataVariable, default: Optional[Variable | Dict] = None):
return _get("map", metadata=v.entry_metadata, key=key, default=default)
def _entry_get_array(key: MetadataVariable, default: Optional[Variable | List] = None):
return _get("array", metadata=v.entry_metadata, key=key, default=default)
###############################################################################################
# Playlist Getters
def _playlist_get_str(key: MetadataVariable, default: Optional[Variable | str] = None) -> str:
return _get("string", metadata=v.playlist_metadata, key=key, default=default)
def _playlist_get_int(key: MetadataVariable, default: Optional[Variable | int] = None) -> str:
return _get("int", metadata=v.playlist_metadata, key=key, default=default)
###############################################################################################
# Source Getters
def _source_get_str(key: MetadataVariable, default: Optional[Variable | str] = None) -> str:
return _get("string", metadata=v.source_metadata, key=key, default=default)
###############################################################################################
# Scripts
ENTRY_EMPTY_METADATA: Dict[Variable, str] = {v.entry_metadata: "{ {} }"}
ENTRY_HARDCODED_VARIABLES: Dict[Variable, str] = {
v.info_json_ext: "info.json",
v.thumbnail_ext: "jpg",
}
ENTRY_RELATIVE_VARIABLES: Dict[MetadataVariable, str] = {
v.playlist_metadata: _entry_get_map(v.playlist_metadata, {}),
v.source_metadata: _entry_get_map(v.source_metadata, {}),
v.sibling_metadata: _entry_get_array(v.sibling_metadata, []),
}
ENTRY_REQUIRED_VARIABLES: Dict[MetadataVariable, str] = {
v.uid: _entry_get_str(v.uid),
v.extractor_key: _entry_get_str(v.extractor_key),
v.epoch: _entry_get_int(v.epoch),
v.webpage_url: _entry_get_str(v.webpage_url),
v.ext: _entry_get_str(v.ext),
}
ENTRY_DEFAULT_VARIABLES: Dict[MetadataVariable, str] = {
v.title: _entry_get_str(v.title, v.uid),
v.extractor: _entry_get_str(v.extractor, v.extractor_key),
v.description: _entry_get_str(v.description, ""),
v.ie_key: _entry_get_str(v.ie_key, v.extractor_key),
v.uploader_id: _entry_get_str(v.uploader_id, v.uid),
v.uploader: _entry_get_str(v.uploader, v.uploader_id),
v.uploader_url: _entry_get_str(v.uploader_url, v.webpage_url),
v.upload_date: _entry_get_str(v.upload_date, v.epoch_date),
v.release_date: _entry_get_str(v.release_date, v.upload_date),
v.channel: _entry_get_str(v.channel, v.uploader),
v.creator: _entry_get_str(v.creator, v.channel),
v.channel_id: _entry_get_str(v.channel_id, v.uploader_id),
v.duration: _entry_get_int(v.duration, 0),
v.playlist_index: _entry_get_int(v.playlist_index, 1),
v.playlist_count: _entry_get_int(v.playlist_count, 1),
v.playlist_uid: _entry_get_str(v.playlist_uid, v.uid),
v.playlist_title: _entry_get_str(v.playlist_title, v.title),
v.playlist_uploader_id: _entry_get_str(v.playlist_uploader_id, v.uploader_id),
}
# MARK AS UNRESOLVABLE UNTIL THEY ARE ADDED IN THE DOWNLOADER
DOWNLOADER_INJECTED_VARIABLES: Dict[Variable, str] = {
v.download_index: "{%int(1)}",
v.upload_date_index: "{%int(1)}",
v.comments: "{ [] }",
v.requested_subtitles: "{ {} }",
v.chapters: "{ [] }",
v.sponsorblock_chapters: "{ [] }",
v.ytdl_sub_input_url: f"{{{v.source_webpage_url.variable_name}}}",
}
ENTRY_DERIVED_VARIABLES: Dict[Variable, str] = {
v.uid_sanitized_plex: _sanitized_plex(v.uid),
v.title_sanitized_plex: _sanitized_plex(v.title),
v.epoch_date: f"{{%datetime_strftime({v.epoch.variable_name}, '%Y%m%d')}}",
v.epoch_hour: f"{{%datetime_strftime({v.epoch.variable_name}, '%H')}}",
v.download_index_padded6: _pad_int(v.download_index, 6),
v.upload_date_index_padded: _pad_int(v.upload_date_index, 2),
v.upload_date_index_reversed: f"{{%sub(100, {v.upload_date_index.variable_name})}}",
v.upload_date_index_reversed_padded: _pad_int(v.upload_date_index_reversed, 2),
v.playlist_index_reversed: (
f"{{%sub({v.playlist_count.variable_name}, {v.playlist_index.variable_name}, -1)}}"
),
v.playlist_index_padded: _pad_int(v.playlist_index, 2),
v.playlist_index_reversed_padded: _pad_int(v.playlist_index_reversed, 2),
v.playlist_index_padded6: _pad_int(v.playlist_index, 6),
v.playlist_index_reversed_padded6: _pad_int(v.playlist_index_reversed, 6),
}
ENTRY_UPLOAD_DATE_VARIABLES: Dict[Variable, str] = {
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[Variable, str] = {
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"),
}
PLAYLIST_VARIABLES: Dict[Variable, str] = {
v.playlist_webpage_url: _playlist_get_str(v.playlist_webpage_url, v.webpage_url),
v.playlist_description: _playlist_get_str(v.playlist_description, v.description),
v.playlist_uploader: _playlist_get_str(v.playlist_uploader, v.uploader),
v.playlist_uploader_url: _playlist_get_str(v.playlist_uploader_url, v.playlist_webpage_url),
v.source_index: _playlist_get_int(v.source_index, 1),
v.source_count: _playlist_get_int(v.source_count, 1),
}
SOURCE_VARIABLES: Dict[Variable, str] = {
v.source_uid: _source_get_str(v.source_uid, v.playlist_uid),
v.source_title: _source_get_str(v.source_title, v.playlist_title),
v.source_webpage_url: _source_get_str(v.source_webpage_url, v.playlist_webpage_url),
v.source_description: _source_get_str(v.source_description, v.playlist_description),
v.source_uploader_id: _source_get_str(v.source_uploader_id, v.playlist_uploader_id),
v.source_uploader: _source_get_str(v.source_uploader, v.playlist_uploader),
v.source_uploader_url: _source_get_str(v.source_uploader_url, v.source_webpage_url),
}
SOURCE_DERIVED_VARIABLES: Dict[Variable, str] = {
v.source_index_padded: _pad_int(v.source_index, 2),
}
SIBLING_VARIABLES: Dict[Variable, str] = {
v.playlist_max_upload_date: f"""{{
%array_reduce(
%if_passthrough(
%extract_field_from_siblings('{v.upload_date.variable_name}'),
[{v.upload_date.variable_name}]
),
%max
)
}}"""
}
SIBLING_DERIVED_VARIABLES: Dict[Variable, str] = {
v.playlist_max_upload_year: _date_metadata(v.playlist_max_upload_date, "year"),
v.playlist_max_upload_year_truncated: _date_metadata(
v.playlist_max_upload_date, "year_truncated"
),
}
_VARIABLE_SCRIPTS: Dict[Variable, str] = {}
mergedeep.merge(
_VARIABLE_SCRIPTS,
ENTRY_EMPTY_METADATA,
ENTRY_HARDCODED_VARIABLES,
ENTRY_RELATIVE_VARIABLES,
ENTRY_REQUIRED_VARIABLES,
ENTRY_DEFAULT_VARIABLES,
DOWNLOADER_INJECTED_VARIABLES,
ENTRY_DERIVED_VARIABLES,
ENTRY_UPLOAD_DATE_VARIABLES,
ENTRY_RELEASE_DATE_VARIABLES,
SIBLING_VARIABLES,
SIBLING_DERIVED_VARIABLES,
PLAYLIST_VARIABLES,
SOURCE_VARIABLES,
SOURCE_DERIVED_VARIABLES,
)
VARIABLE_SCRIPTS: Dict[str, str] = {
var.variable_name: script for var, script in _VARIABLE_SCRIPTS.items()
}
def _keys(*variables: Dict[Variable, str]) -> Set[str]:
keys: Set[str] = set()
for variable_set in variables:
keys.update(set(var.variable_name for var in variable_set.keys()))
return keys
UNRESOLVED_VARIABLES: Set[str] = _keys(
ENTRY_EMPTY_METADATA,
DOWNLOADER_INJECTED_VARIABLES,
)
CustomFunctions.register()

View file

@ -0,0 +1,321 @@
from abc import ABC
from abc import abstractmethod
from dataclasses import dataclass
from typing import Dict
from typing import List
from typing import Optional
from typing import Type
from typing import TypeVar
from ytdl_sub.script.types.array import Array
from ytdl_sub.script.types.map import Map
from ytdl_sub.script.types.resolvable import Integer
from ytdl_sub.script.types.resolvable import String
ENTRY_METADATA_VARIABLE_NAME = "entry_metadata"
PLAYLIST_METADATA_VARIABLE_NAME = "playlist_metadata"
SOURCE_METADATA_VARIABLE_NAME = "source_metadata"
TMetadataVariable = TypeVar("TMetadataVariable", bound="MetadataVariable")
TVariable = TypeVar("TVariable", bound="Variable")
def _get(
cast: str,
metadata_variable_name: str,
metadata_key: str,
variable_name: Optional[str],
default: Optional[TVariable | str | int | Dict | List],
as_type: Type[TMetadataVariable],
) -> TMetadataVariable:
if default is None:
# TODO: assert with good error message if key DNE
out = f"%map_get({metadata_variable_name}, '{metadata_key}')"
elif isinstance(default, Variable):
args = f"{metadata_variable_name}, '{metadata_key}', {default.variable_name}"
out = f"%map_get_non_empty({args})"
elif isinstance(default, str):
out = f"%map_get_non_empty({metadata_variable_name}, '{metadata_key}', '{default}')"
elif isinstance(default, dict):
out = f"%map_get_non_empty({metadata_variable_name}, '{metadata_key}', {{}})"
elif isinstance(default, list):
out = f"%map_get_non_empty({metadata_variable_name}, '{metadata_key}', [])"
else:
out = f"%map_get_non_empty({metadata_variable_name}, '{metadata_key}', {default})"
return as_type(
variable_name=variable_name or metadata_key,
metadata_key=metadata_key,
definition=f"{{ %legacy_bracket_safety(%{cast}({out})) }}",
)
@dataclass(frozen=True)
class Variable(ABC):
variable_name: str
definition: str
@classmethod
@abstractmethod
def human_readable_type(cls) -> str:
"""
Script type of the variable, for documentation
"""
@dataclass(frozen=True)
class StringVariable(Variable):
@classmethod
def human_readable_type(cls) -> str:
return String.__name__
def to_sanitized_plex(self, variable_name: str) -> "StringVariable":
"""
Converts a String variable to be plex sanitized
"""
return StringVariable(
variable_name=variable_name,
definition=f"{{%sanitize_plex_episode({self.variable_name})}}",
)
def as_date_variable(self) -> "StringDateVariable":
"""
Converts a String variable to a date variable (which has metadata helpers)
"""
return StringDateVariable(
variable_name=self.variable_name,
definition=self.definition,
)
@dataclass(frozen=True)
class StringDateVariable(StringVariable):
def get_string_date_metadata(
self, date_metadata_key: str, variable_name: Optional[str] = None
) -> StringVariable:
"""
Gets a string-based date metadata variable
"""
return StringVariable(
variable_name=variable_name or date_metadata_key,
definition=f"""{{
%string(
%map_get(
%to_date_metadata({self.variable_name}),
'{date_metadata_key}'
)
)
}}""",
)
def get_integer_date_metadata(
self, date_metadata_key: str, variable_name: str
) -> "IntegerVariable":
"""
Gets an int-based date metadata variable
"""
return IntegerVariable(
variable_name=variable_name,
definition=f"""{{
%int(
%map_get(
%to_date_metadata({self.variable_name}),
'{date_metadata_key}'
)
)
}}""",
)
@dataclass(frozen=True)
class IntegerVariable(Variable):
@classmethod
def human_readable_type(cls) -> str:
return Integer.__name__
def to_padded_int(self, variable_name: str, pad: int) -> StringVariable:
"""
Pads an integer
"""
return StringVariable(
variable_name=variable_name, definition=f"{{%pad_zero({self.variable_name}, {pad})}}"
)
@dataclass(frozen=True)
class ArrayVariable(Variable):
@classmethod
def human_readable_type(cls) -> str:
return Array.__name__
@dataclass(frozen=True)
class MapVariable(Variable):
@classmethod
def human_readable_type(cls) -> str:
return Map.__name__
@dataclass(frozen=True)
class MetadataVariable(Variable, ABC):
metadata_key: str
@dataclass(frozen=True)
class MapMetadataVariable(MetadataVariable, MapVariable):
@classmethod
def from_entry(
cls,
metadata_key: str,
variable_name: Optional[str] = None,
default: Optional["MapMetadataVariable" | Dict] = None,
) -> "MapMetadataVariable":
"""
Creates a map variable from entry metadata
"""
return _get(
"map",
metadata_variable_name=ENTRY_METADATA_VARIABLE_NAME,
metadata_key=metadata_key,
variable_name=variable_name,
default=default,
as_type=MapMetadataVariable,
)
@dataclass(frozen=True)
class ArrayMetadataVariable(MetadataVariable, ArrayVariable):
@classmethod
def from_entry(
cls,
metadata_key: str,
variable_name: Optional[str] = None,
default: Optional["ArrayMetadataVariable" | List] = None,
) -> "ArrayMetadataVariable":
"""
Creates an array variable from entry metadata
"""
return _get(
"array",
metadata_variable_name=ENTRY_METADATA_VARIABLE_NAME,
metadata_key=metadata_key,
variable_name=variable_name,
default=default,
as_type=ArrayMetadataVariable,
)
@dataclass(frozen=True)
class StringMetadataVariable(MetadataVariable, StringVariable):
@classmethod
def from_entry(
cls,
metadata_key: str,
variable_name: Optional[str] = None,
default: Optional[StringVariable | str] = None,
) -> "StringMetadataVariable":
"""
Creates a string variable from entry metadata
"""
return _get(
"string",
metadata_variable_name=ENTRY_METADATA_VARIABLE_NAME,
metadata_key=metadata_key,
variable_name=variable_name,
default=default,
as_type=StringMetadataVariable,
)
@classmethod
def from_playlist(
cls,
metadata_key: str,
variable_name: Optional[str] = None,
default: Optional[StringVariable | str] = None,
) -> "StringMetadataVariable":
"""
Creates a string variable from playlist metadata
"""
return _get(
"string",
metadata_variable_name=PLAYLIST_METADATA_VARIABLE_NAME,
metadata_key=metadata_key,
variable_name=variable_name,
default=default,
as_type=StringMetadataVariable,
)
@classmethod
def from_source(
cls,
metadata_key: str,
variable_name: Optional[str] = None,
default: Optional[StringVariable | str] = None,
) -> "StringMetadataVariable":
"""
Creates a string variable from source metadata
"""
return _get(
"string",
metadata_variable_name=SOURCE_METADATA_VARIABLE_NAME,
metadata_key=metadata_key,
variable_name=variable_name,
default=default,
as_type=StringMetadataVariable,
)
def as_date_variable(self) -> "StringDateMetadataVariable":
"""
Converts a String variable to a date variable (which has metadata helpers)
"""
return StringDateMetadataVariable(
metadata_key=self.metadata_key,
variable_name=self.variable_name,
definition=self.definition,
)
@dataclass(frozen=True)
class StringDateMetadataVariable(StringMetadataVariable, StringDateVariable):
pass
@dataclass(frozen=True)
class IntegerMetadataVariable(MetadataVariable, IntegerVariable):
@classmethod
def from_entry(
cls,
metadata_key: str,
variable_name: Optional[str] = None,
default: Optional[IntegerVariable | int] = None,
) -> "IntegerMetadataVariable":
"""
Creates an int variable from entry metadata
"""
return _get(
"int",
metadata_variable_name=ENTRY_METADATA_VARIABLE_NAME,
metadata_key=metadata_key,
variable_name=variable_name,
default=default,
as_type=IntegerMetadataVariable,
)
@classmethod
def from_playlist(
cls,
metadata_key: str,
variable_name: Optional[str] = None,
default: Optional[IntegerVariable | int] = None,
) -> "IntegerMetadataVariable":
"""
Creates an int variable from playlist metadata
"""
return _get(
"int",
metadata_variable_name=PLAYLIST_METADATA_VARIABLE_NAME,
metadata_key=metadata_key,
variable_name=variable_name,
default=default,
as_type=IntegerMetadataVariable,
)

View file

@ -1,5 +1,5 @@
from ytdl_sub.entries.script.function_scripts import CUSTOM_FUNCTION_SCRIPTS from ytdl_sub.entries.script.function_scripts import CUSTOM_FUNCTION_SCRIPTS
from ytdl_sub.entries.script.variable_scripts import VARIABLE_SCRIPTS from ytdl_sub.entries.script.variable_definitions import VARIABLE_SCRIPTS
from ytdl_sub.script.functions import Functions from ytdl_sub.script.functions import Functions
from ytdl_sub.script.utils.name_validation import is_valid_name from ytdl_sub.script.utils.name_validation import is_valid_name

View file

@ -5,9 +5,9 @@ from typing import Dict
from typing import Set from typing import Set
from ytdl_sub.entries.script.function_scripts import CUSTOM_FUNCTION_SCRIPTS from ytdl_sub.entries.script.function_scripts import CUSTOM_FUNCTION_SCRIPTS
from ytdl_sub.entries.script.variable_definitions import Variable from ytdl_sub.entries.script.variable_definitions import UNRESOLVED_VARIABLES
from ytdl_sub.entries.script.variable_scripts import UNRESOLVED_VARIABLES from ytdl_sub.entries.script.variable_definitions import VARIABLE_SCRIPTS
from ytdl_sub.entries.script.variable_scripts import VARIABLE_SCRIPTS from ytdl_sub.entries.script.variable_types import Variable
from ytdl_sub.script.script import Script from ytdl_sub.script.script import Script
from ytdl_sub.script.utils.exceptions import RuntimeException from ytdl_sub.script.utils.exceptions import RuntimeException
from ytdl_sub.utils.exceptions import StringFormattingException from ytdl_sub.utils.exceptions import StringFormattingException

View file

@ -4,11 +4,12 @@ from typing import Dict
from typing import Type from typing import Type
from tools.docgen.docgen import DocGen from tools.docgen.docgen import DocGen
from tools.docgen.utils import cached_properties
from tools.docgen.utils import camel_case_to_human from tools.docgen.utils import camel_case_to_human
from tools.docgen.utils import get_function_docs from tools.docgen.utils import get_function_docs
from tools.docgen.utils import line_section from tools.docgen.utils import line_section
from tools.docgen.utils import properties
from tools.docgen.utils import section from tools.docgen.utils import section
from ytdl_sub.entries.script.variable_definitions import VARIABLES
from ytdl_sub.entries.script.variable_definitions import VariableDefinitions from ytdl_sub.entries.script.variable_definitions import VariableDefinitions
@ -37,10 +38,11 @@ class EntryVariablesDocGen(DocGen):
docs += line_section(section_idx=idx) docs += line_section(section_idx=idx)
docs += section(name, level=1) docs += section(name, level=1)
for variable_function_name in properties(parent_objs[name]): for variable_function_name in cached_properties(parent_objs[name]):
docs += get_function_docs( docs += get_function_docs(
function_name=variable_function_name, function_name=variable_function_name,
obj=parent_objs[name], obj=parent_objs[name],
pre_docstring=f":type: ``{getattr(VARIABLES, variable_function_name).human_readable_type()}``\n",
level=2, level=2,
) )

View file

@ -1,4 +1,5 @@
import inspect import inspect
from functools import cached_property
from typing import Any from typing import Any
from typing import Dict from typing import Dict
from typing import List from typing import List
@ -18,6 +19,10 @@ def properties(obj: Type[Any]) -> List[str]:
return sorted(prop for prop in dir(obj) if isinstance(getattr(obj, prop), property)) return sorted(prop for prop in dir(obj) if isinstance(getattr(obj, prop), property))
def cached_properties(obj: Type[Any]) -> List[str]:
return sorted(prop for prop in dir(obj) if isinstance(getattr(obj, prop), cached_property))
def static_methods(obj: Type[Any]) -> List[str]: def static_methods(obj: Type[Any]) -> List[str]:
return sorted( return sorted(
name for name in dir(obj) if isinstance(inspect.getattr_static(obj, name), staticmethod) name for name in dir(obj) if isinstance(inspect.getattr_static(obj, name), staticmethod)
@ -36,11 +41,16 @@ def camel_case_to_human(string: str) -> str:
def get_function_docs( def get_function_docs(
function_name: str, obj: Any, level: int, display_function_name: Optional[str] = None function_name: str,
obj: Any,
level: int,
display_function_name: Optional[str] = None,
pre_docstring: Optional[str] = None,
) -> str: ) -> str:
display_function_name = display_function_name if display_function_name else function_name display_function_name = display_function_name if display_function_name else function_name
docs = section(display_function_name, level=level) docs = section(display_function_name, level=level)
docs += pre_docstring or ""
docs += inspect.cleandoc(getattr(obj, function_name).__doc__) docs += inspect.cleandoc(getattr(obj, function_name).__doc__)
docs += "\n" docs += "\n"
return docs return docs