Helps with eventually adding other pages Also makes it clear it's the backend that decides what data to send to the frontend
106 linhas
3,1 KiB
TypeScript
106 linhas
3,1 KiB
TypeScript
import { headers, parseJson, type Handler } from "../..";
|
|
|
|
export type Info = {
|
|
place: number;
|
|
link: string;
|
|
date: string;
|
|
thumbnail: string;
|
|
game: string;
|
|
details: string[];
|
|
time: string;
|
|
video?: string;
|
|
} | undefined;
|
|
|
|
const user_id = "j03v45mj";
|
|
|
|
interface Runs {
|
|
data: {
|
|
place: number;
|
|
run: {
|
|
weblink: string;
|
|
game: string;
|
|
level?: string;
|
|
category?: string;
|
|
videos: {
|
|
links: {
|
|
uri: string
|
|
}[]
|
|
}
|
|
date: string;
|
|
times: {
|
|
primary_t: number
|
|
}
|
|
};
|
|
}[]
|
|
}
|
|
|
|
interface Game {
|
|
data: {
|
|
names: {
|
|
international: string;
|
|
};
|
|
assets: {
|
|
"cover-tiny": {
|
|
uri: string;
|
|
};
|
|
};
|
|
};
|
|
}
|
|
|
|
interface Level {
|
|
data: {
|
|
name: string;
|
|
};
|
|
}
|
|
|
|
export const speedruncom: Handler = async () => {
|
|
// using the API's embedding would be stupid here, as that'd create lag due to irrelevant runs
|
|
|
|
/** https://github.com/speedruncomorg/api/blob/master/version1/users.md#get-usersidpersonal-bests */
|
|
const speedruncom = await parseJson(await fetch(`https://www.speedrun.com/api/v1/users/${user_id}/personal-bests`, {headers})) as Runs;
|
|
const data = speedruncom.data.at(0);
|
|
|
|
if (!data) {
|
|
return new Response("Not Found", {status: 404});
|
|
}
|
|
|
|
/** https://github.com/speedruncomorg/api/blob/master/version1/games.md#get-gamesid */
|
|
const urlsToRequest = [`https://www.speedrun.com/api/v1/games/${data.run.game}`];
|
|
/** https://github.com/speedruncomorg/api/blob/master/version1/levels.md#get-levelsid */
|
|
if (data.run.level) {urlsToRequest.push(`https://www.speedrun.com/api/v1/levels/${data.run.level}`);}
|
|
/** https://github.com/speedruncomorg/api/blob/master/version1/categories.md */
|
|
if (data.run.category) {urlsToRequest.push(`https://www.speedrun.com/api/v1/categories/${data.run.category}`);}
|
|
|
|
const toRequest = urlsToRequest.map((url) => new Promise(async (resolve) => resolve(await parseJson(await fetch(url)))));
|
|
const responses = await Promise.all(toRequest) as [Game, Level?, Level?];
|
|
const game = responses[0];
|
|
const details = [responses[1]].concat(responses[2]).filter((d) => d !== undefined);
|
|
|
|
const run: Info = {
|
|
place: data.place,
|
|
link: data.run.weblink,
|
|
date: data.run.date,
|
|
thumbnail: game.data.assets["cover-tiny"].uri,
|
|
game: game.data.names.international,
|
|
details: details.map((d) => d.data.name),
|
|
time: sec2time(data.run.times.primary_t),
|
|
video: data.run.videos.links.at(0)?.uri,
|
|
};
|
|
|
|
while (run.time.startsWith("0") || run.time.startsWith(":")) {
|
|
run.time = run.time.substring(1);
|
|
}
|
|
|
|
return Response.json(run, {status: 200});
|
|
};
|
|
|
|
// https://gist.github.com/vankasteelj/74ab7793133f4b257ea3
|
|
function sec2time(timeInSeconds: number) {
|
|
const pad = (num: number, size: number) => ("000" + num).slice(size * -1);
|
|
const time = Number(parseFloat(timeInSeconds.toString()).toFixed(3));
|
|
const hours = Math.floor(time / 60 / 60);
|
|
const minutes = Math.floor(time / 60) % 60;
|
|
const seconds = Math.floor(time - minutes * 60);
|
|
const milliseconds = Number(time.toString().slice(-3));
|
|
return pad(hours, 2) + ":" + pad(minutes, 2) + ":" + pad(seconds, 2) + "." + pad(milliseconds, 3);
|
|
};
|