From a326bc6d610f1a47fc8ac81f462d67785758025f Mon Sep 17 00:00:00 2001 From: MathieuG-P <40181755+Zagrios@users.noreply.github.com> Date: Sun, 26 Jun 2022 23:33:17 +0200 Subject: [PATCH] convert download to promises instead of events --- src/main/ipcs/bs-download-ipcs.ts | 10 +- src/main/services/bs-installer.service.ts | 108 +++++++++--------- .../services/bs-downloader.service.ts | 93 ++++++++------- src/renderer/services/ipc.service.ts | 19 ++- 4 files changed, 124 insertions(+), 106 deletions(-) diff --git a/src/main/ipcs/bs-download-ipcs.ts b/src/main/ipcs/bs-download-ipcs.ts index 047a0321..db76b380 100644 --- a/src/main/ipcs/bs-download-ipcs.ts +++ b/src/main/ipcs/bs-download-ipcs.ts @@ -23,11 +23,15 @@ export interface DownloadInfo { stay?: boolean } -ipcMain.on('bs-download.start', async (event, args: DownloadInfo) => { - BSInstallerService.getInstance().downloadBsVersion(args); +ipcMain.on('bs-download.start', async (event, request: IpcRequest) => { + BSInstallerService.getInstance().downloadBsVersion(request.args).then(res => { + UtilsService.getInstance().newIpcSenc(request.responceChannel, {success: true, data: res}); + }).catch(e => { + UtilsService.getInstance().newIpcSenc(request.responceChannel, {success: false, data: e}); + }); }); -ipcMain.on(`bs-download.${DownloadEventType.GUARD_CODE}`, async (event, args) => { +ipcMain.on(`bs-download.${"[2FA]" as DownloadEventType}`, async (event, args) => { BSInstallerService.getInstance().sendInputProcess(args); }); diff --git a/src/main/services/bs-installer.service.ts b/src/main/services/bs-installer.service.ts index 756fdfc9..e92def74 100644 --- a/src/main/services/bs-installer.service.ts +++ b/src/main/services/bs-installer.service.ts @@ -68,10 +68,10 @@ export class BSInstallerService{ } } - public downloadBsVersion(downloadInfos: DownloadInfo){ - if(this.downloadProcess?.connected){ this.utils.ipcSend(`bs-download.${DownloadEventType.ALREADY_DOAWNLOADING}`); return; } + public async downloadBsVersion(downloadInfos: DownloadInfo): Promise{ + if(this.downloadProcess?.connected){ return {type: "[AlreadyDownloading]"}; } const bsVersion = this.bsVersionService.getVersionDetailFromVersionNumber(downloadInfos.bsVersion.BSVersion); - if(!bsVersion){ this.utils.ipcSend(`bs-download.${DownloadEventType.ERROR}`); return; } + if(!bsVersion){ return {type: "[Error]"}; } this.utils.createFolderIfNotExist(this.installationFolder); this.downloadProcess = spawn( @@ -87,53 +87,56 @@ export class BSInstallerService{ {shell: true, cwd: this.installationFolder} ) - this.downloadProcess.stdout.on('data', async (data) => { - log.info("DL PROCESS OUT " ,data.toString()); - const matched = (data.toString() as string).match(/(?:\[(.*?)\])\|(?:\[(.*?)\]\|)?(.*?)(?=$|\[)/gm); - if(!matched || !matched.length){ return; } + return await new Promise((resolve, reject) => { - matched.forEach(match => { - const out = match.split("|"); - - if(out[0] === DownloadEventType.NOT_LOGGED_IN && downloadInfos.password){ - this.sendInputProcess(downloadInfos.password); - } - else if(out[0] === DownloadEventType.NOT_LOGGED_IN){ - this.downloadProcess.kill(); - this.utils.ipcSend(`bs-download.${DownloadEventType.NOT_LOGGED_IN}`, bsVersion); - } - else if(out[0] === DownloadEventType.GUARD_CODE){ - this.utils.ipcSend(`bs-download.${DownloadEventType.GUARD_CODE}`); - } - else if(out[0] === DownloadEventType.TWO_FA_CODE){ - this.utils.ipcSend(`bs-download.${DownloadEventType.GUARD_CODE}`); - } - else if(out[0] === DownloadEventType.PROGESS || (out[0] === DownloadEventType.VALIDATION && parseFloat(out[1]) < 100)){ - this.utils.ipcSend(`bs-download.${DownloadEventType.PROGESS}`, parseFloat(out[1])); - } - else if(out[0] === DownloadEventType.FINISH || (out[0] === DownloadEventType.VALIDATION && parseFloat(out[1]) == 100)){ - this.utils.ipcSend(`bs-download.${DownloadEventType.FINISH}`); this.downloadProcess.kill(); - } - else if(out[0] === DownloadEventType.ERROR){ - this.utils.ipcSend(`bs-download.${DownloadEventType.ERROR}`); - log.error("Download Event, Error", data.toString()) - } + this.downloadProcess.stdout.on('data', data => { + const matched = (data.toString() as string).match(/(?:\[(.*?)\])\|(?:\[(.*?)\]\|)?(.*?)(?=$|\[)/gm) ?? []; + + matched.forEach(match => { + const out = match.split("|"); + + if(out[0] === "[Password]" as DownloadEventType && downloadInfos.password){ + this.sendInputProcess(downloadInfos.password); + } + else if(out[0] === "[Password]" as DownloadEventType){ + this.downloadProcess.kill(); + resolve({type: "[Password]", data: bsVersion}); + } + else if(out[0] === "[2FA]" as DownloadEventType){ + resolve({type: "[2FA]"}); + } + else if(out[0] === "[2FA]" as DownloadEventType){ + resolve({type: "[2FA]"}); + } + else if(out[0] === "[Progress]" as DownloadEventType || (out[0] === "[Validated]" as DownloadEventType && parseFloat(out[1]) < 100)){ + this.utils.newIpcSenc(`bs-download.${"[Progress]" as DownloadEventType}`, {success: true, data: parseFloat(out[1])}); + } + else if(out[0] === "[Finished]" as DownloadEventType || (out[0] === "[Validated]" as DownloadEventType && parseFloat(out[1]) == 100)){ + resolve({type: "[Finished]"}); + this.downloadProcess.kill(); + } + else if(out[0] === "[Error]" as DownloadEventType){ + reject(out); + log.error("Download Event, Error", data.toString()); + } + }); + + }) + + this.downloadProcess.stdout.on('error', (err) => { + log.error("BS-DOWNLOAD ERROR", err.toString()); + reject(err); + }); + this.downloadProcess.stderr.on('data', (err) => { + log.error("BS-DOWNLOAD ERROR", err.toString()); + reject(err); + }); + this.downloadProcess.stderr.on('error', (err) => { + log.error("BS-DOWNLOAD ERROR", err.toString()); + reject(err); }); - - }) - this.downloadProcess.stdout.on('error', (err) => { - log.error("BS-DOWNLOAD ERROR", err.toString()); - this.utils.ipcSend(`bs-download.${DownloadEventType.ERROR}`); - }); - this.downloadProcess.stderr.on('data', (err) => { - log.error("BS-DOWNLOAD ERROR", err.toString()); - this.utils.ipcSend(`bs-download.${DownloadEventType.ERROR}`); - }); - this.downloadProcess.stderr.on('error', (err) => { - log.error("BS-DOWNLOAD ERROR", err.toString()); - this.utils.ipcSend(`bs-download.${DownloadEventType.ERROR}`); - }); + }) } } @@ -153,13 +156,4 @@ export interface DownloadEvent{ data?: any, } -export enum DownloadEventType{ - NOT_LOGGED_IN = "[Password]", - GUARD_CODE = "[Guard]", - TWO_FA_CODE = "[2FA]", - PROGESS = "[Progress]", - VALIDATION = "[Validated]", - FINISH = "[Finished]", - ALREADY_DOAWNLOADING = "[AlreadyDownloading]", - ERROR = "[Error]", -} +export type DownloadEventType = "[Password]" | "[Guard]" | "[2FA]" | "[Progress]" | "[Validated]" | "[Finished]" | "[AlreadyDownloading]" | "[Error]"; diff --git a/src/renderer/services/bs-downloader.service.ts b/src/renderer/services/bs-downloader.service.ts index 2462a294..30690c06 100644 --- a/src/renderer/services/bs-downloader.service.ts +++ b/src/renderer/services/bs-downloader.service.ts @@ -1,7 +1,9 @@ -import { BehaviorSubject } from 'rxjs'; +import { DownloadEvent } from 'main/services/bs-installer.service'; +import { BehaviorSubject, distinctUntilChanged, Observable, Subscription } from 'rxjs'; import { IpcResponse } from 'shared/models/ipc-models.model'; import { DownloadInfo } from '../../main/ipcs/bs-download-ipcs'; import { BSVersion } from '../../main/services/bs-version-manager.service' +import { AuthUserService } from './auth-user.service'; import { BSVersionManagerService } from './bs-version-manager.service'; import { IpcService } from './ipc.service'; import { ModalExitCode, ModalService, ModalType } from './modale.service'; @@ -10,55 +12,33 @@ export class BsDownloaderService{ private static instance: BsDownloaderService; - private readonly modalService: ModalService = ModalService.getInsance(); + private readonly modalService: ModalService; private readonly ipcService: IpcService; - private readonly bsVersionManager: BSVersionManagerService = BSVersionManagerService.getInstance(); + private readonly bsVersionManager: BSVersionManagerService; + public readonly authService: AuthUserService; public readonly currentBsVersionDownload$: BehaviorSubject = new BehaviorSubject(null); public readonly downloadProgress$: BehaviorSubject = new BehaviorSubject(0); public readonly selectedBsVersion$: BehaviorSubject = new BehaviorSubject(null); - public static getInstance(): BsDownloaderService{ if(!BsDownloaderService.instance){ BsDownloaderService.instance = new BsDownloaderService(); } return BsDownloaderService.instance; } private constructor(){ - this.asignListerners(); this.ipcService = IpcService.getInstance(); + this.modalService = ModalService.getInsance(); + this.bsVersionManager = BSVersionManagerService.getInstance(); + this.authService = AuthUserService.getInstance(); + this.asignListerners(); } private asignListerners(): void{ - window.electron.ipcRenderer.on(`bs-download.[Password]`, async (bsVersion: BSVersion) => { - const res = await this.modalService.openModal(ModalType.STEAM_LOGIN); - if(res.exitCode !== ModalExitCode.COMPLETED){ return; } - if(res.data.stay){ localStorage.setItem("username", res.data.username); } - window.electron.ipcRenderer.sendMessage('bs-download.start', {bsVersion: bsVersion, username: res.data.username, password: res.data.password, stay: res.data.stay} as DownloadInfo) - this.currentBsVersionDownload$.next(bsVersion); - }); - - window.electron.ipcRenderer.on("bs-download.[Guard]", async () => { - const res = await this.modalService.openModal(ModalType.GUARD_CODE); - if(res.exitCode != ModalExitCode.COMPLETED){ return; } - window.electron.ipcRenderer.sendMessage("bs-download.[Guard]", res.data); - }); - - window.electron.ipcRenderer.on("bs-download.[Finished]", async () => { - this.downloadProgress$.next(0); - this.currentBsVersionDownload$.next(null); - this.selectedBsVersion$.next(null); - this.bsVersionManager.askInstalledVersions(); - }); - - window.electron.ipcRenderer.on("bs-download.[Progress]", async (progress: number) => { - this.downloadProgress$.next(progress); - }); - - window.electron.ipcRenderer.on("bs-download.[Error]", async () => { - this.currentBsVersionDownload$.next(null); - this.downloadProgress$.next(0); + + this.ipcService.watch("bs-download.[Progress]").pipe(distinctUntilChanged()).subscribe(response => { + this.downloadProgress$.next(response.data); }); this.currentBsVersionDownload$.subscribe(version => { @@ -67,23 +47,52 @@ export class BsDownloaderService{ }); } - public async download(bsVersion?: BSVersion): Promise{ - if(!bsVersion){ bsVersion = this.selectedBsVersion$.value; } - let username = localStorage.getItem("username"); - if(!username){ + private resetDownload(): void{ + this.currentBsVersionDownload$.next(null); + this.downloadProgress$.next(0); + this.selectedBsVersion$.next(null); + } + + public async send2FA(): Promise>{ + const res = await this.modalService.openModal(ModalType.GUARD_CODE); + if(res.exitCode !== ModalExitCode.COMPLETED){ return {success: false}; } + + return this.ipcService.send('bs-download.2FA', {args: res.data}); + } + + public async download(bsVersion: BSVersion): Promise>{ + let promise; + if(!this.authService.sessionExist()){ const res = await this.modalService.openModal(ModalType.STEAM_LOGIN); - if(res.exitCode !== ModalExitCode.COMPLETED){ return; } - if(res.data.stay){ localStorage.setItem("username", res.data.username); } - window.electron.ipcRenderer.sendMessage('bs-download.start', {bsVersion: bsVersion, username: res.data.username, password: res.data.password, stay: res.data.stay} as DownloadInfo); + if(res.exitCode !== ModalExitCode.COMPLETED){ return {success: false}; } + this.authService.setSteamSession(res.data.username, res.data.stay); + promise = this.ipcService.send('bs-download.start', {args: {bsVersion: bsVersion, username: res.data.username, password: res.data.password, stay: res.data.stay}}); } else{ - window.electron.ipcRenderer.sendMessage('bs-download.start', {bsVersion: bsVersion, username: username} as DownloadInfo); + promise = this.ipcService.send('bs-download.start', {args: {bsVersion: bsVersion, username: this.authService.getSteamUsername()}}); } this.currentBsVersionDownload$.next(bsVersion); + + return promise.then(res => { + if(res.success){ + if(res.data.type === "[Password]"){ + this.authService.deleteSteamSession(); + return this.download(bsVersion); + } + else if(res.data.type === "[2FA]"){ + return this.send2FA().then(res => { + this.resetDownload(); + return res; + }); + } + } + this.resetDownload(); + return res; + }); } public get isDownloading(): boolean{ - return !!this.currentBsVersionDownload$.value || !!this.downloadProgress$.value; + return !!this.currentBsVersionDownload$.value; } public async getInstallationFolder(): Promise{ diff --git a/src/renderer/services/ipc.service.ts b/src/renderer/services/ipc.service.ts index 67722fac..f1d3b0cf 100644 --- a/src/renderer/services/ipc.service.ts +++ b/src/renderer/services/ipc.service.ts @@ -5,12 +5,16 @@ export class IpcService { private static instance: IpcService; + private readonly channelObservables: Map>>; + public static getInstance(): IpcService{ if(!IpcService.instance){ IpcService.instance = new IpcService(); } return IpcService.instance; } - private constructor(){} + private constructor(){ + this.channelObservables = new Map>>(); + } public send(channel: string, request?: IpcRequest): Promise>{ if(!request){ request = {args: null, responceChannel: null}; } @@ -29,12 +33,19 @@ export class IpcService { window.electron.ipcRenderer.sendMessage(channel, request); } - public watch(channel: string): Observable{ - return new Observable(observer => { + public watch(channel: string): Observable>{ + + if(this.channelObservables.has(channel)){ return this.channelObservables.get(channel) as Observable>; } + + const obs = new Observable>(observer => { window.electron.ipcRenderer.on(channel, res => { observer.next(res); }); - }); + }) + + this.channelObservables.set(channel, obs); + + return obs; } } \ No newline at end of file