Split the API logic
This commit is contained in:
parent
150b861bd3
commit
3728614109
31 changed files with 137 additions and 103 deletions
40
api/index.ts
Normal file
40
api/index.ts
Normal file
|
@ -0,0 +1,40 @@
|
|||
import { token } from "./infos/token";
|
||||
import { github } from "./infos/coding/github";
|
||||
import { gitlab } from "./infos/coding/gitlab";
|
||||
import { kitsudev } from "./infos/coding/kitsudev";
|
||||
import { kitsuclub } from "./infos/fediverse/kitsuclub";
|
||||
import { osu } from "./infos/gaming/osu";
|
||||
import { speedruncom } from "./infos/gaming/speedruncom";
|
||||
import { hackthebox } from "./infos/hacking/hackthebox";
|
||||
import { wanikani } from "./infos/japanese/wanikani";
|
||||
import { anilist } from "./infos/media/anilist";
|
||||
import { lastfm } from "./infos/media/lastfm";
|
||||
import { umami } from "./infos/website/umami";
|
||||
|
||||
const info_routes: Record<string, Handler[]> = {
|
||||
coding: [github, gitlab, kitsudev],
|
||||
fediverse: [kitsuclub],
|
||||
gaming: [osu, speedruncom],
|
||||
hacking: [hackthebox],
|
||||
japanese: [wanikani],
|
||||
media: [anilist, lastfm],
|
||||
website: [umami],
|
||||
};
|
||||
|
||||
export type Handler = (req: URLSearchParams) => Promise<Response>;
|
||||
|
||||
export async function api(pathname: string, parameters: URLSearchParams) {
|
||||
if (pathname === "/api/infos/token") {
|
||||
return await token(parameters);
|
||||
}
|
||||
|
||||
for (const route of Object.keys(info_routes)) {
|
||||
for (const endpoint of info_routes[route]) {
|
||||
if (pathname === "/api/infos/" + route + "/" + endpoint.name) {
|
||||
return await endpoint(parameters);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new Response("Not Found", {status: 404});
|
||||
}
|
|
@ -1,10 +1,12 @@
|
|||
import {Octokit} from "@octokit/rest";
|
||||
import {type GithubInfo} from "#Infos/Coding/GitHub.tsx";
|
||||
import type { Handler } from "..";
|
||||
import type { Handler } from "../..";
|
||||
|
||||
export const coding_github: Handler = async () => {
|
||||
const username = "TTTaevas";
|
||||
|
||||
export const github: Handler = async () => {
|
||||
const octokit = new Octokit({auth: process.env["API_GITHUB"]});
|
||||
const github = await octokit.rest.activity.listEventsForAuthenticatedUser({username: "TTTaevas"});
|
||||
const github = await octokit.rest.activity.listEventsForAuthenticatedUser({username});
|
||||
|
||||
const publicPush = github.data.find((e) => (e.type === "PushEvent" || e.type === "PullRequestEvent") && e.public);
|
||||
const privatePush = github.data.find((e) => (e.type === "PushEvent" || e.type === "PullRequestEvent") && !e.public);
|
|
@ -1,8 +1,8 @@
|
|||
import { Gitlab } from "@gitbeaker/rest";
|
||||
import {type GitlabInfo} from "#Infos/Coding/GitLab.tsx";
|
||||
import type { Handler } from "..";
|
||||
import type { Handler } from "../..";
|
||||
|
||||
export const coding_gitlab: Handler = async () => {
|
||||
export const gitlab: Handler = async () => {
|
||||
const api = new Gitlab({token: process.env["API_GITLAB"]!});
|
||||
const gitlab = await api.Events.all({action: "pushed"});
|
||||
|
|
@ -1,8 +1,11 @@
|
|||
import { type KitsudevInfo } from "#Infos/Coding/KitsuDev.tsx";
|
||||
import type { Handler } from "..";
|
||||
import type { Handler } from "../..";
|
||||
|
||||
export const coding_kitsudev: Handler = async () => {
|
||||
const kitsudev = await (await fetch("https://kitsunes.dev/api/v1/users/Taevas/activities/feeds?limit=1")).json() as [{
|
||||
const username = "Taevas";
|
||||
|
||||
export const kitsudev: Handler = async () => {
|
||||
/** https://kitsunes.dev/api/swagger#/user/userListActivityFeeds */
|
||||
const kitsudev = await (await fetch(`https://kitsunes.dev/api/v1/users/${username}/activities/feeds?limit=1`)).json() as [{
|
||||
repo: {
|
||||
full_name: string
|
||||
html_url: string
|
|
@ -1,7 +1,10 @@
|
|||
import { type KitsuclubInfo } from "#Infos/Fediverse/KitsuClub.tsx";
|
||||
import type { Handler } from "..";
|
||||
import type { Handler } from "../..";
|
||||
|
||||
export const fediverse_kitsuclub: Handler = async () => {
|
||||
const user_id = "a2hgd7delf";
|
||||
|
||||
export const kitsuclub: Handler = async () => {
|
||||
/** https://kitsunes.club/api-doc#tag/users/POST/users/notes */
|
||||
const kitsuclub = await (await fetch("https://kitsunes.club/api/users/notes", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
|
@ -9,7 +12,7 @@ export const fediverse_kitsuclub: Handler = async () => {
|
|||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
"userId": "a2hgd7delf",
|
||||
"userId": user_id,
|
||||
"limit": 1,
|
||||
"withReplies": false,
|
||||
"withRepliesToSelf": false,
|
|
@ -1,15 +1,17 @@
|
|||
import * as osu from "osu-api-v2-js";
|
||||
import * as osuv2 from "osu-api-v2-js";
|
||||
import {type OsuInfo} from "#Infos/Gaming/Osu.tsx";
|
||||
import type { Handler } from "../index.ts";
|
||||
import { db, getToken } from "../database.ts";
|
||||
import type { Handler } from "../../index.ts";
|
||||
import { db, getToken } from "../../../database.ts";
|
||||
|
||||
export const gaming_osu: Handler = async (params) => {
|
||||
const user_id = 7276846;
|
||||
|
||||
export const osu: Handler = async (params) => {
|
||||
const token = await getToken(db, "osu");
|
||||
|
||||
let ruleset = params.has("ruleset") ? Number(params.get("ruleset")) : undefined;
|
||||
if (ruleset && isNaN(ruleset)) {ruleset = undefined;}
|
||||
const api = new osu.API({access_token: token?.access_token});
|
||||
const profile = await api.getUser(7276846, ruleset);
|
||||
const api = new osuv2.API({access_token: token?.access_token});
|
||||
const profile = await api.getUser(user_id, ruleset);
|
||||
|
||||
const info: OsuInfo = {
|
||||
country: profile.country.name,
|
|
@ -1,5 +1,7 @@
|
|||
import {type SpeedruncomInfo} from "#Infos/Gaming/Speedruncom.tsx";
|
||||
import type { Handler } from "..";
|
||||
import type { Handler } from "../..";
|
||||
|
||||
const user_id = "j03v45mj";
|
||||
|
||||
interface Runs {
|
||||
data: {
|
||||
|
@ -41,17 +43,22 @@ interface Level {
|
|||
};
|
||||
}
|
||||
|
||||
export const gaming_speedruncom: Handler = async () => {
|
||||
export const speedruncom: Handler = async () => {
|
||||
// using the API's embedding would be stupid here, as that'd create lag due to irrelevant runs
|
||||
const speedruncom = await (await fetch("https://www.speedrun.com/api/v1/users/j03v45mj/personal-bests")).json() as Runs;
|
||||
|
||||
/** https://github.com/speedruncomorg/api/blob/master/version1/users.md#get-usersidpersonal-bests */
|
||||
const speedruncom = await (await fetch(`https://www.speedrun.com/api/v1/users/${user_id}/personal-bests`)).json() 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 (await fetch(url)).json())));
|
|
@ -1,8 +1,11 @@
|
|||
import {type HacktheboxInfo} from "#Infos/Hacking/Hackthebox.tsx";
|
||||
import type { Handler } from "..";
|
||||
import type { Handler } from "../..";
|
||||
|
||||
export const hacking_hackthebox: Handler = async () => {
|
||||
const hackthebox = await (await fetch("https://www.hackthebox.com/api/v4/profile/activity/1063999")).json() as {
|
||||
const user_id = 1063999;
|
||||
|
||||
export const hackthebox: Handler = async () => {
|
||||
/** https://documenter.getpostman.com/view/13129365/TVeqbmeq#1b0b22fc-2e45-456a-9a8f-42888375d1a9 */
|
||||
const hackthebox = await (await fetch(`https://www.hackthebox.com/api/v4/profile/activity/${user_id}`)).json() as {
|
||||
profile: {
|
||||
activity: HacktheboxInfo[];
|
||||
};
|
|
@ -1,6 +1,6 @@
|
|||
import {type WanikaniInfo} from "#Infos/Japanese/Wanikani.tsx";
|
||||
import type { WKLevelProgression, WKResetCollection, WKSummary } from "@bachmacintosh/wanikani-api-types";
|
||||
import type { Handler } from "..";
|
||||
import type { Handler } from "../..";
|
||||
|
||||
interface Subject {
|
||||
id: number;
|
||||
|
@ -48,7 +48,7 @@ function addStuffToLearn(ids: number[], data: {available_at: string; subject_ids
|
|||
return arr;
|
||||
}
|
||||
|
||||
export const japanese_wanikani: Handler = async () => {
|
||||
export const wanikani: Handler = async () => {
|
||||
const urlsToRequest = [
|
||||
"https://api.wanikani.com/v2/level_progressions",
|
||||
"https://api.wanikani.com/v2/resets",
|
|
@ -1,7 +1,10 @@
|
|||
import {type AnilistInfo} from "#Infos/Media/Anilist.tsx";
|
||||
import type { Handler } from "..";
|
||||
import type { Handler } from "../..";
|
||||
|
||||
export const media_anilist: Handler = async () => {
|
||||
const username = "Taevas";
|
||||
|
||||
export const anilist: Handler = async () => {
|
||||
/** https://github.com/AniList/ApiV2-GraphQL-Docs/blob/master/docs/reference/query.md */
|
||||
const anilist = await fetch("https://graphql.anilist.co", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
|
@ -39,7 +42,7 @@ export const media_anilist: Handler = async () => {
|
|||
}
|
||||
`,
|
||||
variables: {
|
||||
userName: "Taevas",
|
||||
userName: username,
|
||||
},
|
||||
}),
|
||||
});
|
|
@ -1,8 +1,11 @@
|
|||
import {type LastfmInfo} from "#Infos/Media/Lastfm.tsx";
|
||||
import type { Handler } from "..";
|
||||
import type { Handler } from "../..";
|
||||
|
||||
export const media_lastfm: Handler = async () => {
|
||||
const lastfm = await (await fetch(`https://ws.audioscrobbler.com/2.0/?method=user.getrecenttracks&user=TTTaevas&api_key=${process.env["API_LASTFM"]}&format=json&limit=1`)).json() as {
|
||||
const username = "TTTaevas";
|
||||
|
||||
export const lastfm: Handler = async () => {
|
||||
/** https://www.last.fm/api/show/user.getRecentTracks */
|
||||
const lastfm = await (await fetch(`https://ws.audioscrobbler.com/2.0/?method=user.getrecenttracks&user=${username}&api_key=${process.env["API_LASTFM"]}&format=json&limit=1`)).json() as {
|
||||
recenttracks: {
|
||||
track: {
|
||||
artist: {
|
|
@ -1,4 +1,4 @@
|
|||
import { addToken, createTables, db, getToken, removeExpiredTokens } from "../database";
|
||||
import { addToken, createTables, db, getToken, removeExpiredTokens } from "../../database";
|
||||
import {API} from "osu-api-v2-js";
|
||||
import type { Handler } from "..";
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
import type { Handler } from "../index.ts";
|
||||
import type { Handler } from "../..";
|
||||
import type { UmamiInfo } from "#Infos/Website/Umami.tsx";
|
||||
import { db, getToken } from "../database.ts";
|
||||
import { db, getToken } from "../../../database.ts";
|
||||
|
||||
export const website_umami: Handler = async () => {
|
||||
export const umami: Handler = async () => {
|
||||
const token = await getToken(db, "umami");
|
||||
|
||||
const api_server = "https://visitors.taevas.xyz/api";
|
BIN
bun.lockb
BIN
bun.lockb
Binary file not shown.
|
@ -1,5 +1,5 @@
|
|||
import { SQL } from "bun";
|
||||
import type { Token } from "./api/token";
|
||||
import type { Token } from "./api/infos/token";
|
||||
|
||||
export const db = new SQL({url: process.env["URL_POSTGRESQL"]});
|
||||
|
||||
|
|
36
index.ts
36
index.ts
|
@ -1,17 +1,6 @@
|
|||
import type { Server } from "bun";
|
||||
import { parseArgs } from "util";
|
||||
import { coding_github } from "./api/coding_github";
|
||||
import { coding_gitlab } from "./api/coding_gitlab";
|
||||
import { coding_kitsudev } from "./api/coding_kitsudev";
|
||||
import { fediverse_kitsuclub } from "./api/fediverse_kitsuclub";
|
||||
import { gaming_osu } from "./api/gaming_osu";
|
||||
import { gaming_speedruncom } from "./api/gaming_speedruncom";
|
||||
import { hacking_hackthebox } from "./api/hacking_hackthebox";
|
||||
import { japanese_wanikani } from "./api/japanese_wanikani";
|
||||
import { media_anilist } from "./api/media_anilist";
|
||||
import { media_lastfm } from "./api/media_lastfm";
|
||||
import { token } from "./api/token";
|
||||
import { website_umami } from "./api/website_umami";
|
||||
import { api } from "./api";
|
||||
|
||||
// PORT AND SSL STUFF
|
||||
|
||||
|
@ -32,23 +21,6 @@ console.log("Therefore, we are opening ports on:", ports);
|
|||
|
||||
// ACTUAL CODE
|
||||
|
||||
export type Handler = (req: URLSearchParams) => Promise<Response>;
|
||||
|
||||
const api_endpoints: Handler[] = [
|
||||
coding_github,
|
||||
coding_gitlab,
|
||||
coding_kitsudev,
|
||||
fediverse_kitsuclub,
|
||||
gaming_osu,
|
||||
gaming_speedruncom,
|
||||
hacking_hackthebox,
|
||||
japanese_wanikani,
|
||||
media_anilist,
|
||||
media_lastfm,
|
||||
token,
|
||||
website_umami
|
||||
];
|
||||
|
||||
const servers: Server[] = ports.map((port) => Bun.serve({
|
||||
idleTimeout: 30,
|
||||
tls: port !== 80 ? tls : undefined,
|
||||
|
@ -92,11 +64,7 @@ const servers: Server[] = ports.map((port) => Bun.serve({
|
|||
// API
|
||||
|
||||
if (pathname.startsWith("/api")) {
|
||||
for (const endpoint of api_endpoints) {
|
||||
if (pathname === "/api/" + endpoint.name) {
|
||||
return await endpoint(parameters);
|
||||
}
|
||||
}
|
||||
return await api(pathname, parameters);
|
||||
}
|
||||
|
||||
return new Response("Not Found", {status: 404});
|
||||
|
|
12
package.json
12
package.json
|
@ -21,20 +21,20 @@
|
|||
"@eslint/js": "^9.23.0",
|
||||
"@stylistic/eslint-plugin": "^3.1.0",
|
||||
"@tailwindcss/forms": "^0.5.10",
|
||||
"@tailwindcss/postcss": "^4.0.17",
|
||||
"@tailwindcss/postcss": "^4.1.1",
|
||||
"@types/bun": "^1.2.8",
|
||||
"@types/react": "^19.0.12",
|
||||
"@types/react-dom": "^19.0.4",
|
||||
"@types/react": "^19.1.0",
|
||||
"@types/react-dom": "^19.1.1",
|
||||
"dotenv": "^16.4.7",
|
||||
"eslint": "^9.23.0",
|
||||
"eslint-config-xo-typescript": "^7.0.0",
|
||||
"eslint-plugin-react": "^7.37.4",
|
||||
"postcss": "^8.5.3",
|
||||
"react-animate-height": "^3.2.3",
|
||||
"tailwindcss": "^4.0.17",
|
||||
"tailwindcss": "^4.1.1",
|
||||
"typescript": "^5.8.2",
|
||||
"typescript-eslint": "^8.28.0",
|
||||
"vite": "^6.2.3"
|
||||
"typescript-eslint": "^8.29.0",
|
||||
"vite": "^6.2.5"
|
||||
},
|
||||
"imports": {
|
||||
"#Main/*": "./src/Main/*",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React, {useState, useEffect} from "react";
|
||||
import Website from "../Website.tsx";
|
||||
import DataHandler from "#Infos/DataHandler.tsx";
|
||||
import DataHandler from "#parts/DataHandler.tsx";
|
||||
import Link from "#parts/Link.tsx";
|
||||
|
||||
export interface GithubInfo {
|
||||
|
@ -14,7 +14,7 @@ export interface GithubInfo {
|
|||
}
|
||||
|
||||
export default function GitHub() {
|
||||
const {data, error, setError} = DataHandler<GithubInfo>("coding_github", 60 * 20);
|
||||
const {data, error, setError} = DataHandler<GithubInfo>("infos/coding/github", 60 * 20);
|
||||
const [elements, setElements] = useState([] as React.JSX.Element[]);
|
||||
|
||||
useEffect(() => {
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
import React, {useState, useEffect} from "react";
|
||||
import Website from "../Website.tsx";
|
||||
import DataHandler from "#Infos/DataHandler.tsx";
|
||||
import DataHandler from "#parts/DataHandler.tsx";
|
||||
|
||||
export type GitlabInfo = {
|
||||
date: string;
|
||||
} | undefined;
|
||||
|
||||
export default function GitLab() {
|
||||
const {data, error, setError} = DataHandler<GitlabInfo>("coding_gitlab", 60 * 20);
|
||||
const {data, error, setError} = DataHandler<GitlabInfo>("infos/coding/gitlab", 60 * 20);
|
||||
const [elements, setElements] = useState([] as React.JSX.Element[]);
|
||||
|
||||
useEffect(() => {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React, {useState, useEffect} from "react";
|
||||
import Website from "../Website.tsx";
|
||||
import DataHandler from "#Infos/DataHandler.tsx";
|
||||
import DataHandler from "#parts/DataHandler.tsx";
|
||||
import Link from "#parts/Link.tsx";
|
||||
|
||||
export type KitsudevInfo = {
|
||||
|
@ -10,7 +10,7 @@ export type KitsudevInfo = {
|
|||
} | undefined;
|
||||
|
||||
export default function KitsuDev() {
|
||||
const {data, error, setError} = DataHandler<KitsudevInfo>("coding_kitsudev", 60 * 20);
|
||||
const {data, error, setError} = DataHandler<KitsudevInfo>("infos/coding/kitsudev", 60 * 20);
|
||||
const [elements, setElements] = useState([] as React.JSX.Element[]);
|
||||
|
||||
useEffect(() => {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React, {useState, useEffect} from "react";
|
||||
import Website from "../Website.tsx";
|
||||
import DataHandler from "#Infos/DataHandler.tsx";
|
||||
import DataHandler from "#parts/DataHandler.tsx";
|
||||
import Link from "#parts/Link.tsx";
|
||||
|
||||
export type KitsuclubInfo = {
|
||||
|
@ -18,7 +18,7 @@ export type KitsuclubInfo = {
|
|||
} | undefined;
|
||||
|
||||
export default function KitsuClub() {
|
||||
const {data, error, setError} = DataHandler<KitsuclubInfo>("fediverse_kitsuclub", 60 * 20);
|
||||
const {data, error, setError} = DataHandler<KitsuclubInfo>("infos/fediverse/kitsuclub", 60 * 20);
|
||||
const [elements, setElements] = useState([] as React.JSX.Element[]);
|
||||
|
||||
useEffect(() => {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import React, {useState, useEffect} from "react";
|
||||
import Website from "../Website.tsx";
|
||||
import { Ruleset } from "osu-api-v2-js";
|
||||
import DataHandler from "#Infos/DataHandler.tsx";
|
||||
import DataHandler from "#parts/DataHandler.tsx";
|
||||
|
||||
export type OsuInfo = {
|
||||
country: string;
|
||||
|
@ -12,7 +12,7 @@ export type OsuInfo = {
|
|||
} | undefined;
|
||||
|
||||
export default function Osu(args: {ruleset: Ruleset}) {
|
||||
const {data, error, setError} = DataHandler<OsuInfo>(`gaming_osu?ruleset=${args.ruleset}`, 60 * 45);
|
||||
const {data, error, setError} = DataHandler<OsuInfo>(`infos/gaming/osu?ruleset=${args.ruleset}`, 60 * 45);
|
||||
const [elements, setElements] = useState([] as React.JSX.Element[]);
|
||||
|
||||
const ruleset = Ruleset[args.ruleset];
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React, {useState, useEffect} from "react";
|
||||
import Website from "../Website.tsx";
|
||||
import DataHandler from "#Infos/DataHandler.tsx";
|
||||
import DataHandler from "#parts/DataHandler.tsx";
|
||||
import Link from "#parts/Link.tsx";
|
||||
import ButtonLink from "#parts/ButtonLink.tsx";
|
||||
|
||||
|
@ -16,7 +16,7 @@ export type SpeedruncomInfo = {
|
|||
} | undefined;
|
||||
|
||||
export default function Speedruncom() {
|
||||
const {data, error, setError} = DataHandler<SpeedruncomInfo>("gaming_speedruncom", 60 * 60);
|
||||
const {data, error, setError} = DataHandler<SpeedruncomInfo>("infos/gaming/speedruncom", 60 * 60);
|
||||
const [elements, setElements] = useState([] as React.JSX.Element[]);
|
||||
|
||||
useEffect(() => {
|
||||
|
|
|
@ -4,10 +4,10 @@ import Info from "../Info.tsx";
|
|||
import Speedruncom from "./Speedruncom.tsx";
|
||||
// import Osu from "./Osu.tsx";
|
||||
// import { Ruleset } from "osu-api-v2-js";
|
||||
// import DataHandler from "#Infos/DataHandler.tsx";
|
||||
// import DataHandler from "#parts/DataHandler.tsx";
|
||||
|
||||
export default function RhythmGames() {
|
||||
// const {data, error} = DataHandler<boolean>("token?service=osu", 60 * 60 * 8, false);
|
||||
// const {data, error} = DataHandler<boolean>("infos/token?service=osu", 60 * 60 * 8, false);
|
||||
const [websites, setWebsites] = useState([] as React.JSX.Element[]);
|
||||
|
||||
useEffect(() => {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import React, {useState, useEffect} from "react";
|
||||
import Website from "../Website.tsx";
|
||||
import ButtonLink from "#parts/ButtonLink.tsx";
|
||||
import DataHandler from "#Infos/DataHandler.tsx";
|
||||
import DataHandler from "#parts/DataHandler.tsx";
|
||||
|
||||
export type HacktheboxInfo = {
|
||||
id: string;
|
||||
|
@ -14,7 +14,7 @@ export type HacktheboxInfo = {
|
|||
} | undefined;
|
||||
|
||||
export default function Hackthebox() {
|
||||
const {data, error, setError} = DataHandler<HacktheboxInfo>("hacking_hackthebox", 60 * 60);
|
||||
const {data, error, setError} = DataHandler<HacktheboxInfo>("infos/hacking/hackthebox", 60 * 60);
|
||||
const [elements, setElements] = useState([] as React.JSX.Element[]);
|
||||
|
||||
useEffect(() => {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import React, {useState, useEffect} from "react";
|
||||
import Website from "../Website.tsx";
|
||||
import { WKLevelProgression, WKReset } from "@bachmacintosh/wanikani-api-types";
|
||||
import DataHandler from "#Infos/DataHandler.tsx";
|
||||
import type { WKLevelProgression, WKReset } from "@bachmacintosh/wanikani-api-types";
|
||||
import DataHandler from "#parts/DataHandler.tsx";
|
||||
|
||||
export type WanikaniInfo = {
|
||||
progression: {
|
||||
|
@ -37,7 +37,7 @@ function Button(item: Item) {
|
|||
}
|
||||
|
||||
export default function Wanikani() {
|
||||
const {data, error, setError} = DataHandler<WanikaniInfo>("japanese_wanikani", 60 * 60);
|
||||
const {data, error, setError} = DataHandler<WanikaniInfo>("infos/japanese/wanikani", 60 * 60);
|
||||
const [elements, setElements] = useState([] as React.JSX.Element[]);
|
||||
|
||||
useEffect(() => {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React, {useState, useEffect} from "react";
|
||||
import Website from "../Website.tsx";
|
||||
import DataHandler from "#Infos/DataHandler.tsx";
|
||||
import DataHandler from "#parts/DataHandler.tsx";
|
||||
import Link from "#parts/Link.tsx";
|
||||
|
||||
export type AnilistInfo = {
|
||||
|
@ -18,7 +18,7 @@ export type AnilistInfo = {
|
|||
} | undefined;
|
||||
|
||||
export default function Anilist() {
|
||||
const {data, error, setError} = DataHandler<AnilistInfo>("media_anilist", 60 * 30);
|
||||
const {data, error, setError} = DataHandler<AnilistInfo>("infos/media/anilist", 60 * 30);
|
||||
const [elements, setElements] = useState([] as React.JSX.Element[]);
|
||||
|
||||
useEffect(() => {
|
||||
|
|
|
@ -2,7 +2,7 @@ import React, {useState, useEffect} from "react";
|
|||
import {format} from "timeago.js";
|
||||
import Website from "../Website.tsx";
|
||||
import Link from "#parts/Link.tsx";
|
||||
import DataHandler from "#Infos/DataHandler.tsx";
|
||||
import DataHandler from "#parts/DataHandler.tsx";
|
||||
|
||||
export type LastfmInfo = {
|
||||
artist: string;
|
||||
|
@ -15,7 +15,7 @@ export type LastfmInfo = {
|
|||
} | undefined;
|
||||
|
||||
export default function Lastfm() {
|
||||
const {data, error, setError} = DataHandler<LastfmInfo>("media_lastfm", 60 * 2);
|
||||
const {data, error, setError} = DataHandler<LastfmInfo>("infos/media/lastfm", 60 * 2);
|
||||
const [elements, setElements] = useState([] as React.JSX.Element[]);
|
||||
|
||||
useEffect(() => {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React, {useState, useEffect} from "react";
|
||||
import Website from "../Website.tsx";
|
||||
import DataHandler from "#Infos/DataHandler.tsx";
|
||||
import DataHandler from "#parts/DataHandler.tsx";
|
||||
|
||||
export type UmamiInfo = {
|
||||
pageviews: number
|
||||
|
@ -10,7 +10,7 @@ export type UmamiInfo = {
|
|||
} | undefined;
|
||||
|
||||
export default function Umami() {
|
||||
const {data, error, setError} = DataHandler<UmamiInfo>("website_umami", 60 * 5);
|
||||
const {data, error, setError} = DataHandler<UmamiInfo>("infos/website/umami", 60 * 5);
|
||||
const [elements, setElements] = useState([] as React.JSX.Element[]);
|
||||
|
||||
useEffect(() => {
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import React, {useEffect, useState} from "react";
|
||||
import Info from "../Info.tsx";
|
||||
import Umami from "./Umami.tsx";
|
||||
import DataHandler from "#Infos/DataHandler.tsx";
|
||||
import DataHandler from "#parts/DataHandler.tsx";
|
||||
|
||||
export default function Website() {
|
||||
const {data} = DataHandler<boolean>("token?service=umami", 60 * 60 * 8, false);
|
||||
const {data} = DataHandler<boolean>("infos/token?service=umami", 60 * 60 * 8, false);
|
||||
const [websites, setWebsites] = useState([] as React.JSX.Element[]);
|
||||
|
||||
// useEffect(() => {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue