UNPKG

itch-dl

Version:

Bulk download games from itch.io - TypeScript implementation

185 lines (184 loc) 6.6 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.DEFAULT_SETTINGS = void 0; exports.processPlatformTraits = processPlatformTraits; exports.createAndGetConfigPath = createAndGetConfigPath; exports.cleanConfig = cleanConfig; exports.loadConfig = loadConfig; const node_path_1 = __importDefault(require("node:path")); const node_fs_1 = __importDefault(require("node:fs")); const node_os_1 = __importDefault(require("node:os")); const package_json_1 = __importDefault(require("axios/package.json")); const package_json_2 = __importDefault(require("./package.json")); function processPlatformTraits(platforms) { if (!platforms || platforms.length === 0) { return undefined; } const traitMapping = { win: 'p_windows', lin: 'p_linux', mac: 'p_osx', osx: 'p_osx', darwin: 'p_osx', and: 'p_android', }; const traits = new Set(); for (let p of platforms) { let platformTrait; p = p.trim().toLowerCase().replace(/^p_/, ''); if (p.startsWith('native')) { const sys = process.platform; p = sys.toLowerCase(); if (p.endsWith('bsd')) { console.warn('Note: Native downloads for *BSDs are not available - Linux binaries will be used.'); p = 'linux'; } } for (const [key, trait] of Object.entries(traitMapping)) { if (p.startsWith(key)) { platformTrait = trait; break; } } if (!platformTrait) { throw new Error(`Platform ${p} not known!`); } traits.add(platformTrait); } return Array.from(traits); } // Default settings used when generating a Settings object exports.DEFAULT_SETTINGS = { apiKey: undefined, userAgent: `axios/${package_json_1.default.version} itch-dl/${package_json_2.default.version}`, downloadTo: undefined, mirrorWeb: false, urlsOnly: false, parallel: 1, filterFilesPlatform: undefined, filterFilesType: undefined, filterFilesGlob: undefined, filterFilesRegex: undefined, filterUrlsGlob: undefined, filterUrlsRegex: undefined, verbose: false, }; /** * Returns the path to the itch-dl configuration directory for the * current operating system. The directory may not exist. */ function createAndGetConfigPath() { const sys = process.platform; let basePath; if (sys === 'linux') { basePath = process.env.XDG_CONFIG_HOME || node_path_1.default.join(node_os_1.default.homedir(), '.config'); } else if (sys === 'darwin') { basePath = node_path_1.default.join(node_os_1.default.homedir(), 'Library', 'Application Support'); } else if (sys === 'win32') { basePath = process.env.APPDATA || node_path_1.default.join(node_os_1.default.homedir(), 'AppData', 'Roaming'); } else { throw new Error(`Unknown platform: ${sys}`); } return node_path_1.default.join(basePath, 'itch-dl'); } const TYPE_CHECKS = { apiKey: v => typeof v === 'string', userAgent: v => typeof v === 'string', downloadTo: v => typeof v === 'string', mirrorWeb: v => typeof v === 'boolean', urlsOnly: v => typeof v === 'boolean', parallel: v => typeof v === 'number', filterFilesPlatform: v => Array.isArray(v), filterFilesType: v => Array.isArray(v), filterFilesGlob: v => typeof v === 'string', filterFilesRegex: v => typeof v === 'string', filterUrlsGlob: v => typeof v === 'string', filterUrlsRegex: v => typeof v === 'string', verbose: v => typeof v === 'boolean', }; const EXPECTED_TYPES = { apiKey: 'string', userAgent: 'string', downloadTo: 'string', mirrorWeb: 'boolean', urlsOnly: 'boolean', parallel: 'number', filterFilesPlatform: 'array', filterFilesType: 'array', filterFilesGlob: 'string', filterFilesRegex: 'string', filterUrlsGlob: 'string', filterUrlsRegex: 'string', verbose: 'boolean', }; /** * Validates config data loaded from JSON, discarding unknown keys and * ensuring value types are correct. Exits the process on fatal errors. */ function cleanConfig(configData) { const cleaned = {}; let invalid = false; for (const [key, value] of Object.entries(configData)) { if (!(key in TYPE_CHECKS)) { console.warn(`Settings contain an unknown item, ignoring: '${key}'`); continue; } if (value !== null && value !== undefined && !TYPE_CHECKS[key](value)) { console.error(`Settings.${key} has invalid type '${typeof value}', expected '${EXPECTED_TYPES[key]}'`); invalid = true; continue; } cleaned[key] = value; } if (invalid) { console.error('Settings invalid, bailing out!'); process.exit(1); } return cleaned; } /** * Loads configuration from disk and applies command-line overrides. * CLI values replace file values when they evaluate to true. */ function loadConfig(cli = {}, profile) { const configPath = createAndGetConfigPath(); const configFilePath = node_path_1.default.join(configPath, 'config.json'); const profileFilePath = profile ? node_path_1.default.join(configPath, 'profiles', profile) : ''; let configData = {}; if (node_fs_1.default.existsSync(configFilePath)) { console.debug(`Found config file: ${configFilePath}`); try { configData = JSON.parse(node_fs_1.default.readFileSync(configFilePath, 'utf-8')); } catch { configData = {}; } } if (profile && node_fs_1.default.existsSync(profileFilePath)) { console.debug(`Found profile: ${profileFilePath}`); try { const profileData = JSON.parse(node_fs_1.default.readFileSync(profileFilePath, 'utf-8')); Object.assign(configData, profileData); } catch { } } const settings = { ...exports.DEFAULT_SETTINGS, ...cleanConfig(configData) }; for (const key of Object.keys(exports.DEFAULT_SETTINGS)) { const value = cli[key]; if (value) { settings[key] = value; } } const envKey = process.env.ITCH_API_KEY; if (!settings.apiKey && envKey) { settings.apiKey = envKey; } settings.filterFilesPlatform = processPlatformTraits(settings.filterFilesPlatform); return settings; }