Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Refactor] Pokerogue API client #4583

Merged
merged 59 commits into from
Nov 4, 2024
Merged
Show file tree
Hide file tree
Changes from 56 commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
c879a73
start migrating Utils.apiFetch to api class
flx-sta Oct 3, 2024
a1adc40
move dailyranking to api
flx-sta Oct 4, 2024
565d80f
use api in title-ui-handler
flx-sta Oct 4, 2024
cc7ce0c
remove: Utils.apiFetch
flx-sta Oct 4, 2024
9f63360
migrate `updateSystemSavedata` to api
flx-sta Oct 4, 2024
ebf8978
migrate clear session savedata to api
flx-sta Oct 4, 2024
3e3315d
migrate updateAllSavedata to api
flx-sta Oct 4, 2024
9df8a61
migrate `updateSessionSavedata` to api
flx-sta Oct 4, 2024
70f78d1
rename `api` to `pokerogue-api`
flx-sta Oct 4, 2024
8ac7ad4
migrate unlink discord to pokerogue-api
flx-sta Oct 4, 2024
8fa0d82
migrate unlink google to pokerogue-api
flx-sta Oct 4, 2024
9b18070
update pokerogue-api login
flx-sta Oct 4, 2024
13b4b0e
migrate register account to pokerogue-api
flx-sta Oct 4, 2024
2395451
remove Utils.apiPost
flx-sta Oct 4, 2024
ab6a191
reset overrides.ts
flx-sta Oct 4, 2024
0e3e128
chore: cleanup
flx-sta Oct 4, 2024
d927ed8
fix env.development
flx-sta Oct 4, 2024
e66bced
fix circular dependencies with api
flx-sta Oct 4, 2024
6468502
fix gamedata verify missing await
flx-sta Oct 4, 2024
e620c68
Merge branch 'beta' into refactor/api-requests
flx-sta Oct 4, 2024
673624a
fix daily api calls in daily-run-scorebard
flx-sta Oct 5, 2024
30b6d4e
fix discord-link request body being empty
flx-sta Oct 7, 2024
a8215d0
Merge branch 'beta' into refactor/api-requests
flx-sta Oct 7, 2024
17d44dd
add pokerogue-api test coverge
flx-sta Oct 7, 2024
f474ec0
add test-utils `getApiBaseUrl()` method
flx-sta Oct 7, 2024
1ad6d63
add pokerogue-admin-api test coverage
flx-sta Oct 7, 2024
8a60a45
add pokerogue-account-api test coverage
flx-sta Oct 7, 2024
41b8778
Merge branch 'beta' into refactor/api-requests
DayKev Oct 8, 2024
594b761
Merge branch 'beta' into refactor/api-requests
flx-sta Oct 8, 2024
bf4f793
add pokerogue-daily-api test coverage
flx-sta Oct 9, 2024
087bedd
add pokerogue-savedata-api test coverage
flx-sta Oct 9, 2024
ba51671
fix some test describes
flx-sta Oct 9, 2024
63e05aa
add pokerogue-session-savedata-api test coverage
flx-sta Oct 9, 2024
db10ca7
add pokerogue-system-savedata-api test coverage
flx-sta Oct 9, 2024
b409bc4
Merge branch 'beta' into refactor/api-requests
flx-sta Oct 9, 2024
856a12a
Merge branch 'beta' into refactor/api-requests
flx-sta Oct 9, 2024
1154d79
Merge branch 'beta' into refactor/api-requests
flx-sta Oct 9, 2024
aafbd00
fix tests
flx-sta Oct 9, 2024
952fc8d
Merge branch 'beta' into refactor/api-requests
flx-sta Oct 10, 2024
ce22229
fix tryExportData
flx-sta Oct 10, 2024
af32e42
Merge branch 'beta' into refactor/api-requests
flx-sta Oct 21, 2024
93d805e
Merge branch 'beta' into refactor/api-requests
flx-sta Oct 21, 2024
1ef836e
chore: fix menu-ui-handlers.ts
flx-sta Oct 21, 2024
7f999de
Merge branch 'beta' into refactor/api-requests
flx-sta Oct 25, 2024
eea9a88
fix admin-ui-handler (types)
flx-sta Oct 25, 2024
0de91ca
extend test-coverage for admin-api
flx-sta Oct 25, 2024
099550c
remove outdated code
flx-sta Oct 26, 2024
be45642
Merge branch 'beta' into refactor/api-requests
flx-sta Oct 26, 2024
80b9b7a
Merge branch 'beta' into refactor/api-requests
flx-sta Oct 28, 2024
2980738
Merge branch 'beta' into refactor/api-requests
flx-sta Oct 29, 2024
a97dafe
skip some clowning-around-encounter tests if events are active
flx-sta Oct 29, 2024
f2ee5a7
Merge branch 'beta' into refactor/api-requests
flx-sta Oct 29, 2024
111fe68
Merge branch 'beta' into refactor/api-requests
flx-sta Oct 30, 2024
23bc1e8
Merge branch 'beta' into refactor/api-requests
flx-sta Oct 31, 2024
f703cbb
Merge branch 'beta' into refactor/api-requests
DayKev Nov 2, 2024
63ed8de
Update src/system/game-data.ts
flx-sta Nov 3, 2024
254ec17
Merge branch 'beta' into refactor/api-requests
flx-sta Nov 4, 2024
ea84157
Revert "skip some clowning-around-encounter tests if events are active"
flx-sta Nov 4, 2024
dbda146
mark `localServerUrl` and `apiUrl` as deprecated
flx-sta Nov 4, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion global.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,5 @@ declare global {
*
* To set up your own server in a test see `game_data.test.ts`
*/
var i18nServer: SetupServerApi;
var server: SetupServerApi;
}
17 changes: 17 additions & 0 deletions src/@types/PokerogueAccountApi.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import type { UserInfo } from "#app/@types/UserInfo";

