mirror of
https://github.com/Zagrios/bs-manager.git
synced 2026-07-03 14:08:25 +02:00
[chore] updating naming sheme of downloaded maps to avoid duplication when downloading maps from other tools
+ updating naming sheme of downloading playlists + updating download models due to function changes
This commit is contained in:
@@ -141,9 +141,11 @@ export class LocalMapsManagerService {
|
||||
const fileName = `${path.basename(zipUrl, ".zip")}-${crypto.randomUUID()}.zip`;
|
||||
const tempPath = this.utils.getTempPath();
|
||||
await ensureFolderExist(this.utils.getTempPath());
|
||||
const dest = path.join(tempPath, fileName);
|
||||
|
||||
const zipPath = (await lastValueFrom(this.reqService.downloadFile(zipUrl, dest))).data;
|
||||
const zipPath = (await lastValueFrom(this.reqService.downloadFile(zipUrl, {
|
||||
destFolder: tempPath,
|
||||
filename: fileName
|
||||
}))).data;
|
||||
const zip = new StreamZip.async({ file: zipPath });
|
||||
|
||||
return { zip, zipPath };
|
||||
@@ -263,7 +265,7 @@ export class LocalMapsManagerService {
|
||||
}
|
||||
|
||||
const zipUrl = map.versions.at(0).downloadURL;
|
||||
const mapFolderName = sanitize(`${map.id}-${map.name}`);
|
||||
const mapFolderName = sanitize(`${map.id} (${map.metadata.songName} - ${map.metadata.levelAuthorName})`);
|
||||
const mapsFolder = await this.getMapsFolderPath(version);
|
||||
|
||||
const mapPath = path.join(mapsFolder, mapFolderName);
|
||||
|
||||
@@ -87,12 +87,14 @@ export class LocalModelsManagerService {
|
||||
|
||||
(async () => {
|
||||
const modelFolder = await this.getModelFolderPath(model.type, version);
|
||||
const modelDest = path.join(modelFolder, sanitize(path.basename(model.download)));
|
||||
|
||||
const url = model.download.split("/");
|
||||
url[url.length - 1] = encodeURIComponent(url[url.length - 1]);
|
||||
|
||||
const download$ = this.request.downloadFile(url.join("/"), modelDest);
|
||||
const download$ = this.request.downloadFile(url.join("/"), {
|
||||
destFolder: modelFolder,
|
||||
filename: sanitize(path.basename(model.download))
|
||||
});
|
||||
|
||||
subs.push(download$.subscribe({ next: value => subscriber.next({ ...value, data: undefined }), error: e => subscriber.error(e) }));
|
||||
|
||||
|
||||
@@ -77,9 +77,13 @@ export class LocalPlaylistsManagerService {
|
||||
if (isLocalFile) {
|
||||
return copyFile(bslistSource, destFile).then(() => destFile);
|
||||
}
|
||||
return lastValueFrom(this.request.downloadFile(bslistSource, destFile)).then(res => res.data);
|
||||
return lastValueFrom(this.request.downloadFile(bslistSource, {
|
||||
destFolder: playlistFolder,
|
||||
filename,
|
||||
preferContentDisposition: true,
|
||||
})).then(res => res.data);
|
||||
}
|
||||
|
||||
|
||||
|
||||
private async readPlaylistFile(path: string): Promise<BPList> {
|
||||
if (!(await pathExist(path))) {
|
||||
@@ -102,8 +106,8 @@ export class LocalPlaylistsManagerService {
|
||||
|
||||
const bpListFilePath = await this.installBPListFile(bpListUrl, version);
|
||||
const bpList = await this.readPlaylistFile(bpListFilePath);
|
||||
|
||||
const progress: Progression<DownloadPlaylistProgressionData> = {
|
||||
|
||||
const progress: Progression<DownloadPlaylistProgressionData> = {
|
||||
total: bpList.songs.length,
|
||||
current: 0,
|
||||
data: {
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
import { Agent, RequestOptions, get } from "https";
|
||||
import { createWriteStream, unlink } from "fs";
|
||||
import { Progression } from "main/helpers/fs.helpers";
|
||||
import { createWriteStream } from "fs";
|
||||
import { Progression, unlinkPath } from "../helpers/fs.helpers";
|
||||
import { Observable, shareReplay, tap } from "rxjs";
|
||||
import log from "electron-log";
|
||||
import fetch, { RequestInfo, RequestInit } from "node-fetch";
|
||||
import { app } from "electron";
|
||||
import os from "os";
|
||||
import path from "path";
|
||||
import { tryit } from "../../shared/helpers/error.helpers";
|
||||
import sanitize from "sanitize-filename";
|
||||
|
||||
export class RequestService {
|
||||
private static instance: RequestService;
|
||||
@@ -56,22 +59,65 @@ export class RequestService {
|
||||
}
|
||||
}
|
||||
|
||||
public downloadFile(url: string, dest: string): Observable<Progression<string>> {
|
||||
private getFilenameFromContentDisposition(disposition: string): string | null {
|
||||
|
||||
if(!disposition) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const utf8FilenameRegex = /filename\*=UTF-8''([\w%\-\.]+)(?:; ?|$)/i;
|
||||
const asciiFilenameRegex = /^filename=(["']?)(.*?[^\\])\1(?:; ?|$)/i;
|
||||
|
||||
const utf8Match = utf8FilenameRegex.exec(disposition);
|
||||
if (utf8Match) {
|
||||
return decodeURIComponent(utf8Match[1]);
|
||||
}
|
||||
|
||||
const filenameStart = disposition.toLowerCase().indexOf('filename=');
|
||||
if (filenameStart >= 0) {
|
||||
const partialDisposition = disposition.slice(filenameStart);
|
||||
const asciiMatch = asciiFilenameRegex.exec(partialDisposition);
|
||||
if (asciiMatch && asciiMatch[2]) {
|
||||
return asciiMatch[2];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public downloadFile(url: string, opt: { destFolder: string, filename: string, preferContentDisposition?: boolean }): Observable<Progression<string>> {
|
||||
return new Observable<Progression<string>>(subscriber => {
|
||||
const progress: Progression<string> = { current: 0, total: 0 };
|
||||
|
||||
const file = createWriteStream(dest);
|
||||
|
||||
file.on("close", () => {
|
||||
progress.data = dest;
|
||||
subscriber.next(progress);
|
||||
subscriber.complete();
|
||||
});
|
||||
file.on("error", err => unlink(dest, () => subscriber.error(err)));
|
||||
|
||||
const req = get(url, this.requestOptionsFromDefaultInit(), res => {
|
||||
|
||||
const filePath = (() => {
|
||||
if(opt.preferContentDisposition && res.headers["content-disposition"]) {
|
||||
const filename = this.getFilenameFromContentDisposition(res.headers["content-disposition"]);
|
||||
return path.join(opt.destFolder, sanitize(filename || opt.filename));
|
||||
}
|
||||
return path.join(opt.destFolder, opt.filename);
|
||||
})();
|
||||
|
||||
const file = createWriteStream(filePath);
|
||||
|
||||
file.on("close", () => {
|
||||
subscriber.next(progress);
|
||||
subscriber.complete();
|
||||
});
|
||||
file.on("error", async err => {
|
||||
log.error(err);
|
||||
const res = await tryit(() => unlinkPath(filePath));
|
||||
if(res.error) {
|
||||
log.error(res.error);
|
||||
}
|
||||
});
|
||||
|
||||
progress.data = filePath;
|
||||
progress.total = parseInt(res.headers?.["content-length"] || "0", 10);
|
||||
|
||||
subscriber.next(progress);
|
||||
|
||||
res.on("data", chunk => {
|
||||
progress.current += chunk.length;
|
||||
subscriber.next(progress);
|
||||
@@ -83,7 +129,7 @@ export class RequestService {
|
||||
req.on("error", err => {
|
||||
subscriber.error(err);
|
||||
});
|
||||
}).pipe(tap({ error: e => log.error(e, url, dest) }), shareReplay(1));
|
||||
}).pipe(tap({ error: e => log.error(e, url) }), shareReplay(1));
|
||||
}
|
||||
|
||||
public downloadBuffer(url: string): Observable<Progression<Buffer>> {
|
||||
|
||||
Reference in New Issue
Block a user