This repository has been archived on 2024-10-29. You can view files and clone it, but cannot push or open issues or pull requests.
Files
scoresaber-reloadedv3/src/common/service/impl/scoresaber.ts

225 lines
7.2 KiB
TypeScript
Raw Normal View History

2024-09-14 18:40:39 +01:00
import ScoreSaberLeaderboardScoresPageToken from "@/common/model/token/scoresaber/score-saber-leaderboard-scores-page-token";
import ScoreSaberPlayerScoresPageToken from "@/common/model/token/scoresaber/score-saber-player-scores-page-token";
import { ScoreSaberPlayerSearchToken } from "@/common/model/token/scoresaber/score-saber-player-search-token";
import ScoreSaberPlayerToken from "@/common/model/token/scoresaber/score-saber-player-token";
import { ScoreSaberPlayersPageToken } from "@/common/model/token/scoresaber/score-saber-players-page-token";
import { ScoreSort } from "../score-sort";
import Service from "../service";
2024-09-27 23:04:14 +01:00
import ScoreSaberPlayer, {
getScoreSaberPlayerFromToken,
} from "@/common/model/player/impl/scoresaber-player";
2024-09-08 22:35:32 +01:00
const API_BASE = "https://scoresaber.com/api";
2024-09-11 20:10:27 +01:00
const SEARCH_PLAYERS_ENDPOINT = `${API_BASE}/players?search=:query`;
const LOOKUP_PLAYER_ENDPOINT = `${API_BASE}/player/:id/full`;
const LOOKUP_PLAYERS_ENDPOINT = `${API_BASE}/players?page=:page`;
const LOOKUP_PLAYERS_BY_COUNTRY_ENDPOINT = `${API_BASE}/players?page=:page&countries=:country`;
2024-09-11 20:10:27 +01:00
const LOOKUP_PLAYER_SCORES_ENDPOINT = `${API_BASE}/player/:id/scores?limit=:limit&sort=:sort&page=:page`;
const LOOKUP_LEADERBOARD_SCORES_ENDPOINT = `${API_BASE}/leaderboard/by-id/:id/scores?page=:page`;
2024-09-08 22:35:32 +01:00
2024-09-13 20:04:04 +01:00
class ScoreSaberService extends Service {
2024-09-11 15:38:04 +01:00
constructor() {
super("ScoreSaber");
}
2024-09-08 22:35:32 +01:00
/**
* Gets the players that match the query.
*
* @param query the query to search for
* @param useProxy whether to use the proxy or not
* @returns the players that match the query, or undefined if no players were found
*/
2024-09-27 23:04:14 +01:00
async searchPlayers(
query: string,
useProxy = true,
): Promise<ScoreSaberPlayerSearchToken | undefined> {
const before = performance.now();
2024-09-11 15:38:04 +01:00
this.log(`Searching for players matching "${query}"...`);
2024-09-14 18:40:39 +01:00
const results = await this.fetch<ScoreSaberPlayerSearchToken>(
2024-09-11 20:10:27 +01:00
useProxy,
2024-09-27 23:04:14 +01:00
SEARCH_PLAYERS_ENDPOINT.replace(":query", query),
2024-09-11 20:10:27 +01:00
);
2024-09-12 00:20:50 +01:00
if (results === undefined) {
return undefined;
}
2024-09-11 20:10:27 +01:00
if (results.players.length === 0) {
2024-09-08 22:35:32 +01:00
return undefined;
}
2024-09-11 20:10:27 +01:00
results.players.sort((a, b) => a.rank - b.rank);
2024-09-27 23:04:14 +01:00
this.log(
`Found ${results.players.length} players in ${(performance.now() - before).toFixed(0)}ms`,
);
2024-09-11 20:10:27 +01:00
return results;
2024-09-08 22:35:32 +01:00
}
/**
* Looks up a player by their ID.
*
* @param playerId the ID of the player to look up
* @param useProxy whether to use the proxy or not
* @returns the player that matches the ID, or undefined
*/
2024-09-27 23:04:14 +01:00
async lookupPlayer(
playerId: string,
useProxy = true,
): Promise<ScoreSaberPlayer | undefined> {
const before = performance.now();
2024-09-11 15:38:04 +01:00
this.log(`Looking up player "${playerId}"...`);
2024-09-27 23:04:14 +01:00
const token = await this.fetch<ScoreSaberPlayerToken>(
useProxy,
LOOKUP_PLAYER_ENDPOINT.replace(":id", playerId),
);
if (token === undefined) {
return undefined;
}
2024-09-27 23:04:14 +01:00
this.log(
`Found player "${playerId}" in ${(performance.now() - before).toFixed(0)}ms`,
);
return getScoreSaberPlayerFromToken(token);
}
/**
* Lookup players on a specific page
*
* @param page the page to get players for
* @param useProxy whether to use the proxy or not
* @returns the players on the page, or undefined
*/
2024-09-27 23:04:14 +01:00
async lookupPlayers(
page: number,
useProxy = true,
): Promise<ScoreSaberPlayersPageToken | undefined> {
const before = performance.now();
this.log(`Looking up players on page "${page}"...`);
const response = await this.fetch<ScoreSaberPlayersPageToken>(
2024-09-13 13:45:04 +01:00
useProxy,
2024-09-27 23:04:14 +01:00
LOOKUP_PLAYERS_ENDPOINT.replace(":page", page.toString()),
2024-09-13 13:45:04 +01:00
);
if (response === undefined) {
return undefined;
}
2024-09-27 23:04:14 +01:00
this.log(
`Found ${response.players.length} players in ${(performance.now() - before).toFixed(0)}ms`,
);
return response;
}
/**
* Lookup players on a specific page and country
*
* @param page the page to get players for
* @param country the country to get players for
* @param useProxy whether to use the proxy or not
* @returns the players on the page, or undefined
*/
async lookupPlayersByCountry(
page: number,
country: string,
2024-09-27 23:04:14 +01:00
useProxy = true,
): Promise<ScoreSaberPlayersPageToken | undefined> {
const before = performance.now();
2024-09-27 23:04:14 +01:00
this.log(
`Looking up players on page "${page}" for country "${country}"...`,
);
const response = await this.fetch<ScoreSaberPlayersPageToken>(
useProxy,
2024-09-27 23:04:14 +01:00
LOOKUP_PLAYERS_BY_COUNTRY_ENDPOINT.replace(
":page",
page.toString(),
).replace(":country", country),
2024-09-13 13:45:04 +01:00
);
if (response === undefined) {
return undefined;
}
2024-09-27 23:04:14 +01:00
this.log(
`Found ${response.players.length} players in ${(performance.now() - before).toFixed(0)}ms`,
);
return response;
2024-09-11 20:10:27 +01:00
}
/**
* Looks up a page of scores for a player
*
* @param playerId the ID of the player to look up
* @param sort the sort to use
* @param page the page to get scores for
2024-09-13 13:45:04 +01:00
* @param search
2024-09-11 20:10:27 +01:00
* @param useProxy whether to use the proxy or not
* @returns the scores of the player, or undefined
*/
2024-09-13 13:45:04 +01:00
async lookupPlayerScores({
playerId,
sort,
page,
search,
useProxy = true,
}: {
playerId: string;
sort: ScoreSort;
page: number;
search?: string;
useProxy?: boolean;
2024-09-14 18:40:39 +01:00
}): Promise<ScoreSaberPlayerScoresPageToken | undefined> {
const before = performance.now();
2024-09-13 13:45:04 +01:00
this.log(
`Looking up scores for player "${playerId}", sort "${sort}", page "${page}"${
search ? `, search "${search}"` : ""
2024-09-27 23:04:14 +01:00
}...`,
2024-09-13 13:45:04 +01:00
);
2024-09-14 18:40:39 +01:00
const response = await this.fetch<ScoreSaberPlayerScoresPageToken>(
2024-09-11 20:10:27 +01:00
useProxy,
LOOKUP_PLAYER_SCORES_ENDPOINT.replace(":id", playerId)
.replace(":limit", 8 + "")
.replace(":sort", sort)
2024-09-27 23:04:14 +01:00
.replace(":page", page + "") + (search ? `&search=${search}` : ""),
2024-09-11 20:10:27 +01:00
);
if (response === undefined) {
return undefined;
}
2024-09-13 13:45:04 +01:00
this.log(
2024-09-27 23:04:14 +01:00
`Found ${response.playerScores.length} scores for player "${playerId}" in ${(
performance.now() - before
).toFixed(0)}ms`,
2024-09-13 13:45:04 +01:00
);
return response;
2024-09-08 22:35:32 +01:00
}
/**
* Looks up a page of scores for a leaderboard
*
* @param leaderboardId the ID of the leaderboard to look up
* @param sort the sort to use
* @param page the page to get scores for
* @param useProxy whether to use the proxy or not
* @returns the scores of the leaderboard, or undefined
*/
async lookupLeaderboardScores(
leaderboardId: string,
page: number,
2024-09-27 23:04:14 +01:00
useProxy = true,
2024-09-14 18:40:39 +01:00
): Promise<ScoreSaberLeaderboardScoresPageToken | undefined> {
const before = performance.now();
2024-09-27 23:04:14 +01:00
this.log(
`Looking up scores for leaderboard "${leaderboardId}", page "${page}"...`,
);
2024-09-14 18:40:39 +01:00
const response = await this.fetch<ScoreSaberLeaderboardScoresPageToken>(
useProxy,
2024-09-27 23:04:14 +01:00
LOOKUP_LEADERBOARD_SCORES_ENDPOINT.replace(":id", leaderboardId).replace(
":page",
page.toString(),
),
);
if (response === undefined) {
return undefined;
}
2024-09-13 13:45:04 +01:00
this.log(
`Found ${response.scores.length} scores for leaderboard "${leaderboardId}" in ${(
performance.now() - before
2024-09-27 23:04:14 +01:00
).toFixed(0)}ms`,
2024-09-13 13:45:04 +01:00
);
return response;
}
2024-09-08 22:35:32 +01:00
}
2024-09-13 20:04:04 +01:00
export const scoresaberService = new ScoreSaberService();