[feature] add function to get user oculus token + other small changes

This commit is contained in:
MathieuG-P
2023-09-28 20:16:02 +02:00
parent bd7d6b2f2e
commit 8bfe4caa5e
6 changed files with 125 additions and 13 deletions
@@ -0,0 +1,97 @@
import { BSVersion } from "../../shared/bs-version.interface";
import { WindowManagerService } from "./window-manager.service";
import { minToMs } from "../../shared/helpers/time.helpers";
import log from "electron-log";
export class BsOculusDownloaderService {
private static instance: BsOculusDownloaderService;
public static getInstance(): BsOculusDownloaderService {
if (!BsOculusDownloaderService.instance) {
BsOculusDownloaderService.instance = new BsOculusDownloaderService();
}
return BsOculusDownloaderService.instance;
}
private readonly windows: WindowManagerService;
private constructor() {
this.windows = WindowManagerService.getInstance();
}
private isUserTokenValid(token: string): boolean{
// Code take from "https://github.com/ComputerElite/QuestAppVersionSwitcher" (TokenTools.cs)
log.info("Checking if Oculus user token is valid");
if(!token){
log.info("Oculus user token is empty");
return false;
}
if(token.includes("%")){
log.info("Token contains %. Token most likely comes from an uri and won't work");
return false;
}
if(!token.startsWith("OC")){
log.info("Token does not start with OC.");
return false;
}
if(token.includes("|")){
log.info("Token contains | which usually indicates an application token which is not valid for user tokens");
return false;
}
if(token.match(/OC[0-9]{15}/)){
log.info("Token matches /OC[0-9}{15}/ which usually indicates a changed oculus store token");
return false;
}
return true;
}
public async getUserToken(): Promise<string>{
const redirectUrl = "https://developer.oculus.com/manage/";
const loginUrl = `https://auth.oculus.com/login/?redirect_uri=${encodeURIComponent(redirectUrl)}`;
const window = await this.windows.openWindow(loginUrl, { frame: true });
let timout: NodeJS.Timeout;
const promise = new Promise<string>((resolve, reject) => {
timout = setTimeout(() => {
reject(new Error("Trying to get Oculus user token timed out"));
window.close();
}, minToMs(5));
window.webContents.on("did-navigate", async (_, url) => {
if(!url.startsWith(redirectUrl)){ return; }
const token = (await window.webContents.session.cookies.get({ name: "oc_www_at" })).at(0)?.value;
if(!this.isUserTokenValid(token)){
return;
}
resolve(token);
});
window.on("closed", () => {
reject(new Error("Oculus login window closed by user"));
});
}).finally(() => {
if(!window.isDestroyed() && window.isClosable()){
window.close();
}
clearTimeout(timout);
});
return promise;
}
public downloadVersion(version: BSVersion){
return this.getUserToken();
}
}
+18 -11
View File
@@ -1,4 +1,4 @@
import { app, BrowserWindow, BrowserWindowConstructorOptions, shell } from "electron";
import { app, BrowserWindow, BrowserWindowConstructorOptions, shell, WebContents } from "electron";
import { resolveHtmlPath } from "../util";
import { UtilsService } from "./utils.service";
import { AppWindow } from "shared/models/window-manager/app-window.model";
@@ -10,6 +10,7 @@ export class WindowManagerService {
private static instance: WindowManagerService;
private readonly PRELOAD_PATH = app.isPackaged ? path.join(__dirname, "preload.js") : path.join(__dirname, "../../../.erb/dll/preload.js");
private readonly IS_DEBUG = process.env.NODE_ENV === "development" || process.env.DEBUG_PROD === "true"
private readonly utilsService: UtilsService = UtilsService.getInstance();
@@ -28,10 +29,10 @@ export class WindowManagerService {
show: false,
frame: false,
titleBarOverlay: false,
webPreferences: { preload: this.PRELOAD_PATH, webSecurity: false },
webPreferences: { preload: this.PRELOAD_PATH, webSecurity: !this.IS_DEBUG },
};
private readonly windows: Map<AppWindow, BrowserWindow> = new Map<AppWindow, BrowserWindow>();
private readonly windows = new Map<string, BrowserWindow>();
public static getInstance(): WindowManagerService {
if (!WindowManagerService.instance) {
@@ -42,8 +43,7 @@ export class WindowManagerService {
private constructor() {}
public openWindow(windowType: AppWindow, options?: BrowserWindowConstructorOptions): Promise<BrowserWindow> {
const window = new BrowserWindow({ ...this.appWindowsOptions[windowType], ...this.baseWindowOption, ...options });
private handleNewWindow(url: AppWindow, window: BrowserWindow){
window.webContents.setWindowOpenHandler(({ url }) => {
if(isValidUrl(url)){
@@ -51,12 +51,13 @@ export class WindowManagerService {
}
return { action: "deny"}
})
});
const promise = window.loadURL(resolveHtmlPath(windowType));
window.removeMenu();
window.setMenu(null);
const promise = window.loadURL(isValidUrl(url) ? url : resolveHtmlPath(url));
window.once("ready-to-show", () => {
if (!window) {
throw new Error('"window" is not defined');
@@ -65,18 +66,24 @@ export class WindowManagerService {
});
window.once("closed", () => {
this.windows.delete(windowType);
this.windows.delete(url);
if (!this.windows.size) {
app.quit();
}
});
this.windows.set(windowType, window);
this.utilsService.setMainWindows(this.windows);
this.windows.set(url, window);
this.utilsService.setMainWindows(this.windows as Map<AppWindow, BrowserWindow>); // TODO : remove
return promise.then(() => window);
}
public openWindow(windowType: AppWindow, options?: BrowserWindowConstructorOptions): Promise<BrowserWindow> {
const window = new BrowserWindow({ ...(this.appWindowsOptions[windowType] ?? {}), ...this.baseWindowOption, ...options });
return this.handleNewWindow(windowType, window);
}
public closeAllWindows(except?: AppWindow) {
this.windows.forEach((window, key) => {
if (key === except) {
@@ -96,7 +103,7 @@ export class WindowManagerService {
return this.windows.get(window);
}
public getAppWindowFromWebContents(sender: Electron.WebContents): AppWindow {
public getAppWindowFromWebContents(sender: WebContents): AppWindow {
return Array.from(this.windows.entries()).find(([, value]) => value.webContents.id === sender.id)[0];
}