Get rid of shared/api in Netlify functions

This commit is contained in:
Taevas 2025-03-02 14:37:13 +01:00
parent aecb5051ae
commit b4e060c954
12 changed files with 60 additions and 91 deletions

BIN
bun.lockb

Binary file not shown.

View file

@ -32,6 +32,7 @@ export default tseslint.config(
"@stylistic/indent": ["error", 2],
"@stylistic/semi": ["error", "always"],
"react/no-unescaped-entities": "off",
"no-async-promise-executor": "off",
}
},
{

View file

@ -1,13 +1,12 @@
import {type Handler} from "@netlify/functions";
import {api} from "./shared/api.js";
import {type HacktheboxInfo} from "#Infos/Hacking/Hackthebox.js";
const handler: Handler = async () => {
const hackthebox = await api<{
const hackthebox = await (await fetch("https://www.hackthebox.com/api/v4/profile/activity/1063999")).json() as {
profile: {
activity: HacktheboxInfo[];
};
}>("https://www.hackthebox.com/api/v4/profile/activity/1063999");
};
const pwn = hackthebox.profile.activity.find((a: HacktheboxInfo) => a?.object_type === "machine");
if (!pwn) {

View file

@ -1,11 +1,27 @@
/* eslint no-async-promise-executor: 0 */ // Doing promises is needed in order to make multiple requests at once, lowering wait time
import {type Handler} from "@netlify/functions";
import { KitsuclubInfo } from "#Infos/Fediverse/KitsuClub.js";
import { api } from "./shared/api.js";
const handler: Handler = async () => {
const kitsuclub = await api<{
const kitsuclub = await (await fetch("https://kitsunes.club/api/users/notes", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.API_KITSUCLUB}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"userId": "a2hgd7delf",
"limit": 1,
"withReplies": false,
"withRepliesToSelf": false,
"withQuotes": true,
"withRenotes": false,
"withBots": true,
"withNonPublic": true,
"withChannelNotes": false,
"withFiles": false,
"allowPartial": false,
})
})).json() as {
id: string
user: {
name: string
@ -22,19 +38,7 @@ const handler: Handler = async () => {
thumbnailUrl: string
comment: string
}[]
}[]>("https://kitsunes.club/api/users/notes", process.env.API_KITSUCLUB, true, JSON.stringify({
"userId": "a2hgd7delf",
"limit": 1,
"withReplies": false,
"withRepliesToSelf": false,
"withQuotes": true,
"withRenotes": false,
"withBots": true,
"withNonPublic": true,
"withChannelNotes": false,
"withFiles": false,
"allowPartial": false,
}));
}[];
const details = kitsuclub.at(Math.max(0, kitsuclub.length - 1));
if (!details) {

View file

@ -1,15 +1,14 @@
import {type Handler} from "@netlify/functions";
import {api} from "./shared/api.js";
import { type KitsudevInfo } from "#Infos/Coding/KitsuDev.js";
const handler: Handler = async () => {
const kitsudev = await api<[{
const kitsudev = await (await fetch("https://kitsunes.dev/api/v1/users/Taevas/activities/feeds?limit=1")).json() as [{
repo: {
full_name: string
html_url: string
}
created: string
}]>("https://kitsunes.dev/api/v1/users/Taevas/activities/feeds?limit=1");
}];
const info: KitsudevInfo = {
name: kitsudev[0].repo.full_name,

View file

@ -1,9 +1,8 @@
import {type Handler} from "@netlify/functions";
import {api} from "./shared/api.js";
import {type LastfmInfo} from "#Infos/Music/Lastfm.js";
const handler: Handler = async () => {
const lastfm = await api<{
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 {
recenttracks: {
track: {
artist: {
@ -27,7 +26,8 @@ const handler: Handler = async () => {
};
}[];
};
}>(`http://ws.audioscrobbler.com/2.0/?method=user.getrecenttracks&user=TTTaevas&api_key=${process.env.API_LASTFM}&format=json&limit=1`);
};
const image = lastfm.recenttracks.track[0].image.find((i) => i.size == "large");
const track: LastfmInfo = {
artist: lastfm.recenttracks.track[0].artist["#text"],

View file

@ -1,24 +0,0 @@
export async function api<T>(url: string, restful_token?: string, post?: boolean, body?: BodyInit): Promise<T> {
let fetched: Promise<Response>;
if (post) {
fetched = fetch(url, {
method: "POST",
headers: {
"Authorization": `Bearer ${restful_token}`,
"Content-Type": "application/json",
},
body,
});
} else {
fetched = (restful_token ? fetch(url, {headers: {"Authorization": `Bearer ${restful_token}`}}) : fetch(url));
}
return fetched.then(async response => {
if (!response.ok) {
console.error(response.status, response.statusText);
throw new Error("Request failed :(");
}
return response.json() as Promise<T>;
});
}

View file

@ -1,5 +1,4 @@
import {type Handler} from "@netlify/functions";
import {api} from "./shared/api.js";
import {type SpeedruncomInfo} from "#Infos/Speedrun/Speedruncom.js";
interface Runs {
@ -44,7 +43,7 @@ interface Level {
const handler: Handler = async () => {
// using the API's embedding would be stupid here, as that'd create lag due to irrelevant runs
const speedruncom = await api<Runs>("https://www.speedrun.com/api/v1/users/j03v45mj/personal-bests");
const speedruncom = await (await fetch("https://www.speedrun.com/api/v1/users/j03v45mj/personal-bests")).json() as Runs;
const data = speedruncom.data.at(0);
if (!data) {
@ -53,25 +52,14 @@ const handler: Handler = async () => {
};
}
const detailsToRequest = [new Promise((resolve) => {
resolve(api<Game>(`https://www.speedrun.com/api/v1/games/${data.run.game}`));
})];
const urlsToRequest = [`https://www.speedrun.com/api/v1/games/${data.run.game}`];
if (data.run.level) {urlsToRequest.push(`https://www.speedrun.com/api/v1/levels/${data.run.level}`);}
if (data.run.category) {urlsToRequest.push(`https://www.speedrun.com/api/v1/categories/${data.run.category}`);}
if (data.run.level) {
detailsToRequest.push(new Promise((resolve) => {
resolve(api<Level>(`https://www.speedrun.com/api/v1/levels/${data.run.level}`));
}));
}
if (data.run.category) {
detailsToRequest.push(new Promise((resolve) => {
resolve(api<Level>(`https://www.speedrun.com/api/v1/categories/${data.run.category}`));
}));
}
const requests = await Promise.all(detailsToRequest);
const game = requests[0] as Game;
const details = requests.slice(1) as Level[];
const toRequest = urlsToRequest.map((url) => new Promise(async (resolve) => resolve(await (await fetch(url)).json())));
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: SpeedruncomInfo = {
place: data.place,

View file

@ -1,5 +1,3 @@
/* eslint no-async-promise-executor: 0 */ // Doing promises is needed in order to make multiple requests at once, lowering wait time
import {type Handler} from "@netlify/functions";
import {InsertOneResult, MongoClient} from "mongodb";

View file

@ -1,7 +1,7 @@
import { UmamiInfo } from "#Infos/Website/Umami.js";
import {type Handler} from "@netlify/functions";
import { MongoClient } from "mongodb";
import { Token } from "./umami_token.js";
import { Token } from "./token.js";
const handler: Handler = async () => {
const client = new MongoClient(process.env.URL_MONGODB!);

View file

@ -1,5 +1,4 @@
import {type Handler} from "@netlify/functions";
import {api} from "./shared/api.js";
import {type WanikaniInfo} from "#Infos/Japanese/Wanikani.js";
import { WKLevelProgression, WKResetCollection, WKSummary } from "@bachmacintosh/wanikani-api-types";
@ -50,18 +49,20 @@ function addStuffToLearn(ids: number[], data: {available_at: string; subject_ids
}
const handler: Handler = async () => {
const data = await Promise.all([
new Promise((resolve) => {
resolve(api("https://api.wanikani.com/v2/level_progressions", process.env.API_WANIKANI));
}),
new Promise((resolve) => {
resolve(api("https://api.wanikani.com/v2/resets", process.env.API_WANIKANI));
}),
new Promise((resolve) => {
resolve(api("https://api.wanikani.com/v2/summary", process.env.API_WANIKANI));
}),
]);
const urlsToRequest = [
"https://api.wanikani.com/v2/level_progressions",
"https://api.wanikani.com/v2/resets",
"https://api.wanikani.com/v2/summary",
];
const toRequest = urlsToRequest.map((url) => new Promise(async (resolve) => {
const response = await fetch(url, {headers: {
"Authorization": `Bearer ${process.env.API_WANIKANI}`,
"Content-Type": "application/json",
}});
resolve(await response.json());
}));
const data = await Promise.all(toRequest);
const progression = data[0] as {
total_count: number;
data: WKLevelProgression[];
@ -90,7 +91,10 @@ const handler: Handler = async () => {
const moreThingsToReviewAt = nextReviews.at(0)?.available_at ?? summary.data.next_reviews_at;
const subjectIdsAll = subjectIdsLessons.concat(subjectIdsReviews);
const subjects = await api<{data: Subject[]}>(`https://api.wanikani.com/v2/subjects?ids=${subjectIdsAll.toString()}`, process.env.API_WANIKANI);
const subjects = await (await fetch(`https://api.wanikani.com/v2/subjects?ids=${subjectIdsAll.toString()}`, {headers: {
"Authorization": `Bearer ${process.env.API_WANIKANI}`,
"Content-Type": "application/json",
}})).json() as {data: Subject[]};
const lessons = addStuffToLearn(subjectIdsLessons, summary.data.lessons, subjects.data);
const reviews = addStuffToLearn(subjectIdsReviews, summary.data.reviews, subjects.data);

View file

@ -7,11 +7,11 @@
},
"dependencies": {
"@bachmacintosh/wanikani-api-types": "^1.7.0",
"@carbon/icons-react": "^11.55.0",
"@carbon/icons-react": "^11.56.0",
"@gitbeaker/rest": "^42.1.0",
"@netlify/functions": "^2.8.2",
"@octokit/rest": "^20.1.1",
"mongodb": "^6.13.1",
"@octokit/rest": "^20.1.2",
"mongodb": "^6.14.0",
"osu-api-v2-js": "^1.1.1",
"react": "^19.0.0",
"react-dom": "^19.0.0",
@ -23,7 +23,7 @@
"@stylistic/eslint-plugin": "^3.1.0",
"@tailwindcss/forms": "^0.5.10",
"@types/bun": "latest",
"@types/node": "^20.17.19",
"@types/node": "^20.17.22",
"@types/react": "^19.0.10",
"@types/react-dom": "^19.0.4",
"@vitejs/plugin-react": "^4.3.4",
@ -34,7 +34,7 @@
"postcss": "^8.5.3",
"react-animate-height": "^3.2.3",
"tailwindcss": "^3.4.17",
"typescript": "^5.7.3",
"typescript": "^5.8.2",
"typescript-eslint": "^8.25.0",
"vite": "^5.4.14"
},