start playlists management

This commit is contained in:
MathieuG-P
2022-12-20 03:00:51 +01:00
parent ee95df202d
commit 58faea04a3
5 changed files with 146 additions and 4 deletions
+2 -1
View File
@@ -17,6 +17,7 @@ import { WindowManagerService } from './services/window-manager.service';
import { DeepLinkService } from './services/deep-link.service';
import { AppWindow } from 'shared/models/window-manager/app-window.model';
import { LocalMapsManagerService } from './services/additional-content/local-maps-manager.service';
import { LocalPlaylistsManagerService } from './services/additional-content/local-playlists-manager.service';
export const PRELOAD_PATH = app.isPackaged ? path.join(__dirname, 'preload.js') : path.join(__dirname, '../../.erb/dll/preload.js')
@@ -57,7 +58,7 @@ const createWindow = async (window: AppWindow = "launcher.html") => {
const initServicesMustBeInitialized = () => {
LocalMapsManagerService.getInstance();
// Playlist
LocalPlaylistsManagerService.getInstance();
// Model
}
@@ -0,0 +1,81 @@
import path from "path";
import { BehaviorSubject } from "rxjs";
import { 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 { RequestService } from "../request.service";
import { UtilsService } from "../utils.service";
import { LocalMapsManagerService } from "./local-maps-manager.service";
export class LocalPlaylistsManagerService {
private static instance: LocalPlaylistsManagerService
public static getInstance(): LocalPlaylistsManagerService {
if (!LocalPlaylistsManagerService.instance) { LocalPlaylistsManagerService.instance = new LocalPlaylistsManagerService(); }
return LocalPlaylistsManagerService.instance;
}
private readonly PLAYLISTS_FOLDER = "Playlists";
private readonly DEEP_LINKS = {
BeatSaver: "bsplaylist",
};
private readonly versions: BSLocalVersionService;
private readonly maps: LocalMapsManagerService;
public readonly utils: UtilsService;
public readonly request: RequestService;
private constructor(){
this.maps = LocalMapsManagerService.getInstance();
this.versions = BSLocalVersionService.getInstance();
this.utils = UtilsService.getInstance();
this.request = RequestService.getInstance();
}
private getPlaylistIdFromDownloadUrl(url: string): string{
const splited = url.split("/")
const idIndex = splited.indexOf("id");
return splited[idIndex + 1];
}
private async downloadPlaylistFile(playlist: BsvPlaylist, version: BSVersion): Promise<string>{
const versionFolder = await this.versions.getVersionPath(version);
const bpListUrl = playlist.downloadURL;
const bsListDest = path.join(versionFolder, this.PLAYLISTS_FOLDER, path.basename(bpListUrl));
return this.request.downloadFile(bpListUrl, bsListDest);
}
public downloadPlaylist(playlistPage: BsvPlaylistPage, version: BSVersion): Observable<string[]>{
const res = new BehaviorSubject<string[]>([]);
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]);
}
res.next([...res.value, bpListPath]);
res.complete();
}
catch(e){
res.error(e);
}
}
observer();
return res.asObservable();
}
}
@@ -1,6 +1,6 @@
import { ApiResult } from "renderer/models/api/api.model";
import { BsvMapDetail } from "shared/models/maps";
import { MapFilter, SearchParams, SearchResponse } from "shared/models/maps/beat-saver.model";
import { BsvPlaylistPage, MapFilter, SearchParams, SearchResponse } from "shared/models/maps/beat-saver.model";
import fetch from "node-fetch"
export class BeatSaverApiService {
@@ -121,4 +121,14 @@ export class BeatSaverApiService {
}
public async getPlaylistDetails(id: number): Promise<ApiResult<BsvPlaylistPage>>{
const res = await fetch(`${this.bsaverApiUrl}/playlists/id/${id}`);
const data = await res.json() as BsvPlaylistPage;
return {status: res.status, data};
}
}
@@ -1,7 +1,8 @@
import { splitIntoChunk } from "../../../helpers/array-tools";
import { BsvMapDetail } from "shared/models/maps";
import { SearchParams } from "shared/models/maps/beat-saver.model";
import { BsvPlaylist, BsvPlaylistPage, SearchParams } from "shared/models/maps/beat-saver.model";
import { BeatSaverApiService } from "./beat-saver-api.service";
import { red } from "tailwindcss/colors";
export class BeatSaverService {
@@ -65,6 +66,13 @@ export class BeatSaverService {
}
public async getPlaylistPage(id: number): Promise<BsvPlaylistPage>{
const res = await this.bsaverApi.getPlaylistDetails(id);
return res.data;
}
}
+43 -1
View File
@@ -183,4 +183,46 @@ export interface SearchParams {
includeEmpty?: boolean
}
export type SearchOrder = "Latest"|"Relevance"|"Rating"|"Curated";
export type SearchOrder = "Latest"|"Relevance"|"Rating"|"Curated";
export interface BsvMapDetailWithOrder {
map: BsvMapDetail,
order: number
}
export interface BsvPlaylist {
createdAt: BsvInstant,
curatedAt: BsvInstant,
curator: BsvUserDetail,
deletedAt: BsvInstant,
description: string,
downloadURL: string,
name: string,
owner: BsvUserDetail,
playlistId: number,
playlistImage: string,
playlistImage512: string,
public: boolean,
songsChangedAt: BsvInstant,
stats: BsvPlaylistStats,
updatedAt: BsvInstant,
}
export interface BsvPlaylistStats {
avgScore: number,
downVotes: number,
mapperCount: number,
maxNps: number,
maxNpsTwoDP: number,
minNps: number,
minNpsTwoDP: number,
scoreOneDP: number,
totalDuration: number,
totalMaps: number,
upVotes: number
}
export interface BsvPlaylistPage {
maps: BsvMapDetailWithOrder[],
playlist: BsvPlaylist
}