From 346486c563fe7201714c12034f9504034e8e00c6 Mon Sep 17 00:00:00 2001 From: Ryszard Knop Date: Mon, 27 Jan 2025 12:13:47 +0100 Subject: [PATCH] Allow filtering downloaded files by glob/regex --- itch_dl/cli.py | 11 +++++++++-- itch_dl/config.py | 3 +++ itch_dl/downloader.py | 18 ++++++++++++++++++ 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/itch_dl/cli.py b/itch_dl/cli.py index a91010a..bc18b39 100644 --- a/itch_dl/cli.py +++ b/itch_dl/cli.py @@ -29,6 +29,10 @@ def parse_args() -> argparse.Namespace: help="how many threads to use for downloading games (default: 1)") parser.add_argument("--mirror-web", action="store_true", help="try to fetch assets on game sites") + parser.add_argument("--filter-files-glob", metavar="glob", default=None, + help="filter downloaded files with a shell-style glob/fnmatch (unmatched files are skipped)") + parser.add_argument("--filter-files-regex", metavar="regex", default=None, + help="filter downloaded files with a Python regex (unmatched files are skipped)") parser.add_argument("--verbose", action="store_true", help="print verbose logs") return parser.parse_args() @@ -36,8 +40,11 @@ def parse_args() -> argparse.Namespace: def apply_args_on_settings(args: argparse.Namespace, settings: Settings): - if args.api_key: - settings.api_key = args.api_key + """Apply settings overrides from provided command line arguments, if set.""" + for key in ("api_key", "filter_files_glob", "filter_files_regex"): + value = getattr(args, key) + if value: + setattr(settings, key, value) def run() -> int: diff --git a/itch_dl/config.py b/itch_dl/config.py index ec35102..0f52aa2 100644 --- a/itch_dl/config.py +++ b/itch_dl/config.py @@ -17,6 +17,9 @@ class Settings(BaseModel): api_key: Optional[str] = None user_agent: str = f"python-requests/{requests.__version__} itch-dl/{__version__}" + filter_files_glob: Optional[str] = None + filter_files_regex: Optional[str] = None + def create_and_get_config_path() -> str: """Returns the configuration directory in the appropriate diff --git a/itch_dl/downloader.py b/itch_dl/downloader.py index e95dea2..087e3f2 100644 --- a/itch_dl/downloader.py +++ b/itch_dl/downloader.py @@ -1,6 +1,7 @@ import os import json import re +import fnmatch import logging import urllib.parse import zipfile @@ -65,6 +66,7 @@ class GameDownloader: self.download_to = download_to self.mirror_web = mirror_web + self.settings = settings self.download_keys = keys self.client = ItchApiClient(settings.api_key, settings.user_agent) @@ -307,6 +309,22 @@ class GameDownloader: expected_size = upload.get("size") upload_is_external = upload["storage"] == "external" + if self.settings.filter_files_glob and not fnmatch.fnmatch(file_name, self.settings.filter_files_glob): + logging.info( + "File '%s' does not match the glob filter '%s', skipping", + file_name, + self.settings.filter_files_glob + ) + continue + + if self.settings.filter_files_regex and not re.fullmatch(self.settings.filter_files_regex, file_name): + logging.info( + "File '%s' does not match the regex filter '%s', skipping", + file_name, + self.settings.filter_files_regex + ) + continue + logging.debug( "Downloading '%s' (%d), %s", file_name,