From 8ac7ad42215a2f4cb71b276f2406270da071bbc4 Mon Sep 17 00:00:00 2001 From: flx-sta <50131232+flx-sta@users.noreply.github.com> Date: Fri, 4 Oct 2024 10:41:44 -0700 Subject: [PATCH] migrate unlink discord to pokerogue-api --- .env.development | 2 +- src/account.ts | 2 +- src/plugins/api/api.ts | 74 ++++++++++++++++ .../api/models/LinkAccountToDiscordId.ts | 4 + src/plugins/api/pokerogue-admin-api.ts | 27 ++++++ src/plugins/api/pokerogue-api.ts | 86 ++++++------------- src/ui/admin-ui-handler.ts | 19 ++-- src/ui/menu-ui-handler.ts | 5 +- src/utils.ts | 2 +- 9 files changed, 143 insertions(+), 78 deletions(-) create mode 100644 src/plugins/api/api.ts create mode 100644 src/plugins/api/models/LinkAccountToDiscordId.ts create mode 100644 src/plugins/api/pokerogue-admin-api.ts diff --git a/.env.development b/.env.development index d2f5934cee7..f107186293b 100644 --- a/.env.development +++ b/.env.development @@ -1,4 +1,4 @@ -VITE_BYPASS_LOGIN=0 +VITE_BYPASS_LOGIN=0 # TODO: revert to `1` VITE_BYPASS_TUTORIAL=0 VITE_SERVER_URL=http://localhost:8001 VITE_DISCORD_CLIENT_ID=1234567890 diff --git a/src/account.ts b/src/account.ts index 974c61788d9..c012e44425e 100644 --- a/src/account.ts +++ b/src/account.ts @@ -1,5 +1,5 @@ import { bypassLogin } from "./battle-scene"; -import { pokerogueApi } from "./plugins/api/pokerogue-api"; +import { pokerogueApi } from "#app/plugins/api/pokerogue-api"; import * as Utils from "./utils"; export interface UserInfo { diff --git a/src/plugins/api/api.ts b/src/plugins/api/api.ts new file mode 100644 index 00000000000..e31dbc4ad2b --- /dev/null +++ b/src/plugins/api/api.ts @@ -0,0 +1,74 @@ +import { SESSION_ID_COOKIE_NAME } from "#app/constants"; +import { getCookie } from "#app/utils"; + +type DataType = "json" | "form-urlencoded"; + +export abstract class Api { + //#region Fields + + protected readonly base: string; + + //#region Public + + constructor(base: string) { + this.base = base; + } + + //#region Protected + + /** + * Send a GET request. + * @param path The path to send the request to. + */ + protected async doGet(path: string) { + return this.doFetch(path, { method: "GET" }); + } + + /** + * Send a POST request. + * @param path THe path to send the request to. + * @param bodyData The body-data to send. + * @param dataType The data-type of the {@linkcode bodyData}. + */ + protected async doPost(path: string, bodyData?: D, dataType: DataType = "json") { + let body: string | undefined = undefined; + const headers: HeadersInit = {}; + + if (bodyData) { + if (dataType === "json") { + body = typeof bodyData === "string" ? bodyData : JSON.stringify(bodyData); + headers["Content-Type"] = "application/json"; + } else if (dataType === "form-urlencoded") { + if (bodyData instanceof Object) { + body = new URLSearchParams(Object.entries(bodyData).map(([k, v]) => [k, v.toString()])).toString(); + } else { + console.warn("Could not add body data to form-urlencoded!", bodyData); + } + headers["Content-Type"] = "application/x-www-form-urlencoded"; + } else { + console.warn(`Unsupported data type: ${dataType}`); + body = String(bodyData); + headers["Content-Type"] = "text/plain"; + } + } + + return await this.doFetch(path, { method: "POST", body, headers }); + } + + /** + * A generic request helper. + * @param path The path to send the request to. + * @param config The request {@linkcode RequestInit | Configuration}. + */ + protected async doFetch(path: string, config: RequestInit): Promise { + config.headers = { + ...config.headers, + Authorization: getCookie(SESSION_ID_COOKIE_NAME), + "Content-Type": config.headers?.["Content-Type"] ?? "application/json", + }; + + console.log(`Sending ${config.method ?? "GET"} request to: `, this.base + path, config); + + return await fetch(this.base + path, config); + } +} diff --git a/src/plugins/api/models/LinkAccountToDiscordId.ts b/src/plugins/api/models/LinkAccountToDiscordId.ts new file mode 100644 index 00000000000..3e8500634cc --- /dev/null +++ b/src/plugins/api/models/LinkAccountToDiscordId.ts @@ -0,0 +1,4 @@ +export interface LinkAccountToDiscordIdRequest { + username: string; + discordId: string; +} diff --git a/src/plugins/api/pokerogue-admin-api.ts b/src/plugins/api/pokerogue-admin-api.ts new file mode 100644 index 00000000000..3da9055d4f4 --- /dev/null +++ b/src/plugins/api/pokerogue-admin-api.ts @@ -0,0 +1,27 @@ +import { Api } from "#app/plugins/api/api"; +import type { LinkAccountToDiscordIdRequest } from "#app/plugins/api/models/LinkAccountToDiscordId"; + +export class PokerogueAdminApi extends Api { + /** + * Links an account to a discord id. + * @param linkData The {@linkcode LinkAccountToDiscordIdRequest} to send + * @returns `true` if successful, `false` if not + */ + public async linkAccountToDiscordId(linkData: LinkAccountToDiscordIdRequest) { + try { + const linkArr = Object.entries(linkData).map(([key, value]) => [key, String(value)]); + const params = new URLSearchParams(linkArr); + const response = await this.doPost("/admin/account/discord-link", params, "form-urlencoded"); + + if (response.ok) { + return true; + } else { + console.warn("Could not link account with discord!", response.status, response.statusText); + } + } catch (err) { + console.warn("Could not link account with discord!", err); + } + + return false; + } +} diff --git a/src/plugins/api/pokerogue-api.ts b/src/plugins/api/pokerogue-api.ts index ad924f0a3cd..7b68e0223f5 100644 --- a/src/plugins/api/pokerogue-api.ts +++ b/src/plugins/api/pokerogue-api.ts @@ -1,28 +1,29 @@ import type { PokerogueApiClearSessionData } from "#app/@types/pokerogue-api"; import { loggedInUser } from "#app/account"; import { MAX_INT_ATTR_VALUE, SESSION_ID_COOKIE_NAME } from "#app/constants"; +import { Api } from "#app/plugins/api/api"; +import type { AccountInfoResponse } from "#app/plugins/api/models/AccountInfo"; +import type { AccountLoginRequest, AccountLoginResponse } from "#app/plugins/api/models/AccountLogin"; +import type { TitleStatsResponse } from "#app/plugins/api/models/TitleStats"; +import type { UpdateAllSavedataRequest } from "#app/plugins/api/models/UpdateAllSavedata"; +import type { UpdateSessionSavedataRequest } from "#app/plugins/api/models/UpdateSessionSavedata"; +import type { UpdateSystemSavedataRequest } from "#app/plugins/api/models/UpdateSystemSavedata"; +import type { VerifySavedataResponse } from "#app/plugins/api/models/VerifySavedata"; import type { SessionSaveData } from "#app/system/game-data"; import type { RankingEntry, ScoreboardCategory } from "#app/ui/daily-run-scoreboard"; -import { getCookie, removeCookie, setCookie } from "#app/utils"; -import type { AccountInfoResponse } from "./models/AccountInfo"; -import type { AccountLoginRequest, AccountLoginResponse } from "./models/AccountLogin"; -import type { TitleStatsResponse } from "./models/TitleStats"; -import type { UpdateAllSavedataRequest } from "./models/UpdateAllSavedata"; -import type { UpdateSessionSavedataRequest } from "./models/UpdateSessionSavedata"; -import type { UpdateSystemSavedataRequest } from "./models/UpdateSystemSavedata"; -import type { VerifySavedataResponse } from "./models/VerifySavedata"; +import { removeCookie, setCookie } from "#app/utils"; +import { PokerogueAdminApi } from "#app/plugins/api/pokerogue-admin-api"; -type DataType = "json" | "form-urlencoded"; - -export class PokerogueApi { +export class PokerogueApi extends Api { //#region Fields - private readonly base: string; + public readonly admin: PokerogueAdminApi; //#region Public constructor(base: string) { - this.base = base; + super(base); + this.admin = new PokerogueAdminApi(base); } /** @@ -370,61 +371,26 @@ export class PokerogueApi { } } - //#region Private - /** - * Send a GET request. - * @param path The path to send the request to. + * Unlink the currently logged in user from Discord. + * @returns `true` if unlinking was successful, `false` if not */ - private async doGet(path: string) { - return this.doFetch(path, { method: "GET" }); - } - - /** - * Send a POST request. - * @param path THe path to send the request to. - * @param bodyData The body-data to send. - * @param dataType The data-type of the {@linkcode bodyData}. - */ - private async doPost(path: string, bodyData: D, dataType: DataType = "json") { - let body: string = ""; - const headers: HeadersInit = {}; - - if (dataType === "json") { - body = typeof bodyData === "string" ? bodyData : JSON.stringify(bodyData); - headers["Content-Type"] = "application/json"; - } else if (dataType === "form-urlencoded") { - if (bodyData instanceof Object) { - body = new URLSearchParams(Object.entries(bodyData).map(([k, v]) => [k, v.toString()])).toString(); + public async unlinkDiscord() { + try { + const response = await this.doPost("/unlink/discord"); + if (response.ok) { + return true; } else { - console.warn("Could not add body data to form-urlencoded!", bodyData); + console.warn(`Unlink failed (${response.status}: ${response.statusText})`); } - headers["Content-Type"] = "application/x-www-form-urlencoded"; - } else { - console.warn(`Unsupported data type: ${dataType}`); - body = String(bodyData); - headers["Content-Type"] = "text/plain"; + } catch (err) { + console.warn("Could not unlink discord!", err); } - return await this.doFetch(path, { method: "POST", body, headers }); + return false; } - /** - * A generic request helper. - * @param path The path to send the request to. - * @param config The request {@linkcode RequestInit | Configuration}. - */ - private async doFetch(path: string, config: RequestInit): Promise { - config.headers = { - ...config.headers, - Authorization: getCookie(SESSION_ID_COOKIE_NAME), - "Content-Type": config.headers?.["Content-Type"] ?? "application/json", - }; - - console.log(`Sending ${config.method ?? "GET"} request to: `, this.base + path, config); - - return await fetch(this.base + path, config); - } + //#region Private private async isLocalMode(): Promise { return ( diff --git a/src/ui/admin-ui-handler.ts b/src/ui/admin-ui-handler.ts index c48138853fc..4e69cb6e76b 100644 --- a/src/ui/admin-ui-handler.ts +++ b/src/ui/admin-ui-handler.ts @@ -1,9 +1,9 @@ import BattleScene from "#app/battle-scene"; import { ModalConfig } from "./modal-ui-handler"; import { Mode } from "./ui"; -import * as Utils from "../utils"; import { FormModalUiHandler } from "./form-modal-ui-handler"; import { Button } from "#app/enums/buttons"; +import { pokerogueApi } from "#app/plugins/api/pokerogue-api"; export default class AdminUiHandler extends FormModalUiHandler { @@ -61,17 +61,14 @@ export default class AdminUiHandler extends FormModalUiHandler { if (!this.inputs[1].text) { return onFail("Discord Id is required"); } - Utils.apiPost("admin/account/discord-link", `username=${encodeURIComponent(this.inputs[0].text)}&discordId=${encodeURIComponent(this.inputs[1].text)}`, "application/x-www-form-urlencoded", true) - .then(response => { - if (!response.ok) { - console.error(response); + const [ usernameInput, discordIdInput ] = this.inputs; + pokerogueApi.admin.linkAccountToDiscordId({ username: usernameInput.text, discordId: discordIdInput.text }) + .then(isSuccess => { + if (isSuccess) { + usernameInput.setText(""); + discordIdInput.setText(""); } - this.inputs[0].setText(""); - this.inputs[1].setText(""); - this.scene.ui.revertMode(); - }) - .catch((err) => { - console.error(err); + this.scene.ui.revertMode(); }); return false; diff --git a/src/ui/menu-ui-handler.ts b/src/ui/menu-ui-handler.ts index 19247d95f23..6e476f39ee7 100644 --- a/src/ui/menu-ui-handler.ts +++ b/src/ui/menu-ui-handler.ts @@ -514,10 +514,7 @@ export default class MenuUiHandler extends MessageUiHandler { window.open(discordUrl, "_self"); return true; } else { - Utils.apiPost("/auth/discord/logout", undefined, undefined, true).then(res => { - if (!res.ok) { - console.error(`Unlink failed (${res.status}: ${res.statusText})`); - } + pokerogueApi.unlinkDiscord().then(_isSuccess => { updateUserInfo().then(() => this.scene.reset(true, true)); }); return true; diff --git a/src/utils.ts b/src/utils.ts index 132f9dd5393..feee203882c 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,7 +1,7 @@ import { MoneyFormat } from "#enums/money-format"; import { Moves } from "#enums/moves"; import i18next from "i18next"; -import { pokerogueApi } from "./plugins/api/pokerogue-api"; +import { pokerogueApi } from "#app/plugins/api/pokerogue-api"; export type nil = null | undefined;