export interface AccountInfoResponse extends UserInfo {}

export interface AccountLoginRequest {
username: string;
password: string;
}

export interface AccountLoginResponse {
token: string;
}

export interface AccountRegisterRequest {
username: string;
password: string;
}
31 changes: 31 additions & 0 deletions src/@types/PokerogueAdminApi.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
export interface LinkAccountToDiscordIdRequest {
username: string;
discordId: string;
}

export interface UnlinkAccountFromDiscordIdRequest {
username: string;
discordId: string;
}

export interface LinkAccountToGoogledIdRequest {
username: string;
googleId: string;
}

export interface UnlinkAccountFromGoogledIdRequest {
username: string;
googleId: string;
}

export interface SearchAccountRequest {
username: string;
}

export interface SearchAccountResponse {
username: string;
discordId: string;
googleId: string;
lastLoggedIn: string;
registered: string;
}
4 changes: 4 additions & 0 deletions src/@types/PokerogueApi.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export interface TitleStatsResponse {
playerCount: number;
battleCount: number;
}
10 changes: 10 additions & 0 deletions src/@types/PokerogueDailyApi.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import type { ScoreboardCategory } from "#app/ui/daily-run-scoreboard";

export interface GetDailyRankingsRequest {
category: ScoreboardCategory;
page?: number;
}

export interface GetDailyRankingsPageCountRequest {
category: ScoreboardCategory;
}
8 changes: 8 additions & 0 deletions src/@types/PokerogueSavedataApi.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import type { SessionSaveData, SystemSaveData } from "#app/system/game-data";

export interface UpdateAllSavedataRequest {
system: SystemSaveData;
session: SessionSaveData;
sessionSlotId: number;
clientSessionId: string;
}
39 changes: 39 additions & 0 deletions src/@types/PokerogueSessionSavedataApi.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
export class UpdateSessionSavedataRequest {
slot: number;
trainerId: number;
secretId: number;
clientSessionId: string;
}

/** This is **NOT** similar to {@linkcode ClearSessionSavedataRequest} */
export interface NewClearSessionSavedataRequest {
slot: number;
clientSessionId: string;
}

export interface GetSessionSavedataRequest {
slot: number;
clientSessionId: string;
}

export interface DeleteSessionSavedataRequest {
slot: number;
clientSessionId: string;
}

/** This is **NOT** similar to {@linkcode NewClearSessionSavedataRequest} */
export interface ClearSessionSavedataRequest {
slot: number;
trainerId: number;
clientSessionId: string;
}

/**
* Pokerogue API response for path: `/savedata/session/clear`
*/
export interface ClearSessionSavedataResponse {
/** Contains the error message if any occured */
error?: string;
/** Is `true` if the request was successfully processed */
success?: boolean;
}
20 changes: 20 additions & 0 deletions src/@types/PokerogueSystemSavedataApi.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import type { SystemSaveData } from "#app/system/game-data";

export interface GetSystemSavedataRequest {
clientSessionId: string;
}

export class UpdateSystemSavedataRequest {
clientSessionId: string;
trainerId?: number;
secretId?: number;
}

export interface VerifySystemSavedataRequest {
clientSessionId: string;
}

export interface VerifySystemSavedataResponse {
valid: boolean;
systemData: SystemSaveData;
}
7 changes: 7 additions & 0 deletions src/@types/UserInfo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export interface UserInfo {
username: string;
lastSessionSlot: number;
discordId: string;
googleId: string;
hasAdminRole: boolean;
}
9 changes: 0 additions & 9 deletions src/@types/pokerogue-api.ts

This file was deleted.

26 changes: 8 additions & 18 deletions src/account.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,8 @@
import { pokerogueApi } from "#app/plugins/api/pokerogue-api";
import type { UserInfo } from "#app/@types/UserInfo";
import { bypassLogin } from "./battle-scene";
import * as Utils from "./utils";

export interface UserInfo {
username: string;
lastSessionSlot: integer;
discordId: string;
googleId: string;
hasAdminRole: boolean;
}

