diff --git a/src/ytdl_sub/plugins/throttle_protection.py b/src/ytdl_sub/plugins/throttle_protection.py index 77ec4fa8..27cad374 100644 --- a/src/ytdl_sub/plugins/throttle_protection.py +++ b/src/ytdl_sub/plugins/throttle_protection.py @@ -185,6 +185,13 @@ class ThrottleProtectionOptions(ToggleableOptionsDictValidator): class ThrottleProtectionPlugin(Plugin[ThrottleProtectionOptions]): plugin_options_type = ThrottleProtectionOptions + @classmethod + def perform_sleep(cls, sleep_time: float) -> None: + """ + Wrapper to be able to mock + """ + time.sleep(sleep_time) + def __init__( self, options: ThrottleProtectionOptions, @@ -239,7 +246,7 @@ class ThrottleProtectionPlugin(Plugin[ThrottleProtectionOptions]): self._subscription_max_downloads is not None and self._subscription_download_counter == 0 ): - logger.debug( + logger.info( "Setting subscription max downloads to %d", self._subscription_max_downloads ) @@ -248,8 +255,8 @@ class ThrottleProtectionPlugin(Plugin[ThrottleProtectionOptions]): if self.plugin_options.sleep_per_download_s: sleep_time = self.plugin_options.sleep_per_download_s.randomized_float() - logger.debug("Sleeping between downloads for %0.2f seconds", sleep_time) - time.sleep(sleep_time) + logger.info("Sleeping between downloads for %0.2f seconds", sleep_time) + self.perform_sleep(sleep_time) return None @@ -265,5 +272,5 @@ class ThrottleProtectionPlugin(Plugin[ThrottleProtectionOptions]): if self.plugin_options.sleep_per_subscription_s: sleep_time = self.plugin_options.sleep_per_subscription_s.randomized_float() - logger.debug("Sleeping between subscriptions for %0.2f seconds", sleep_time) - time.sleep(sleep_time) + logger.info("Sleeping between subscriptions for %0.2f seconds", sleep_time) + self.perform_sleep(sleep_time) diff --git a/src/ytdl_sub/prebuilt_presets/helpers/throttle_protection.yaml b/src/ytdl_sub/prebuilt_presets/helpers/throttle_protection.yaml new file mode 100644 index 00000000..81264d69 --- /dev/null +++ b/src/ytdl_sub/prebuilt_presets/helpers/throttle_protection.yaml @@ -0,0 +1,26 @@ +presets: + + _throttle_protection: + throttle_protection: + enable: >- + { + %print( + %if( + enable_throttle_protection, + "Throttle protection is enabled. Disable using the override variable `enable_throttle_protection: False`", + "Throttle protection is disabled. Use at your own risk!" + ), + enable_throttle_protection + ) + } + sleep_per_request_s: + min: 3.5 + max: 3.5 + sleep_per_download_s: + min: 13.8 + max: 28.4 + sleep_per_subscription_s: + min: 16.3 + max: 26.1 + overrides: + enable_throttle_protection: True \ No newline at end of file diff --git a/src/ytdl_sub/prebuilt_presets/music/albums_from_chapters.yaml b/src/ytdl_sub/prebuilt_presets/music/albums_from_chapters.yaml index 6c9b82ee..5881bfb4 100644 --- a/src/ytdl_sub/prebuilt_presets/music/albums_from_chapters.yaml +++ b/src/ytdl_sub/prebuilt_presets/music/albums_from_chapters.yaml @@ -22,4 +22,5 @@ presets: "YouTube Full Albums": preset: - - "_albums_from_chapters" \ No newline at end of file + - "_albums_from_chapters" + - "_throttle_protection" \ No newline at end of file diff --git a/src/ytdl_sub/prebuilt_presets/music/albums_from_playlists.yaml b/src/ytdl_sub/prebuilt_presets/music/albums_from_playlists.yaml index 22839279..7d847d27 100644 --- a/src/ytdl_sub/prebuilt_presets/music/albums_from_playlists.yaml +++ b/src/ytdl_sub/prebuilt_presets/music/albums_from_playlists.yaml @@ -18,6 +18,7 @@ presets: "YouTube Releases": preset: - "_albums_from_playlists" + - "_throttle_protection" "Bandcamp": preset: diff --git a/src/ytdl_sub/prebuilt_presets/music/singles.yaml b/src/ytdl_sub/prebuilt_presets/music/singles.yaml index dc7b5a25..04a9a031 100644 --- a/src/ytdl_sub/prebuilt_presets/music/singles.yaml +++ b/src/ytdl_sub/prebuilt_presets/music/singles.yaml @@ -2,6 +2,7 @@ presets: _music_base: + output_options: output_directory: "{music_directory}" file_name: "{track_full_path}" diff --git a/src/ytdl_sub/prebuilt_presets/music/other_websites.yaml b/src/ytdl_sub/prebuilt_presets/music/soundcloud.yaml similarity index 100% rename from src/ytdl_sub/prebuilt_presets/music/other_websites.yaml rename to src/ytdl_sub/prebuilt_presets/music/soundcloud.yaml diff --git a/src/ytdl_sub/prebuilt_presets/music_videos/music_video_base.yaml b/src/ytdl_sub/prebuilt_presets/music_videos/music_video_base.yaml index 25b97697..a0c93c4b 100644 --- a/src/ytdl_sub/prebuilt_presets/music_videos/music_video_base.yaml +++ b/src/ytdl_sub/prebuilt_presets/music_videos/music_video_base.yaml @@ -2,6 +2,9 @@ presets: _music_video_base: preset: + # ytdl-sub includes throttle prootection by default or all prebuilt presets. + # Can be disabled with override variable `enable_throttle_protection: False` + - "_throttle_protection" - "_url_categorized" output_options: diff --git a/src/ytdl_sub/prebuilt_presets/tv_show/episode.yaml b/src/ytdl_sub/prebuilt_presets/tv_show/episode.yaml index fe39e5cf..de02cfbb 100644 --- a/src/ytdl_sub/prebuilt_presets/tv_show/episode.yaml +++ b/src/ytdl_sub/prebuilt_presets/tv_show/episode.yaml @@ -3,6 +3,11 @@ presets: #################################################################################################### _episode_base: + preset: + # ytdl-sub includes throttle prootection by default or all prebuilt presets. + # Can be disabled with override variable `enable_throttle_protection: False` + - "_throttle_protection" + output_options: output_directory: "{tv_show_directory}/{tv_show_name_sanitized}" file_name: "{episode_file_path}.{ext}" diff --git a/src/ytdl_sub/script/functions/print_functions.py b/src/ytdl_sub/script/functions/print_functions.py index a89bcd28..79113f1c 100644 --- a/src/ytdl_sub/script/functions/print_functions.py +++ b/src/ytdl_sub/script/functions/print_functions.py @@ -9,6 +9,9 @@ logger = Logger.get(name="preset") def _log(message: AnyArgument, level: Optional[Integer]) -> None: + if not str(message): + return + if level is None: logger.info(str(message)) return diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py index fbd26c4c..b1d40434 100644 --- a/tests/integration/conftest.py +++ b/tests/integration/conftest.py @@ -15,6 +15,7 @@ from ytdl_sub.downloaders.url.downloader import MultiUrlDownloader from ytdl_sub.downloaders.ytdlp import YTDLP from ytdl_sub.entries.script.variable_definitions import VARIABLES from ytdl_sub.entries.script.variable_definitions import VariableDefinitions +from ytdl_sub.plugins.throttle_protection import ThrottleProtectionPlugin v: VariableDefinitions = VARIABLES @@ -264,6 +265,9 @@ def mock_download_collection_entries( patch.object( MultiUrlDownloader, "_extract_entry_info_with_retry", new=lambda _, entry: entry ), + # Throttle protection is included in all prebuilt presets. Mock the sleep avoid + # actual sleeps + patch.object(ThrottleProtectionPlugin, "perform_sleep", new=lambda _1, _2: None), ): # Stub out metadata. TODO: update this if we do metadata plugins yield diff --git a/tests/integration/plugins/test_throttle_protection.py b/tests/integration/plugins/test_throttle_protection.py index 860e49ca..51f3cc23 100644 --- a/tests/integration/plugins/test_throttle_protection.py +++ b/tests/integration/plugins/test_throttle_protection.py @@ -55,7 +55,7 @@ class TestThrottleProtectionPlugin: assert_logs( logger=throttle_protection_logger, expected_message="Sleeping between downloads for %0.2f seconds", - log_level="debug", + log_level="info", expected_occurrences=4, ), ): @@ -68,7 +68,7 @@ class TestThrottleProtectionPlugin: assert_logs( logger=throttle_protection_logger, expected_message="Sleeping between subscriptions for %0.2f seconds", - log_level="debug", + log_level="info", expected_occurrences=1, ), ): @@ -92,7 +92,7 @@ class TestThrottleProtectionPlugin: mock_download_collection_entries, disable_value, ): - throttle_subscription_dict["throttle_protection"]["enable"] = disable_value + throttle_subscription_dict["overrides"]["enable_throttle_protection"] = disable_value subscription = Subscription.from_dict( config=config, preset_name=subscription_name, @@ -106,7 +106,7 @@ class TestThrottleProtectionPlugin: assert_logs( logger=throttle_protection_logger, expected_message="Sleeping between downloads for %0.2f seconds", - log_level="debug", + log_level="info", expected_occurrences=0, ), ): diff --git a/tests/unit/script/functions/test_print_functions.py b/tests/unit/script/functions/test_print_functions.py index a23f447d..56500d16 100644 --- a/tests/unit/script/functions/test_print_functions.py +++ b/tests/unit/script/functions/test_print_functions.py @@ -15,12 +15,15 @@ class TestPrintFunctions: ("{%print('hi mom', True)}", "hi mom", True), ("{%print('this is great', [1, 2, 3])}", "this is great", [1, 2, 3]), ("{%print([1, 2], [3, 4])}", "[1, 2]", [3, 4]), + ("{%print('', True)}", None, True), # print_if_true ("{%print_if_true('hi mom', True)}", "hi mom", True), ("{%print_if_true('hi mom', False)}", None, False), + ("{%print_if_true('', True)}", None, True), # print_if_false ("{%print_if_false('hi mom', True)}", None, True), ("{%print_if_false('hi mom', False)}", "hi mom", False), + ("{%print_if_false('', True)}", None, True), ], ) def test_print_functions(