mirror of
https://github.com/Zagrios/bs-manager.git
synced 2026-07-03 14:08:25 +02:00
Merge branch 'master' into master
This commit is contained in:
+1
-1
@@ -2,7 +2,7 @@
|
||||
"name": "bs-manager",
|
||||
"description": "Manage maps, mods and more for Beat Saber",
|
||||
"main": "./.erb/dll/main.bundle.dev.js",
|
||||
"version": "1.5.0-alpha.9",
|
||||
"version": "1.5.0-alpha.10",
|
||||
"scripts": {
|
||||
"build-rust-scripts": "ts-node ./.erb/scripts/build-rust-scripts.js",
|
||||
"build": "concurrently \"npm run build:main\" \"npm run build:renderer\"",
|
||||
|
||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "bs-manager",
|
||||
"version": "1.5.0-alpha.9",
|
||||
"version": "1.5.0-alpha.10",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "bs-manager",
|
||||
"version": "1.5.0-alpha.9",
|
||||
"version": "1.5.0-alpha.10",
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "bs-manager",
|
||||
"version": "1.5.0-alpha.9",
|
||||
"version": "1.5.0-alpha.10",
|
||||
"description": "BSManager",
|
||||
"main": "./dist/main/main.js",
|
||||
"author": {
|
||||
|
||||
@@ -3,7 +3,6 @@ import { BbmFullMod, BbmMod, BbmModVersion, BbmPlatform } from "../../../shared/
|
||||
import { RequestService } from "../request.service";
|
||||
import { BsStore } from "../../../shared/models/bs-store.enum";
|
||||
import log from "electron-log"
|
||||
import { tryit } from "shared/helpers/error.helpers";
|
||||
|
||||
export class BeatModsApiService {
|
||||
private static instance: BeatModsApiService;
|
||||
@@ -60,42 +59,17 @@ export class BeatModsApiService {
|
||||
});
|
||||
}
|
||||
|
||||
public async getModByHash<T extends string>(hashs: T[]): Promise<Record<T, BbmModVersion>> {
|
||||
|
||||
const getModsFromCache = (hashs: T[]): Record<T, BbmModVersion> => {
|
||||
const mods = {} as Record<T, BbmModVersion>;
|
||||
|
||||
for (const hash of hashs) {
|
||||
const mod = this.modsHashCache.get(hash);
|
||||
if(mod){
|
||||
mods[hash] = mod;
|
||||
}
|
||||
}
|
||||
|
||||
return mods;
|
||||
public getModByHash(hash: string): Promise<BbmModVersion|undefined> {
|
||||
if (this.modsHashCache.has(hash)) {
|
||||
return Promise.resolve(this.modsHashCache.get(hash));
|
||||
}
|
||||
|
||||
const mods = getModsFromCache(hashs);
|
||||
const missingHashs = hashs.filter(hash => !mods[hash]);
|
||||
|
||||
if(!missingHashs.length){
|
||||
return mods;
|
||||
}
|
||||
|
||||
const url = new URL(`${this.MODS_REPO_API_URL}/hashlookup`);
|
||||
missingHashs.forEach(hash => url.searchParams.append("hash", hash));
|
||||
|
||||
const res = await tryit(() => this.requestService.getJSON<{ modVersions: BbmModVersion[] }>(url.toString()));
|
||||
|
||||
if(res.error){
|
||||
log.error(`Failed to get mod by hashes`, res.error);
|
||||
return this.requestService.getJSON<{ modVersions: BbmModVersion[] }>(`${this.MODS_REPO_API_URL}/hashlookup?hash=${hash}`).then(({ data }) => {
|
||||
this.updateModsHashCache(data?.modVersions ?? []);
|
||||
return data?.modVersions?.at(0);
|
||||
}).catch((e): undefined => {
|
||||
log.error(`Failed to get mod by hash: ${hash}`, e);
|
||||
return undefined;
|
||||
}
|
||||
|
||||
this.updateModsHashCache(res.result?.data?.modVersions ?? []);
|
||||
|
||||
const missingMods = getModsFromCache(missingHashs);
|
||||
|
||||
return {...mods, ...missingMods};
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,6 @@ import crypto from "crypto";
|
||||
import { BsmZipExtractor } from "main/models/bsm-zip-extractor.class";
|
||||
import { BsmShellLog, bsmSpawn } from "main/helpers/os.helpers";
|
||||
import { BbmFullMod, BbmModVersion, ExternalMod } from "../../../shared/models/mods/mod.interface";
|
||||
import { Stats } from "fs";
|
||||
|
||||
export class BsModsManagerService {
|
||||
private static instance: BsModsManagerService;
|
||||
@@ -29,6 +28,8 @@ export class BsModsManagerService {
|
||||
private readonly linuxService: LinuxService;
|
||||
private readonly requestService: RequestService;
|
||||
|
||||
private manifestMatches: BbmModVersion[];
|
||||
|
||||
public static getInstance(): BsModsManagerService {
|
||||
if (!BsModsManagerService.instance) {
|
||||
BsModsManagerService.instance = new BsModsManagerService();
|
||||
@@ -43,9 +44,14 @@ export class BsModsManagerService {
|
||||
this.requestService = RequestService.getInstance();
|
||||
}
|
||||
|
||||
private async getModsFromHashes(hashes: string[]): Promise<BbmModVersion[] | undefined> {
|
||||
const mods = await this.beatModsApi.getModByHash(hashes)
|
||||
return Object.values(mods).filter(mod => !mod.contentHashes.some(content => content.path.includes("IPA")));
|
||||
private async getModFromHash(hash: string): Promise<BbmModVersion | undefined> {
|
||||
const mod = await this.beatModsApi.getModByHash(hash);
|
||||
|
||||
if(mod?.contentHashes?.some(content => content.path.includes("IPA.exe"))){
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return mod;
|
||||
|
||||
}
|
||||
|
||||
@@ -57,16 +63,40 @@ export class BsModsManagerService {
|
||||
return [];
|
||||
}
|
||||
|
||||
const ignoreFunc = (file: string, stats: Stats): boolean => {
|
||||
if(!stats.isFile()) { return true; }
|
||||
const ext = path.extname(file);
|
||||
return !(ext === ".dll" || ext === ".exe" || ext === ".manifest");
|
||||
}
|
||||
const files = await recursiveReadDir(modsPath);
|
||||
|
||||
const files = await recursiveReadDir(modsPath, [ignoreFunc]);
|
||||
const hashes = await Promise.all(files.map(file => md5File(file)));
|
||||
const promises = files.map(async filePath => {
|
||||
const ext = path.extname(filePath);
|
||||
|
||||
const mods = await this.getModsFromHashes(hashes);
|
||||
if (ext !== ".dll" && ext !== ".exe" && ext !== ".manifest") {
|
||||
return undefined;
|
||||
}
|
||||
const hash = await md5File(filePath);
|
||||
const mod = await this.getModFromHash(hash);
|
||||
|
||||
if (!mod) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (ext === ".manifest") {
|
||||
this.manifestMatches.push(mod);
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (filePath.toLowerCase().includes("libs")) {
|
||||
const manifestIndex = this.manifestMatches.findIndex(m => m.id === mod.id);
|
||||
|
||||
if (manifestIndex < 0) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
this.manifestMatches.splice(manifestIndex, 1);
|
||||
}
|
||||
|
||||
return mod;
|
||||
});
|
||||
|
||||
const mods = await Promise.all(promises);
|
||||
return mods.filter(Boolean);
|
||||
}
|
||||
|
||||
@@ -77,7 +107,7 @@ export class BsModsManagerService {
|
||||
return undefined;
|
||||
}
|
||||
const injectorMd5 = await md5File(injectorPath);
|
||||
return (await this.beatModsApi.getModByHash([injectorMd5]))[injectorMd5];
|
||||
return this.beatModsApi.getModByHash(injectorMd5);
|
||||
}
|
||||
|
||||
private async downloadZip(zipUrl: string): Promise<BsmZipExtractor> {
|
||||
@@ -308,10 +338,12 @@ export class BsModsManagerService {
|
||||
}
|
||||
|
||||
public async getInstalledMods(version: BSVersion): Promise<BbmModVersion[]> {
|
||||
this.manifestMatches = [];
|
||||
|
||||
const bsipa = await this.getBsipaInstalled(version);
|
||||
|
||||
const pluginsMods = await Promise.all([this.getModsInDir(version, ModsInstallFolder.PLUGINS_PENDING), this.getModsInDir(version, ModsInstallFolder.PLUGINS)]);
|
||||
const libsMods = await Promise.all([this.getModsInDir(version, ModsInstallFolder.LIBS_PENDING), this.getModsInDir(version, ModsInstallFolder.LIBS)]);
|
||||
const pluginsMods = await Promise.all([this.getModsInDir(version, ModsInstallFolder.PLUGINS), this.getModsInDir(version, ModsInstallFolder.PLUGINS_PENDING)]);
|
||||
const libsMods = await Promise.all([this.getModsInDir(version, ModsInstallFolder.LIBS), this.getModsInDir(version, ModsInstallFolder.LIBS_PENDING)]);
|
||||
|
||||
const dirMods = pluginsMods.flat().concat(libsMods.flat());
|
||||
|
||||
|
||||
Reference in New Issue
Block a user