export let loggedInUser: UserInfo | null = null;
// This is a random string that is used to identify the client session - unique per session (tab or window) so that the game will only save on the one that the server is expecting
export const clientSessionId = Utils.randomString(32);
Expand Down Expand Up @@ -43,18 +37,14 @@ export function updateUserInfo(): Promise<[boolean, integer]> {
});
return resolve([ true, 200 ]);
}
Utils.apiFetch("account/info", true).then(response => {
if (!response.ok) {
resolve([ false, response.status ]);
pokerogueApi.account.getInfo().then(([ accountInfo, status ]) => {
if (!accountInfo) {
resolve([ false, status ]);
return;
} else {
loggedInUser = accountInfo;
resolve([ true, 200 ]);
}
return response.json();
}).then(jsonResponse => {
loggedInUser = jsonResponse;
resolve([ true, 200 ]);
}).catch(err => {
console.error(err);
resolve([ false, 500 ]);
});
});
}
6 changes: 6 additions & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,9 @@ export const PLAYER_PARTY_MAX_SIZE: number = 6;

/** Whether to use seasonal splash messages in general */
export const USE_SEASONAL_SPLASH_MESSAGES: boolean = false;

/** Name of the session ID cookie */
export const SESSION_ID_COOKIE_NAME: string = "pokerogue_sessionId";

/** Max value for an integer attribute in {@linkcode SystemSaveData} */
export const MAX_INT_ATTR_VALUE = 0x80000000;
12 changes: 4 additions & 8 deletions src/data/daily-run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { Starter } from "#app/ui/starter-select-ui-handler";
import * as Utils from "#app/utils";
import PokemonSpecies, { PokemonSpeciesForm, getPokemonSpecies, getPokemonSpeciesForm } from "#app/data/pokemon-species";
import { speciesStarterCosts } from "#app/data/balance/starters";
import { pokerogueApi } from "#app/plugins/api/pokerogue-api";

export interface DailyRunConfig {
seed: integer;
Expand All @@ -14,14 +15,9 @@ export interface DailyRunConfig {

export function fetchDailyRunSeed(): Promise<string | null> {
return new Promise<string | null>((resolve, reject) => {
Utils.apiFetch("daily/seed").then(response => {
if (!response.ok) {
resolve(null);
return;
}
return response.text();
}).then(seed => resolve(seed ?? null))
.catch(err => reject(err));
pokerogueApi.daily.getSeed().then(dailySeed => {
resolve(dailySeed);
});
});
}

Expand Down
8 changes: 4 additions & 4 deletions src/phases/game-over-phase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import * as Utils from "#app/utils";
import { PlayerGender } from "#enums/player-gender";
import { TrainerType } from "#enums/trainer-type";
import i18next from "i18next";
import { pokerogueApi } from "#app/plugins/api/pokerogue-api";

export class GameOverPhase extends BattlePhase {
private victory: boolean;
Expand Down Expand Up @@ -176,10 +177,9 @@ export class GameOverPhase extends BattlePhase {
If Online, execute apiFetch as intended
If Offline, execute offlineNewClear(), a localStorage implementation of newClear daily run checks */
if (this.victory) {
if (!Utils.isLocal) {
Utils.apiFetch(`savedata/session/newclear?slot=${this.scene.sessionSlotId}&clientSessionId=${clientSessionId}`, true)
.then(response => response.json())
.then(newClear => doGameOver(newClear));
if (!Utils.isLocal || Utils.isLocalServerConnected) {
pokerogueApi.savedata.session.newclear({ slot: this.scene.sessionSlotId, clientSessionId })
.then((success) => doGameOver(!!success));
} else {
this.scene.gameData.offlineNewClear(this.scene).then(result => {
doGameOver(result);
Expand Down
2 changes: 1 addition & 1 deletion src/phases/title-phase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ export class TitlePhase extends Phase {
};

// If Online, calls seed fetch from db to generate daily run. If Offline, generates a daily run based on current date.
if (!Utils.isLocal) {
if (!Utils.isLocal || Utils.isLocalServerConnected) {
fetchDailyRunSeed().then(seed => {
if (seed) {
generateDaily(seed);
Expand Down
91 changes: 91 additions & 0 deletions src/plugins/api/api-base.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import { SESSION_ID_COOKIE_NAME } from "#app/constants";
import { getCookie } from "#app/utils";

type DataType = "json" | "form-urlencoded";

export abstract class ApiBase {
//#region Fields

public readonly ERR_GENERIC: string = "There was an error";

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<D = undefined>(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 = this.toUrlSearchParams(bodyData).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<Response> {
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);
}

/**
* Helper to transform data to {@linkcode URLSearchParams}
* Any key with a value of `undefined` will be ignored.
* Any key with a value of `null` will be included.
* @param data the data to transform to {@linkcode URLSearchParams}
* @returns a {@linkcode URLSearchParams} representaton of {@linkcode data}
*/
protected toUrlSearchParams<D extends Record<string, any>>(data: D) {
const arr = Object.entries(data)
.map(([ key, value ]) => (value !== undefined ? [ key, String(value) ] : [ key, "" ]))
.filter(([ , value ]) => value !== "");

return new URLSearchParams(arr);
}
}
Loading
Loading