UNPKG

dmclc

Version:

Dolphin Minecraft Launcher Core

119 lines (118 loc) 3.5 kB
import fs from "fs"; import { ensureDir } from "fs-extra"; import got, { HTTPError } from "got"; import path from "path"; import * as streamPromises from "stream/promises"; import { FormattedError } from "../errors/FormattedError.js"; import { transformURL } from "./TransformURL.js"; import { checkFile } from "./check_file.js"; /** * Download multi files after checking hash. * @throws RequestError * @param files A map from URL to path * @param launcher Launcher * @returns true if success */ export async function checkAndDownloadAll(files, launcher, algorithm = "sha1") { const promises = []; files.forEach((v, k) => { if (v.a === "no") { promises.push(download(k, v.b, launcher)); } else { promises.push(checkAndDownload(k, v.b, v.a, launcher, algorithm)); } }); return !(await Promise.all(promises)).includes(false); } /** * Download multi files. * @throws RequestError * @param files A map from URL to path * @param launcher Launcher * @returns true if success */ export async function downloadAll(files, launcher) { const promises = []; files.forEach((v, k) => { promises.push(download(k, v, launcher)); }); return !(await Promise.all(promises)).includes(false); } /** * Download a file after checking hash. * @throws {@link FormattedError} * @param url - URL. * @param filename - File name. * @param mirror - BMCLAPI mirror. */ export async function checkAndDownload(url, filename, hash, launcher, algorithm = "sha1") { if (!await checkFile(filename, hash, algorithm)) { return await download(url, filename, launcher); } return true; } /** * Download a file. * @throws {@link FormattedError} * @param url - URL. * @param filename - File name. * @param mirror - BMCLAPI mirror. */ export async function download(url, filename, launcher) { if (url.length === 0) return true; const dir = path.dirname(filename.toString()); await ensureDir(dir); let realURL = transformURL(url, launcher.mirror); if (launcher.downloader) await launcher.downloader(realURL, filename, url); else await downloader(realURL, filename, url); return true; } export async function downloadIntoStream(url, out, launcher) { if (url.length === 0) return true; let realURL = transformURL(url, launcher.mirror); let failed = true; for (let i = 0; i < 10; i++) { try { await streamPromises.pipeline(got.stream(realURL), out); failed = false; break; } catch (e) { if (e instanceof HTTPError) { if (e.response.statusCode === 404) { i--; } } } } if (failed) { throw new FormattedError(`Download failed: ${url}`); } return true; } async function downloader(url, filename, oldURL) { let failed = true; for (let i = 0; i < 10; i++) { try { await streamPromises.pipeline(got.stream(url), fs.createWriteStream(filename)); failed = false; break; } catch (e) { if (e instanceof HTTPError) { if (e.response.statusCode === 404) { url = oldURL.replaceAll("http://", "https://"); i--; } } } } if (failed) { throw new FormattedError(`Download failed: ${url}`); } }