mirror of
https://github.com/Zagrios/bs-manager.git
synced 2026-07-03 14:08:25 +02:00
[feature] add the possibility to enter oculus token manually
This commit is contained in:
@@ -680,7 +680,9 @@
|
||||
"title": "Mit Meta verbinden",
|
||||
"body":{
|
||||
"token-needed": "Dein Meta-Verbindungstoken wird benötigt, um Beat Saber herunterzuladen.",
|
||||
"need-cookie-enabled": "Beim Einloggen in Meta wird ein Anmeldefenster geöffnet und du kannst dann den Anmeldevorgang beginnen. Bitte stelle sicher, dass Cookies akzeptiert werden, sonst könnten wir deinen Token zum Starten des Downloads nicht abrufen."
|
||||
"need-cookie-enabled": "Beim Einloggen in Meta wird ein Anmeldefenster geöffnet und du kannst dann den Anmeldevorgang beginnen. Bitte stelle sicher, dass Cookies akzeptiert werden, sonst könnten wir deinen Token zum Starten des Downloads nicht abrufen.",
|
||||
"enter-token-manually": "Mein Anmelde-Token manuell eingeben",
|
||||
"enter-token-manually-tooltip": "Dies ermöglicht es Ihnen, Ihren Anmelde-Token einzugeben, ohne sich über Meta anzumelden."
|
||||
},
|
||||
"stay":"Angemeldet bleiben",
|
||||
"connect-to-meta": "Mit Meta verbinden"
|
||||
@@ -694,6 +696,16 @@
|
||||
},
|
||||
"not-remind-me": "Nicht mehr erinnern",
|
||||
"understood": "Verstanden"
|
||||
},
|
||||
"enter-meta-token": {
|
||||
"title": "Meta-Token",
|
||||
"body": {
|
||||
"need-token": "Um Beat Saber herunterzuladen, ist Ihr Meta-Anmelde-Token erforderlich.",
|
||||
"how-obtain-token": "Wie erhalte ich mein Meta-Token?",
|
||||
"input-label": "Meta-Token",
|
||||
"token-is-invalid": "Das Token ist ungültig."
|
||||
},
|
||||
"valid-btn": "Validieren"
|
||||
}
|
||||
},
|
||||
"maps": {
|
||||
|
||||
@@ -680,7 +680,9 @@
|
||||
"title": "Connect to Meta",
|
||||
"body":{
|
||||
"token-needed": "Your Meta connection token is required to download Beat Saber.",
|
||||
"need-cookie-enabled": "By logging into Meta, a login window will open and you can then start the login process. Please ensure to accept cookies, otherwise, we might not be able to retrieve your token to start the download."
|
||||
"need-cookie-enabled": "By logging into Meta, a login window will open and you can then start the login process. Please ensure to accept cookies, otherwise, we might not be able to retrieve your token to start the download.",
|
||||
"enter-token-manually": "Enter my login token manually",
|
||||
"enter-token-manually-tooltip": "This will allow you to enter your login token without going through Meta login."
|
||||
},
|
||||
"stay":"Remember me",
|
||||
"connect-to-meta": "Connect to Meta"
|
||||
@@ -694,6 +696,16 @@
|
||||
},
|
||||
"not-remind-me": "Do not remind me",
|
||||
"understood": "Understood"
|
||||
},
|
||||
"enter-meta-token": {
|
||||
"title": "Meta Token",
|
||||
"body": {
|
||||
"need-token": "To download Beat Saber, your Meta login token is required.",
|
||||
"how-obtain-token": "How do I obtain my Meta Token?",
|
||||
"input-label": "Meta Token",
|
||||
"token-is-invalid": "The Token is invalid."
|
||||
},
|
||||
"valid-btn": "Validate"
|
||||
}
|
||||
},
|
||||
"maps": {
|
||||
|
||||
@@ -679,7 +679,9 @@
|
||||
"title": "Conexión a Meta",
|
||||
"body":{
|
||||
"token-needed": "Tu token de conexión a Meta es necesario para descargar Beat Saber.",
|
||||
"need-cookie-enabled": "Al conectarte a Meta, se abrirá una ventana de inicio de sesión y entonces podrás empezar el proceso de conexión. Asegúrate de aceptar las cookies, de lo contrario, podríamos no poder recuperar tu token para iniciar la descarga."
|
||||
"need-cookie-enabled": "Al conectarte a Meta, se abrirá una ventana de inicio de sesión y entonces podrás empezar el proceso de conexión. Asegúrate de aceptar las cookies, de lo contrario, podríamos no poder recuperar tu token para iniciar la descarga.",
|
||||
"enter-token-manually": "Ingresar mi token de inicio de sesión manualmente",
|
||||
"enter-token-manually-tooltip": "Esto te permitirá ingresar tu token de inicio de sesión sin pasar por el inicio de sesión de Meta."
|
||||
},
|
||||
"stay":"Recuérdame",
|
||||
"connect-to-meta": "Conectarse a Meta"
|
||||
@@ -693,6 +695,16 @@
|
||||
},
|
||||
"not-remind-me": "No volver a recordármelo",
|
||||
"understood": "Entendido"
|
||||
},
|
||||
"enter-meta-token": {
|
||||
"title": "Token de Meta",
|
||||
"body": {
|
||||
"need-token": "Para descargar Beat Saber, se requiere su token de inicio de sesión de Meta.",
|
||||
"how-obtain-token": "¿Cómo obtengo mi Token de Meta?",
|
||||
"input-label": "Token de Meta",
|
||||
"token-is-invalid": "El Token es inválido."
|
||||
},
|
||||
"valid-btn": "Validar"
|
||||
}
|
||||
},
|
||||
"maps": {
|
||||
|
||||
@@ -676,7 +676,9 @@
|
||||
"title": "Connexion à Meta",
|
||||
"body":{
|
||||
"token-needed": "Votre token de connexion à Meta est nécessaire pour télécharger Beat Saber.",
|
||||
"need-cookie-enabled": "En vous connectant à Meta, une fenêtre de connexion s'ouvrira et vous pourrez alors débuter le processus de connexion. Veillez à bien accepter les cookies sinon quoi, il se pourrait que l'on n'arrive pas à récupérer votre token pour démarrer le téléchargement."
|
||||
"need-cookie-enabled": "En vous connectant à Meta, une fenêtre de connexion s'ouvrira et vous pourrez alors débuter le processus de connexion. Veillez à bien accepter les cookies sinon quoi, il se pourrait que l'on n'arrive pas à récupérer votre token pour démarrer le téléchargement.",
|
||||
"enter-token-manually": "Entrer mon token de connexion manuellement",
|
||||
"enter-token-manually-tooltip": "Cela vous permettra d'entrer votre token de connexion sans passer par la connexion Meta."
|
||||
},
|
||||
"stay":"Se souvenir de moi",
|
||||
"connect-to-meta": "Se connecter à Meta"
|
||||
@@ -690,6 +692,16 @@
|
||||
},
|
||||
"not-remind-me": "Ne plus me rappeler",
|
||||
"understood": "J'ai compris"
|
||||
},
|
||||
"enter-meta-token": {
|
||||
"title": "Token Meta",
|
||||
"body": {
|
||||
"need-token": "Pour télécharger Beat Saber, votre token de connexion à Meta est nécessaire.",
|
||||
"how-obtain-token": "Comment obtenir mon Token Meta ?",
|
||||
"input-label": "Token Meta",
|
||||
"token-is-invalid": "Le Token est invalide."
|
||||
},
|
||||
"valid-btn": "Valider"
|
||||
}
|
||||
},
|
||||
"maps": {
|
||||
|
||||
@@ -680,7 +680,9 @@
|
||||
"title": "Подключение к Meta",
|
||||
"body":{
|
||||
"token-needed": "Для скачивания Beat Saber необходим ваш токен подключения к Meta.",
|
||||
"need-cookie-enabled": "При входе в Meta откроется окно входа, и вы сможете начать процесс входа. Пожалуйста, убедитесь, что вы приняли cookies, иначе мы можем не суметь получить ваш токен для начала загрузки."
|
||||
"need-cookie-enabled": "При входе в Meta откроется окно входа, и вы сможете начать процесс входа. Пожалуйста, убедитесь, что вы приняли cookies, иначе мы можем не суметь получить ваш токен для начала загрузки.",
|
||||
"enter-token-manually": "Ввести мой токен входа вручную",
|
||||
"enter-token-manually-tooltip": "Это позволит вам ввести ваш токен входа без прохождения через вход в Meta."
|
||||
},
|
||||
"stay":"Запомнить меня",
|
||||
"connect-to-meta": "Подключиться к Meta"
|
||||
@@ -694,6 +696,16 @@
|
||||
},
|
||||
"not-remind-me": "Больше не напоминать",
|
||||
"understood": "Понял"
|
||||
},
|
||||
"enter-meta-token": {
|
||||
"title": "Мета Токен",
|
||||
"body": {
|
||||
"need-token": "Для загрузки Beat Saber требуется ваш токен входа в Meta.",
|
||||
"how-obtain-token": "Как получить мой Мета Токен?",
|
||||
"input-label": "Мета Токен",
|
||||
"token-is-invalid": "Токен недействителен."
|
||||
},
|
||||
"valid-btn": "Подтвердить"
|
||||
}
|
||||
},
|
||||
"maps": {
|
||||
|
||||
@@ -7,10 +7,11 @@ import { OculusDownloader } from "../../models/oculus-downloader.class";
|
||||
import { Cookie, session } from "electron";
|
||||
import { Progression, ensurePathNotAlreadyExist } from "../../helpers/fs.helpers";
|
||||
import { BSLocalVersionService } from "../bs-local-version.service";
|
||||
import { Observable, finalize, from, map, switchMap } from "rxjs";
|
||||
import { Observable, finalize, from, map, of, switchMap } from "rxjs";
|
||||
import path from "path";
|
||||
import { DownloadInfo } from "./bs-steam-downloader.service";
|
||||
import { BsStore } from "../../../shared/models/bs-store.enum";
|
||||
import { isOculusTokenValid } from "../../../shared/helpers/oculus.helpers";
|
||||
|
||||
export class BsOculusDownloaderService {
|
||||
|
||||
@@ -37,34 +38,7 @@ export class BsOculusDownloaderService {
|
||||
}
|
||||
|
||||
private isUserTokenValid(token: string): boolean{
|
||||
|
||||
// Code taken 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\d{15}/)){
|
||||
log.info("Token matches /OC[0-9}{15}/ which usually indicates a changed oculus store token");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
return isOculusTokenValid(token, log.info);
|
||||
}
|
||||
|
||||
private isCookieValid(cookie: Cookie): boolean {
|
||||
@@ -147,7 +121,9 @@ export class BsOculusDownloaderService {
|
||||
|
||||
let downloadVersion: BSVersion
|
||||
|
||||
return from(this.getUserTokenFromMetaAuth(downloadInfo.stay)).pipe(
|
||||
const tokenObs$ = downloadInfo.token ? of(downloadInfo.token) : from(this.getUserTokenFromMetaAuth(downloadInfo.stay));
|
||||
|
||||
return tokenObs$.pipe(
|
||||
switchMap(token => {
|
||||
if(!downloadInfo.isVerification){
|
||||
return this.createDownloadVersion(downloadInfo.bsVersion).then(({version, dest}) => ({token, version, dest}))
|
||||
@@ -169,7 +145,9 @@ export class BsOculusDownloaderService {
|
||||
|
||||
let downloadVersion: BSVersion
|
||||
|
||||
return from(this.getAuthToken()).pipe(
|
||||
const tokenObs$ = downloadInfo.token ? of(downloadInfo.token) : from(this.getAuthToken());
|
||||
|
||||
return tokenObs$.pipe(
|
||||
map(token => {
|
||||
if(!token){
|
||||
throw new CustomError("No Meta auth token was found in cookies for auto download", "NO_META_AUTH_TOKEN");
|
||||
|
||||
@@ -159,6 +159,7 @@ export interface DownloadInfo {
|
||||
bsVersion: BSVersion;
|
||||
isVerification?: boolean;
|
||||
stay?: boolean;
|
||||
token?: string;
|
||||
}
|
||||
|
||||
export interface DownloadSteamInfo extends DownloadInfo {
|
||||
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
import { BsmButton } from "renderer/components/shared/bsm-button.component";
|
||||
import { ModalComponent, ModalExitCode } from "../../../../services/modale.service";
|
||||
import { BsmImage } from "renderer/components/shared/bsm-image.component";
|
||||
import BeatWaiting from "../../../../../../assets/images/apngs/beat-impatient.png";
|
||||
import { useTranslation } from "renderer/hooks/use-translation.hook";
|
||||
import { useState } from "react";
|
||||
import { isOculusTokenValid } from "shared/helpers/oculus.helpers";
|
||||
import { logRenderError } from "renderer";
|
||||
|
||||
export const EnterMetaTokenModal: ModalComponent<string> = ({resolver}) => {
|
||||
|
||||
const t = useTranslation();
|
||||
|
||||
const [token, setToken] = useState("");
|
||||
const [showToken, setShowToken] = useState(false);
|
||||
|
||||
const submit = () => {
|
||||
resolver({exitCode: ModalExitCode.COMPLETED, data: token});
|
||||
}
|
||||
|
||||
const cancel = () => {
|
||||
resolver({exitCode: ModalExitCode.CANCELED});
|
||||
}
|
||||
|
||||
const isTokenValid = (() => {
|
||||
return isOculusTokenValid(token, logRenderError);
|
||||
})();
|
||||
|
||||
return (
|
||||
<form className="flex flex-col w-80 gap-4">
|
||||
<h1 className="text-3xl uppercase tracking-wide w-full text-center">{t("modals.enter-meta-token.title")}</h1>
|
||||
|
||||
<BsmImage className="h-20 w-20 mx-auto" image={BeatWaiting}/>
|
||||
|
||||
<p>{t("modals.enter-meta-token.body.need-token")}</p>
|
||||
|
||||
<a href="https://github.com/Zagrios/bs-manager/wiki/How-to-obtain-your-Oculus-Token" target="_blank" className="underline">{t("modals.enter-meta-token.body.how-obtain-token")}</a>
|
||||
|
||||
<div>
|
||||
<div className="flex flex-row items-center justify-between">
|
||||
<label className="font-bold cursor-pointer tracking-wide inline-block" htmlFor="meta_token">{t("modals.enter-meta-token.body.input-label")}</label>
|
||||
{!isTokenValid && token.length > 0 && (
|
||||
<span className="text-orange-700 dark:text-orange-400 text-xs whitespace-normal min-w-0">{t("modals.enter-meta-token.body.token-is-invalid")}</span>
|
||||
)}
|
||||
</div>
|
||||
<div className="bg-light-main-color-1 dark:bg-main-color-1 rounded-md flex box-border h-9">
|
||||
<input className="grow px-1 py-[2px] outline-none bg-transparent" onChange={e => setToken(e.target.value)} value={token} type={showToken ? "text" : "password"} name="meta_token" id="meta_token" placeholder="OCAStr43sdx2..." />
|
||||
<BsmButton className="shrink-0 m-1 rounded-md p-0.5 !bg-light-main-color-3 dark:!bg-main-color-3" icon={showToken ? "eye-cross" : "eye"} withBar={false} onClick={() => setShowToken(prev => !prev)} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-row gap-2">
|
||||
<BsmButton className="rounded-md flex justify-center items-center transition-all h-9 w-full" typeColor="cancel" text="misc.cancel" withBar={false} onClick={cancel}/>
|
||||
<BsmButton className="rounded-md flex justify-center items-center transition-all h-9 w-full" typeColor="primary" text="modals.enter-meta-token.valid-btn" withBar={false} onClick={submit} disabled={!isTokenValid}/>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
);
|
||||
}
|
||||
+19
-2
@@ -4,17 +4,24 @@ import { BsmButton } from "renderer/components/shared/bsm-button.component";
|
||||
import { useTranslation } from "renderer/hooks/use-translation.hook";
|
||||
import { MetaIcon } from "renderer/components/svgs/icons/meta-icon.component";
|
||||
import { BsmCheckbox } from "renderer/components/shared/bsm-checkbox.component";
|
||||
import Tippy from "@tippyjs/react";
|
||||
|
||||
export const LoginToMetaModal: ModalComponent<boolean> = ({ resolver }) => {
|
||||
type ReturnType = { method: MetaAuthMethod.META, stay: boolean } | { method: MetaAuthMethod.MANUAL };
|
||||
|
||||
export const LoginToMetaModal: ModalComponent<ReturnType> = ({ resolver }) => {
|
||||
|
||||
const t = useTranslation();
|
||||
|
||||
const [stay, setStay] = useState(false);
|
||||
|
||||
const submit = () => {
|
||||
resolver({ exitCode: ModalExitCode.COMPLETED, data: stay });
|
||||
resolver({ exitCode: ModalExitCode.COMPLETED, data: { method: MetaAuthMethod.META, stay } });
|
||||
};
|
||||
|
||||
const enterTokenManually = () => {
|
||||
resolver({ exitCode: ModalExitCode.COMPLETED, data: { method: MetaAuthMethod.MANUAL } });
|
||||
}
|
||||
|
||||
return (
|
||||
<form className="flex flex-col justify-center items-center w-96 gap-4">
|
||||
<h1 className="text-3xl uppercase tracking-wide w-full text-center">{t("modals.connect-to-meta.title")}</h1>
|
||||
@@ -32,6 +39,16 @@ export const LoginToMetaModal: ModalComponent<boolean> = ({ resolver }) => {
|
||||
</div>
|
||||
|
||||
<BsmButton className="rounded-md flex justify-center items-center transition-all h-10 w-full" typeColor="primary" text="modals.connect-to-meta.connect-to-meta" withBar={false} onClick={submit}/>
|
||||
|
||||
<Tippy className="!bg-neutral-900" arrow={false} content={t("modals.connect-to-meta.body.enter-token-manually-tooltip")} >
|
||||
<p className="text-sm italic underline text-center -translate-y-1 leading-3 cursor-pointer" onClick={enterTokenManually}>{t("modals.connect-to-meta.body.enter-token-manually")}</p>
|
||||
</Tippy>
|
||||
|
||||
</form>
|
||||
);
|
||||
};
|
||||
|
||||
export enum MetaAuthMethod {
|
||||
MANUAL = "manual",
|
||||
META = "meta"
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ const ipc = IpcService.getInstance();
|
||||
const themeService = ThemeService.getInstance();
|
||||
|
||||
window.onerror = (...data) => {
|
||||
ipc.sendLazy("log-error", { args: data });
|
||||
logRenderError(data);
|
||||
};
|
||||
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
@@ -58,4 +58,8 @@ if (launcherContainer) {
|
||||
});
|
||||
}
|
||||
|
||||
export function logRenderError(...params: unknown[]){
|
||||
ipc.sendLazy("log-error", { args: params });
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -6,11 +6,12 @@ import { ProgressBarService } from "../progress-bar.service";
|
||||
import { CustomError } from "shared/models/exceptions/custom-error.class";
|
||||
import { NotificationService } from "../notification.service";
|
||||
import { ModalExitCode, ModalService } from "../modale.service";
|
||||
import { LoginToMetaModal } from "renderer/components/modal/modal-types/bs-downgrade/login-to-meta-modal.component";
|
||||
import { LoginToMetaModal, MetaAuthMethod } from "renderer/components/modal/modal-types/bs-downgrade/login-to-meta-modal.component";
|
||||
import { DownloaderServiceInterface } from "./bs-store-downloader.interface";
|
||||
import { AbstractBsDownloaderService } from "./abstract-bs-downloader.service";
|
||||
import { DownloadInfo } from "main/services/bs-version-download/bs-steam-downloader.service";
|
||||
import { MetaAuthErrorCodes, OculusDownloaderErrorCodes } from "shared/models/bs-version-download/oculus-download.model";
|
||||
import { EnterMetaTokenModal } from "renderer/components/modal/modal-types/bs-downgrade/enter-meta-token-modal.component";
|
||||
|
||||
export class OculusDownloaderService extends AbstractBsDownloaderService implements DownloaderServiceInterface{
|
||||
|
||||
@@ -103,16 +104,26 @@ export class OculusDownloaderService extends AbstractBsDownloaderService impleme
|
||||
|
||||
if(autoDownload){ return autoDownload; }
|
||||
|
||||
const [completed, stay] = await this.modals.openModal(LoginToMetaModal).then(res => [res.exitCode === ModalExitCode.COMPLETED, res.data]);
|
||||
const {exitCode, data} = await this.modals.openModal(LoginToMetaModal)
|
||||
|
||||
if(!completed){
|
||||
return completed;
|
||||
if(exitCode !== ModalExitCode.COMPLETED){
|
||||
return false
|
||||
}
|
||||
|
||||
return lastValueFrom(this.startDownloadBsVersion({ bsVersion, isVerification, stay })).then(() => true);
|
||||
if(data.method === MetaAuthMethod.META){
|
||||
return lastValueFrom(this.startDownloadBsVersion({ bsVersion, isVerification, stay: data.stay })).then(() => true);
|
||||
}
|
||||
|
||||
})().then(() => {
|
||||
if(autoDownloadFailed){
|
||||
const tokenRes = await this.modals.openModal(EnterMetaTokenModal);
|
||||
|
||||
if(tokenRes.exitCode !== ModalExitCode.COMPLETED){
|
||||
return false;
|
||||
}
|
||||
|
||||
return lastValueFrom(this.startDownloadBsVersion({ bsVersion, isVerification, token: tokenRes.data })).then(() => true);
|
||||
|
||||
})().then(res => {
|
||||
if(autoDownloadFailed || !res){
|
||||
return bsVersion;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
export function isOculusTokenValid(token: string, logger?: (...args: unknown[]) => void): boolean{
|
||||
|
||||
// Code taken from "https://github.com/ComputerElite/QuestAppVersionSwitcher" (TokenTools.cs)
|
||||
|
||||
logger?.("Checking if Oculus user token is valid");
|
||||
|
||||
if(!token){
|
||||
logger?.("Oculus user token is empty");
|
||||
return false;
|
||||
}
|
||||
if(token.includes("%")){
|
||||
logger?.("Token contains %. Token most likely comes from an uri and won't work");
|
||||
return false;
|
||||
}
|
||||
if(!token.startsWith("OC")){
|
||||
logger?.("Token does not start with OC.");
|
||||
return false;
|
||||
}
|
||||
if(token.includes("|")){
|
||||
logger?.("Token contains | which usually indicates an application token which is not valid for user tokens");
|
||||
return false;
|
||||
}
|
||||
if(token.match(/OC\d{15}/)){
|
||||
logger?.("Token matches /OC[0-9}{15}/ which usually indicates a changed oculus store token");
|
||||
return false;
|
||||
}
|
||||
|
||||
logger?.("Oculus user token is valid");
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user