advencement on oneclick playlists

This commit is contained in:
MathieuG-P
2022-12-22 00:57:06 +01:00
parent 16aa65afed
commit d556350eef
11 changed files with 240 additions and 34 deletions
@@ -61,7 +61,7 @@ export class LocalMapsManagerService {
});
}
private async getMapsFolderPath(version?: BSVersion): Promise<string>{
public async getMapsFolderPath(version?: BSVersion): Promise<string>{
if(version){ return path.join(await this.localVersion.getVersionPath(version), this.LEVELS_ROOT_FOLDER, this.CUSTOM_LEVELS_FOLDER); }
const sharedMapsPath = path.join(this.installLocation.sharedMapsPath, this.CUSTOM_LEVELS_FOLDER);
if(!(await this.utils.pathExist(sharedMapsPath))){
@@ -1,7 +1,6 @@
import path from "path";
import { BehaviorSubject, Observable } from "rxjs";
import { BSVersion } from "shared/bs-version.interface";
import { BsvPlaylist, BsvPlaylistPage } from "shared/models/maps/beat-saver.model";
import { BSLocalVersionService } from "../bs-local-version.service";
import { DeepLinkService } from "../deep-link.service";
import { RequestService } from "../request.service";
@@ -12,8 +11,11 @@ import { isValidUrl } from "../../helpers/url.helpers";
import { ipcMain } from "electron";
import { WindowManagerService } from "../window-manager.service";
import { IpcRequest } from "shared/models/ipc";
import { BPList } from "shared/models/playlists/playlist.interface";
import { readFileSync } from "fs";
import { BPList, DownloadPlaylistProgression } from "shared/models/playlists/playlist.interface";
import { copyFileSync, readFileSync } from "fs";
import { BeatSaverService } from "../thrid-party/beat-saver/beat-saver.service";
import { copySync } from "fs-extra";
import { timer } from "rxjs";
export class LocalPlaylistsManagerService {
@@ -36,6 +38,7 @@ export class LocalPlaylistsManagerService {
private readonly request: RequestService;
private readonly deepLink: DeepLinkService;
private readonly windows: WindowManagerService;
private readonly bsaver: BeatSaverService;
private constructor(){
this.maps = LocalMapsManagerService.getInstance();
@@ -44,6 +47,7 @@ export class LocalPlaylistsManagerService {
this.request = RequestService.getInstance();
this.deepLink = DeepLinkService.getInstance();
this.windows = WindowManagerService.getInstance();
this.bsaver = BeatSaverService.getInstance();
this.deepLink.addLinkOpenedListener(this.DEEP_LINKS.BeatSaver, link => {
@@ -69,29 +73,54 @@ export class LocalPlaylistsManagerService {
return splited[idIndex + 1];
}
private async downloadPlaylistFile(playlist: BsvPlaylist, version: BSVersion): Promise<string>{
private async getPlaylistsFolder(version?: BSVersion){
if(!version){ throw "Playlists are not available to be linked yet" }
const versionFolder = await this.versions.getVersionPath(version);
const bpListUrl = playlist.downloadURL;
const bsListDest = path.join(versionFolder, this.PLAYLISTS_FOLDER, path.basename(bpListUrl));
const folder = path.join(versionFolder, this.PLAYLISTS_FOLDER);
return this.request.downloadFile(bpListUrl, bsListDest);
await this.utils.createFolderIfNotExist(folder)
return folder;
}
private async installBPListFile(bpListUrlOrPath: string, version: BSVersion): Promise<string>{
const playlistFolder = await this.getPlaylistsFolder(version);
const bpListDest = path.join(playlistFolder, path.basename(bpListUrlOrPath));
console.log("INSTALL BPLIST", bpListUrlOrPath, playlistFolder);
if(this.utils.pathExist(bpListUrlOrPath)){
console.log("PATH EXIST", bpListUrlOrPath);
console.log("COPY", bpListUrlOrPath, bpListDest);
copyFileSync(bpListUrlOrPath, bpListDest);
}
else{
await this.request.downloadFile(bpListUrlOrPath, bpListDest);
}
return bpListDest;
}
private async readPlaylistFile(path: string): Promise<BPList>{
if(!this.utils.pathExist(path)){ return null; }
if(!this.utils.pathExist(path)){ throw `bplist file not exist at ${path}`; }
const content = readFileSync(path).toJSON();
const rawContent = readFileSync(path).toString();
return JSON.parse(rawContent);
// TODO
}
private openOneClickDownloadPlaylistWindow(downloadUrl: string): void{
// TODO make once
ipcMain.on("one-click-playlist-info", async (event, req: IpcRequest<void>) => {
this.utils.ipcSend(req.responceChannel, {success: true, data: {bpListUrl: downloadUrl, id: this.getPlaylistIdFromDownloadUrl(downloadUrl)}});
});
@@ -100,30 +129,98 @@ export class LocalPlaylistsManagerService {
}
public downloadPlaylist(playlistPage: BsvPlaylistPage, version: BSVersion): Observable<string[]>{
public downloadPlaylist(bpListUrl: string, version: BSVersion): Observable<DownloadPlaylistProgression>{
const res = new BehaviorSubject<string[]>([]);
console.log("DOWNLOAD PLAYLIST");
const res = new BehaviorSubject<DownloadPlaylistProgression>({progression: 0, current: null, downloadedMaps: [], mapsPath: [], bpListPath: ""});
const sub = res.subscribe(process => {
console.log("PROGRESS", process);
this.utils.ipcSend("download-playlist-progress", {success: true, data: process});
}, err => {
this.utils.ipcSend("download-playlist-progress", {success: false, error: err});
});
const observer = async () => {
try{
const bpListPath = await this.downloadPlaylistFile(playlistPage.playlist, version);
for(const map of playlistPage.maps){
const mapPath = await this.maps.downloadMap(map.map, version);
res.next([...res.value, mapPath]);
try{
const bpListPath = await this.installBPListFile(bpListUrl, version);
res.next({...res.value, bpListPath});
const bpList = await this.readPlaylistFile(bpListPath);
for(const song of bpList.songs){
if(!song.key){ continue; }
const map = await this.bsaver.getMapDetailsById(song.key);
res.next({
...res.value,
current: map,
progression: ((res.value.downloadedMaps.length + .5) / bpList.songs.length) * 100
});
const mapPath = await this.maps.downloadMap(map, version);
const progression = ((res.value.downloadedMaps.length + 1) / bpList.songs.length) * 100;
res.next({
...res.value,
downloadedMaps: [...res.value.downloadedMaps, map],
mapsPath: [...res.value.mapsPath, mapPath],
progression
});
}
res.next([...res.value, bpListPath]);
res.complete();
}
catch(e){
res.error(e);
}
res.complete();
}
observer();
observer().finally(() => sub.unsubscribe());
return res.asObservable();
}
public async oneClickInstallPlaylist(bpListUrl: string): Promise<void>{
const versions = await this.versions.getInstalledVersions();
await timer(2);
const firstVersion = versions.shift();
const fistVersionLinked = await this.maps.versionIsLinked(firstVersion);
const {bpListPath, mapsPath} = await this.downloadPlaylist(bpListUrl, firstVersion).toPromise();
for(const version of versions){
await this.installBPListFile(bpListPath, version);
const versionIsLinked = await this.maps.versionIsLinked(version);
if(fistVersionLinked && versionIsLinked){ continue; }
for(const mapPath of mapsPath){
const versionMapsFolder = await this.maps.getMapsFolderPath(version);
const mapDest = path.join(versionMapsFolder, path.basename(mapPath));
console.log("COPY MAP", mapPath, mapDest);
copySync(mapPath, mapDest, {overwrite: true});
}
}
}
}
+2
View File
@@ -98,8 +98,10 @@ export class UtilsService{
public ipcSend<T = any>(channel: string, response: IpcResponse<T>): void{
try {
console.log(channel, ...Array.from(this.windows.keys()), response);
Array.from(this.windows.values()).forEach(window => window.webContents.send(channel, response));
} catch (error) {
console.log("ERREUR", error);
log.error(error);
}
}
@@ -37,8 +37,6 @@ export class WindowManagerService{
public openWindow(windowType: AppWindow, options?: BrowserWindowConstructorOptions): Promise<BrowserWindow>{
const window = new BrowserWindow({...this.appWindowsOptions[windowType], ...this.baseWindowOption, ...options});
console.log({...this.appWindowsOptions[windowType], ...this.baseWindowOption, ...options});
const promise = window.loadURL(resolveHtmlPath(windowType));
window.removeMenu();
window.setMenu(null);