2022-05-15 02:02:45 +02:00
|
|
|
import os
|
2025-01-31 23:40:40 +01:00
|
|
|
import sys
|
2022-05-15 02:02:45 +02:00
|
|
|
import logging
|
|
|
|
import argparse
|
|
|
|
|
|
|
|
from .handlers import get_jobs_for_url_or_path
|
|
|
|
from .downloader import drive_downloads
|
2022-06-12 19:28:31 +02:00
|
|
|
from .config import Settings, load_config
|
2022-05-15 02:02:45 +02:00
|
|
|
from .keys import get_download_keys
|
|
|
|
from .api import ItchApiClient
|
2022-05-15 16:38:31 +02:00
|
|
|
|
2022-05-15 02:02:45 +02:00
|
|
|
logging.basicConfig()
|
|
|
|
logging.getLogger().setLevel(logging.INFO)
|
|
|
|
|
|
|
|
|
2022-06-12 19:28:31 +02:00
|
|
|
def parse_args() -> argparse.Namespace:
|
2024-03-17 01:17:19 +01:00
|
|
|
# fmt: off
|
2022-05-15 02:02:45 +02:00
|
|
|
parser = argparse.ArgumentParser(description="Bulk download stuff from Itch.io.")
|
|
|
|
parser.add_argument("url_or_path",
|
|
|
|
help="itch.io URL or path to a game jam entries.json file")
|
2022-06-12 19:28:31 +02:00
|
|
|
parser.add_argument("--profile", metavar="profile", default=None,
|
|
|
|
help="configuration profile to load")
|
2025-01-31 22:35:37 +01:00
|
|
|
|
|
|
|
# These args must match config.py -> Settings class. Make sure all defaults here
|
|
|
|
# evaluate to False, or apply_args_on_settings will override profile settings.
|
|
|
|
parser.add_argument("--api-key", metavar="key", default=None,
|
|
|
|
help="itch.io API key - https://itch.io/user/settings/api-keys")
|
|
|
|
parser.add_argument("--user-agent", metavar="agent", default=None,
|
|
|
|
help="user agent to use when sending HTTP requests")
|
|
|
|
parser.add_argument("--download-to", metavar="path", default=None,
|
|
|
|
help="directory to save results into (default: current working dir)")
|
|
|
|
parser.add_argument("--mirror-web", action="store_true",
|
|
|
|
help="try to fetch assets on game sites")
|
2022-05-15 02:02:45 +02:00
|
|
|
parser.add_argument("--urls-only", action="store_true",
|
|
|
|
help="print scraped game URLs without downloading them")
|
2025-01-31 22:35:37 +01:00
|
|
|
parser.add_argument("--parallel", metavar="parallel", type=int, default=None,
|
2022-05-15 02:02:45 +02:00
|
|
|
help="how many threads to use for downloading games (default: 1)")
|
2025-01-27 12:13:47 +01:00
|
|
|
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)")
|
2022-05-15 02:02:45 +02:00
|
|
|
parser.add_argument("--verbose", action="store_true",
|
|
|
|
help="print verbose logs")
|
2025-01-31 22:35:37 +01:00
|
|
|
|
2022-05-15 02:02:45 +02:00
|
|
|
return parser.parse_args()
|
2024-03-17 01:17:19 +01:00
|
|
|
# fmt: on
|
2022-05-15 02:02:45 +02:00
|
|
|
|
|
|
|
|
|
|
|
def run() -> int:
|
|
|
|
args = parse_args()
|
|
|
|
if args.verbose:
|
|
|
|
logging.getLogger().setLevel(logging.DEBUG)
|
|
|
|
|
2025-01-31 22:35:37 +01:00
|
|
|
settings: Settings = load_config(args, profile=args.profile)
|
|
|
|
if settings.verbose:
|
|
|
|
logging.getLogger().setLevel(logging.DEBUG)
|
2022-06-12 19:28:31 +02:00
|
|
|
|
|
|
|
if not settings.api_key:
|
2025-01-31 23:40:40 +01:00
|
|
|
sys.exit(
|
2024-03-17 01:17:19 +01:00
|
|
|
"You did not provide an API key which itch-dl requires.\n"
|
|
|
|
"See https://github.com/DragoonAethis/itch-dl/wiki/API-Keys for more info."
|
|
|
|
)
|
2022-06-12 19:28:31 +02:00
|
|
|
|
2025-01-31 22:35:37 +01:00
|
|
|
url_or_path = args.url_or_path
|
|
|
|
del args # Do not use `args` beyond this point.
|
|
|
|
|
2022-06-12 19:28:31 +02:00
|
|
|
# Check API key validity:
|
|
|
|
client = ItchApiClient(settings.api_key, settings.user_agent)
|
|
|
|
profile_req = client.get("/profile")
|
|
|
|
if not profile_req.ok:
|
2025-01-31 23:40:40 +01:00
|
|
|
sys.exit(
|
2024-03-17 01:17:19 +01:00
|
|
|
f"Provided API key appears to be invalid: {profile_req.text}\n"
|
|
|
|
"See https://github.com/DragoonAethis/itch-dl/wiki/API-Keys for more info."
|
|
|
|
)
|
2022-06-12 19:28:31 +02:00
|
|
|
|
2025-01-31 22:35:37 +01:00
|
|
|
jobs = get_jobs_for_url_or_path(url_or_path, settings)
|
2022-05-15 02:02:45 +02:00
|
|
|
jobs = list(set(jobs)) # Deduplicate, just in case...
|
2025-01-31 23:40:40 +01:00
|
|
|
logging.info("Found %d URL(s).", len(jobs))
|
2022-05-15 02:02:45 +02:00
|
|
|
|
|
|
|
if len(jobs) == 0:
|
2025-01-31 23:40:40 +01:00
|
|
|
sys.exit("No URLs to download.")
|
2022-05-15 02:02:45 +02:00
|
|
|
|
2025-01-31 22:35:37 +01:00
|
|
|
if settings.urls_only:
|
2022-05-15 02:02:45 +02:00
|
|
|
for job in jobs:
|
|
|
|
print(job)
|
|
|
|
|
|
|
|
return 0
|
|
|
|
|
2025-01-31 22:35:37 +01:00
|
|
|
# If the download dir is not set, use the current working dir:
|
|
|
|
settings.download_to = os.path.normpath(settings.download_to or os.getcwd())
|
|
|
|
os.makedirs(settings.download_to, exist_ok=True)
|
2022-05-15 02:02:45 +02:00
|
|
|
|
|
|
|
# Grab all the download keys (there's no way to fetch them per title...):
|
|
|
|
keys = get_download_keys(client)
|
|
|
|
|
2025-01-31 23:40:40 +01:00
|
|
|
drive_downloads(jobs, settings, keys)
|
|
|
|
return 0
|