itch-dl
Version:
Bulk download games from itch.io - TypeScript implementation
112 lines (111 loc) • 5.38 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.parseArgs = parseArgs;
exports.run = run;
const commander_1 = require("commander");
const node_path_1 = __importDefault(require("node:path"));
const node_fs_1 = __importDefault(require("node:fs"));
const package_json_1 = __importDefault(require("../package.json"));
const config_1 = require("./config");
const api_1 = require("./api");
const handlers_1 = require("./handlers");
const keys_1 = require("./keys");
const downloader_1 = require("./downloader");
const originalDebug = console.debug;
function setLogging(verbose) {
if (verbose) {
console.debug = originalDebug;
}
else {
console.debug = () => {
/* noop */
};
}
}
function buildProgram() {
const program = new commander_1.Command();
program
.name('itch-dl')
.description('Bulk download stuff from Itch.io. Docs: https://github.com/Wal33D/itch-dl/wiki')
.version(package_json_1.default.version)
.argument('<url_or_path>', 'itch.io URL or path to a game jam entries.json file')
.option('--profile <profile>', 'configuration profile to load')
.option('--api-key <key>', 'itch.io API key - https://itch.io/user/settings/api-keys')
.option('--user-agent <agent>', 'user agent to use when sending HTTP requests')
.option('--download-to <path>', 'directory to save results into (default: current working dir)')
.option('--mirror-web', 'try to fetch assets on game sites')
.option('--urls-only', 'print scraped game URLs without downloading them')
.option('--parallel <parallel>', 'how many threads to use for downloading games (default: 1)', v => parseInt(v, 10))
.option('--filter-files-platform <platforms...>', 'filter downloaded files by platform (windows, mac, linux, android, native), affects only executables')
.option('--filter-files-type <types...>', 'filter downloaded files by type (see wiki for valid values)')
.option('--filter-files-glob <glob>', 'filter downloaded files with a shell-style glob/fnmatch (unmatched files are skipped)')
.option('--filter-files-regex <regex>', 'filter downloaded files with a Python regex (unmatched files are skipped)')
.option('--filter-urls-glob <glob>', 'filter itch URLs with a shell-style glob/fnmatch (unmatched URLs are skipped)')
.option('--filter-urls-regex <regex>', 'filter itch URLs with a Python regex (unmatched URLs are skipped)')
.option('--verbose', 'print verbose logs');
return program;
}
function parseArgs(argv = process.argv) {
const program = buildProgram();
program.parse(argv);
const opts = program.opts();
const settings = {
apiKey: opts.apiKey,
userAgent: opts.userAgent,
downloadTo: opts.downloadTo,
mirrorWeb: Boolean(opts.mirrorWeb),
urlsOnly: Boolean(opts.urlsOnly),
parallel: typeof opts.parallel === 'number' && !isNaN(opts.parallel) ? opts.parallel : 1,
filterFilesPlatform: opts.filterFilesPlatform,
filterFilesType: opts.filterFilesType,
filterFilesGlob: opts.filterFilesGlob,
filterFilesRegex: opts.filterFilesRegex,
filterUrlsGlob: opts.filterUrlsGlob,
filterUrlsRegex: opts.filterUrlsRegex,
verbose: Boolean(opts.verbose),
};
const urlOrPath = program.args[0];
const profile = opts.profile;
return { urlOrPath, settings, profile };
}
async function run(argv = process.argv) {
const { urlOrPath, settings: cliSettings, profile } = parseArgs(argv);
// Initial verbosity toggle from CLI flag
setLogging(Boolean(cliSettings.verbose));
const settings = (0, config_1.loadConfig)(cliSettings, profile);
// Final verbosity after config merge
setLogging(settings.verbose);
if (!settings.apiKey) {
console.error('You did not provide an API key which itch-dl requires.\n' +
'See https://github.com/Wal33D/itch-dl/wiki/API-Keys for more info.');
return;
}
const client = new api_1.ItchApiClient(settings.apiKey, settings.userAgent);
const profileReq = await client.get('/profile');
if (profileReq.status !== 200) {
console.error(`Provided API key appears to be invalid: ${profileReq.data}\n` +
'See https://github.com/Wal33D/itch-dl/wiki/API-Keys for more info.');
return;
}
let jobs = await (0, handlers_1.getJobsForUrlOrPath)(urlOrPath, settings);
console.info('Found %d URL(s) total.', jobs.length);
jobs = (0, handlers_1.preprocessJobUrls)(jobs, settings);
console.info('Will process %d URL(s) after filtering and deduplication.', jobs.length);
if (jobs.length === 0) {
console.error('No URLs to download.');
return;
}
if (settings.urlsOnly) {
for (const job of jobs) {
console.log(job);
}
return;
}
settings.downloadTo = node_path_1.default.normalize(settings.downloadTo ?? process.cwd());
node_fs_1.default.mkdirSync(settings.downloadTo, { recursive: true });
const keys = await (0, keys_1.getDownloadKeys)(client);
await (0, downloader_1.driveDownloads)(jobs, settings, keys);
}