[feature-136] init show local models

This commit is contained in:
MathieuG-P
2023-05-01 23:00:13 +02:00
parent bdbdcfb1b4
commit ab798437d5
36 changed files with 456 additions and 64 deletions
@@ -21,7 +21,7 @@ import { Archive } from "../../models/archive.class";
import { deleteFolder, ensureFolderExist, getFoldersInFolder, pathExist } from "../../helpers/fs.helpers";
import { readFile } from "fs/promises";
import { FolderLinkerService } from "../folder-linker.service";
import { allSettled } from "../../helpers/promise.helpers";
import { allSettled } from "../../../shared/helpers/promise.helpers";
export class LocalMapsManagerService {
@@ -4,15 +4,22 @@ import { ipcMain } from "electron";
import { IpcRequest } from "shared/models/ipc";
import { UtilsService } from "../utils.service";
import { WindowManagerService } from "../window-manager.service";
import { MSModel, MSModelType } from "../../../shared/models/model-saber/model-saber.model";
import { MSModel, MSModelType } from "../../../shared/models/models/model-saber.model";
import { BSVersion } from "shared/bs-version.interface";
import { BSLocalVersionService } from "../bs-local-version.service";
import path from "path";
import { RequestService } from "../request.service";
import { copyFileSync } from "fs-extra";
import sanitize from "sanitize-filename";
import { ensureFolderExist } from "../../helpers/fs.helpers";
import { MODEL_TYPE_FOLDERS } from "../../../shared/models/model-saber/models-constants";
import { Progression, ensureFolderExist, extname } from "../../helpers/fs.helpers";
import { MODEL_TYPE_FOLDERS } from "../../../shared/models/models/constants";
import { InstallationLocationService } from "../installation-location.service";
import { Observable } from "rxjs";
import { readdir } from "fs/promises";
import md5File from "md5-file";
import { allSettled } from "../../../shared/helpers/promise.helpers";
import { ModelSaberService } from "../thrid-party/model-saber/model-saber.service";
import { BsmLocalModel } from "shared/models/models/bsm-local-model.interface";
export class LocalModelsManagerService {
@@ -31,7 +38,9 @@ export class LocalModelsManagerService {
private readonly utils: UtilsService;
private readonly windows: WindowManagerService;
private readonly localVersion: BSLocalVersionService;
private readonly installPaths: InstallationLocationService;
private readonly request: RequestService;
private readonly modelSaber: ModelSaberService;
private constructor(){
this.deepLink = DeepLinkService.getInstance();
@@ -39,6 +48,8 @@ export class LocalModelsManagerService {
this.windows = WindowManagerService.getInstance();
this.localVersion = BSLocalVersionService.getInstance();
this.request = RequestService.getInstance();
this.installPaths = InstallationLocationService.getInstance();
this.modelSaber = ModelSaberService.getInstance();
this.deepLink.addLinkOpenedListener(this.DEEP_LINKS.ModelSaber, (link) => {
log.info("DEEP-LINK RECEIVED FROM", this.DEEP_LINKS.ModelSaber, link);
@@ -63,10 +74,8 @@ export class LocalModelsManagerService {
private async getModelFolderPath(type: MSModelType, version?: BSVersion): Promise<string>{
if(!version){ throw "will be implemented whith models management" }
const versionPath = await this.localVersion.getVersionPath(version);
const modelFolderPath = path.join(versionPath, MODEL_TYPE_FOLDERS[type]);
const rootPath = !!version ? await this.localVersion.getVersionPath(version) : this.installPaths.sharedContentPath;
const modelFolderPath = path.join(rootPath, MODEL_TYPE_FOLDERS[type]);
await ensureFolderExist(modelFolderPath);
@@ -105,6 +114,54 @@ export class LocalModelsManagerService {
}
private async getModelsPaths(type: MSModelType, version?: BSVersion): Promise<string[]>{
const modelsPath = await this.getModelFolderPath(type, version);
const files = await readdir(modelsPath, {withFileTypes: true});
return files.filter(file => file.isFile() && extname(file.name, false) === type).map(file => path.join(modelsPath, file.name));
}
public getModels(type: MSModelType, version?: BSVersion): Observable<Progression<BsmLocalModel[]>>{
const progression: Progression<BsmLocalModel[]> = {
total: 0,
current: 0,
extra: null
};
return new Observable<Progression<BsmLocalModel[]>>(subscriber => {
(async () => {
const modelsPaths = await this.getModelsPaths(type, version);
progression.total = modelsPaths.length;
const models = await allSettled(modelsPaths.map(async modelPath => {
const hash = await md5File(modelPath)
const localModel: BsmLocalModel = {
path: modelPath,
fileName: path.basename(modelPath),
model: await this.modelSaber.getModelByHash(hash),
type, hash
}
progression.current++;
subscriber.next(progression);
return localModel;
}));
progression.extra = models;
subscriber.next(progression);
})().catch(e => subscriber.error(e)).finally(() => subscriber.complete());
});
}
public enableDeepLinks(): boolean{
return Array.from(Object.values(this.DEEP_LINKS)).every(link => this.deepLink.registerDeepLink(link));
}
@@ -117,4 +174,10 @@ export class LocalModelsManagerService {
return Array.from(Object.values(this.DEEP_LINKS)).every(link => this.deepLink.isDeepLinkRegistred(link));
}
}
export interface BsmLocalModelsProgress {
total: number;
loaded: number;
models: MSModel[];
}
+1 -1
View File
@@ -4,7 +4,7 @@ import { writeFileSync } from 'fs';
import { BSVersion } from 'shared/bs-version.interface';
import { RequestService } from "./request.service"
import { readJSON } from 'fs-extra';
import { allSettled } from '../helpers/promise.helpers';
import { allSettled } from '../../shared/helpers/promise.helpers';
export class BSVersionLibService{
@@ -1,4 +1,4 @@
import { splitIntoChunk } from "../../../helpers/array.helpers";
import { splitIntoChunk } from "../../../../shared/helpers/array.helpers";
import { BsvMapDetail } from "shared/models/maps";
import { BsvPlaylist, SearchParams } from "shared/models/maps/beat-saver.model";
import { BeatSaverApiService } from "./beat-saver-api.service";
@@ -1,6 +1,6 @@
import fetch from "node-fetch";
import { ApiResult } from "renderer/models/api/api.model";
import { MSGetQuery, MSGetQueryFilter, MSGetResponse } from "shared/models/model-saber/model-saber.model";
import { MSGetQuery, MSGetQueryFilter, MSGetResponse } from "../../../../shared/models/models/model-saber.model";
export class ModelSaberApiService {
@@ -1,5 +1,6 @@
import { MSGetQuery, MSGetQueryFilter, MSModel } from "shared/models/model-saber/model-saber.model";
import { MSGetQuery, MSGetQueryFilterType, MSModel, MSModelPlatform } from "../../../../shared/models/models/model-saber.model";
import { ModelSaberApiService } from "./model-saber-api.service";
import log from "electron-log";
export class ModelSaberService {
@@ -10,6 +11,8 @@ export class ModelSaberService {
return ModelSaberService.instance;
}
private readonly modelsHashCache: Map<string, MSModel> = new Map(); // key: hash, value: model
private readonly modelSaberApi: ModelSaberApiService;
private constructor(){
@@ -21,8 +24,8 @@ export class ModelSaberService {
const query: MSGetQuery = {
start: 0,
end: 1,
platform: "pc",
filter: [{type: "id", value: id}]
platform: MSModelPlatform.PC,
filter: [{type: MSGetQueryFilterType.ID, value: id}]
}
try{
@@ -37,6 +40,42 @@ export class ModelSaberService {
return res.data[`${id}`];
}
catch(e){
log.error(e);
return null;
}
}
public async getModelByHash(hash: string): Promise<MSModel>{
if(this.modelsHashCache.has(hash)){
return this.modelsHashCache.get(hash);
}
const query: MSGetQuery = {
start: 0,
end: 1,
platform: MSModelPlatform.PC,
filter: [{type: MSGetQueryFilterType.Hash, value: hash}]
}
try{
const res = await this.modelSaberApi.searchModel(query);
if(res.status !== 200){ return null;}
if(Object.keys(res.data).length === 0){
return null;
}
const model = Array.from(Object.values(res.data)).at(0);
this.modelsHashCache.set(hash, model);
return model
}
catch(e){
log.error(e);
return null;
}
@@ -5,7 +5,7 @@ import { BSVersion } from "shared/bs-version.interface";
import { LocalMapsManagerService } from "./additional-content/local-maps-manager.service";
import { BSLocalVersionService } from "./bs-local-version.service";
import { FolderLinkerService, LinkOptions } from "./folder-linker.service";
import { allSettled } from "../helpers/promise.helpers";
import { allSettled } from "../../shared/helpers/promise.helpers";
export class VersionFolderLinkerService {