Playlists have always been a pain-point with ytdl-sub. If an author adds new videos to the end of a playlist, as opposed to the front, it breaks ytdl-sub's intuition of incremental scraping by breaking on the first (oldest) video. This update now makes it possible to handle this in the prebuilt TV Show presets:
- Add each URL variable (`url`, `url2`, ...) into the `download` portion of the subscription twice
- First definition is what we all know and use, simply scrapes first-to-last, then downloads last-to-first
- Second definition does the following:
- Check to see if a URL is a YouTube playlist URL, if so...
- Set the field to download, but with modifications to scrape last-to-first, then download first-to-last
- Otherwise...
- Set the field to an empty string, which means ytdl-sub will skip it
88 lines
3.1 KiB
Python
88 lines
3.1 KiB
Python
from ytdl_sub.script.script import Script
|
|
from ytdl_sub.script.script_output import ScriptOutput
|
|
from ytdl_sub.script.types.map import Map
|
|
from ytdl_sub.script.types.resolvable import String
|
|
|
|
|
|
class TestScript:
|
|
def test_pre_resolved(self):
|
|
assert Script(
|
|
{
|
|
"%custom_func": "return {[$0, $1]}",
|
|
"aa": "a",
|
|
"bb": "b",
|
|
"cc": "{%custom_func(aa, bb)}",
|
|
}
|
|
).resolve(resolved={"bb": String("bb_override")}) == ScriptOutput(
|
|
{
|
|
"aa": String("a"),
|
|
"bb": String("bb_override"),
|
|
"cc": String('return ["a", "bb_override"]'),
|
|
}
|
|
)
|
|
|
|
def test_partial_resolve(self):
|
|
assert Script(
|
|
{
|
|
"%custom_func": "return {[$0, $1]}",
|
|
"aa": "a",
|
|
"bb": "b",
|
|
"cc": "{%custom_func(aa, bb)}",
|
|
}
|
|
).resolve(unresolvable={"bb"}) == ScriptOutput({"aa": String("a")})
|
|
|
|
def test_partial_update_script(self):
|
|
# to be resolved later
|
|
entry_map = Map({String("title"): String("the title")})
|
|
|
|
script = Script(
|
|
{
|
|
"entry": "{%throw('entry has not been populated yet')}",
|
|
"title": "{%map_get(entry, 'title')}",
|
|
"override": "hi",
|
|
"resolved_override": "{override} mom",
|
|
}
|
|
)
|
|
|
|
script.resolve(unresolvable={"entry"}, update=True)
|
|
assert script.get("override") == String("hi")
|
|
assert script.get("resolved_override") == String("hi mom")
|
|
|
|
script.add(
|
|
{
|
|
"new_variable_titlecase": "{%titlecase(new_variable_upper)}",
|
|
"new_variable": "{resolved_override} {title}",
|
|
"new_variable_upper": "{%upper(new_variable)}",
|
|
}
|
|
).resolve(resolved={"entry": entry_map}, update=True)
|
|
|
|
assert script.get("title") == String("the title")
|
|
assert script.get("new_variable") == String("hi mom the title")
|
|
assert script.get("new_variable_upper") == String("HI MOM THE TITLE")
|
|
assert script.get("new_variable_titlecase") == String("Hi Mom The Title")
|
|
assert script.get("entry") == entry_map
|
|
|
|
def test_resolve_once_with_custom_functions(self):
|
|
script = Script(
|
|
{
|
|
"%is_bilateral_url": "{ %not(%contains( $0, 'youtube.com/playlist' )) }",
|
|
"%bilateral_url": """{
|
|
%if(
|
|
%and(
|
|
enable_bilateral_scraping,
|
|
%is_bilateral_url($0)
|
|
),
|
|
$0,
|
|
""
|
|
)
|
|
}""",
|
|
"enable_bilateral_scraping": "True",
|
|
}
|
|
)
|
|
|
|
assert script.resolve_once({"url": "{ %bilateral_url('nope') }"})["url"].native == "nope"
|
|
script.add({"%bilateral_url_wrap": "{ %bilateral_url($0) }"})
|
|
|
|
assert (
|
|
script.resolve_once({"url": "{ %bilateral_url_wrap('nope') }"})["url"].native == "nope"
|
|
)
|