Merge branch 'master' into master

This commit is contained in:
GaetanGrd
2025-01-28 19:52:54 +01:00
committed by GitHub
5 changed files with 60 additions and 54 deletions
+1 -1
View File
@@ -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\"",
+2 -2
View File
@@ -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 -1
View File
@@ -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());