Lint Netlify functions
This commit is contained in:
parent
eb85319f73
commit
d2f3cada52
11 changed files with 83 additions and 90 deletions
BIN
bun.lockb
BIN
bun.lockb
Binary file not shown.
|
@ -7,6 +7,7 @@ const handler: Handler = async () => {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||||
"Accept": "application/json",
|
"Accept": "application/json",
|
||||||
},
|
},
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
|
@ -53,8 +54,7 @@ const handler: Handler = async () => {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const p_json = await anilist.json() as Record<string, any>;
|
const json = (await anilist.json() as any).data.MediaList;
|
||||||
const json = p_json.data.MediaList;
|
|
||||||
const anime: AnilistInfo = {
|
const anime: AnilistInfo = {
|
||||||
title: json.media.title.romaji,
|
title: json.media.title.romaji,
|
||||||
episodes: {
|
episodes: {
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
import {type Handler} from "@netlify/functions";
|
import {type Handler} from "@netlify/functions";
|
||||||
import {Octokit} from "@octokit/core";
|
import {Octokit} from "@octokit/rest";
|
||||||
import {type GithubInfo} from "../../src/components/Info/Git.js";
|
import {type GithubInfo} from "../../src/components/Info/Git.js";
|
||||||
|
|
||||||
const handler: Handler = async () => {
|
const handler: Handler = async () => {
|
||||||
const octokit = new Octokit({auth: process.env.API_GITHUB});
|
const octokit = new Octokit({auth: process.env.API_GITHUB});
|
||||||
const github = await octokit.request("GET /users/TTTaevas/events", {per_page: 100});
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||||
|
const github = await octokit.rest.activity.listEventsForAuthenticatedUser({username: "TTTaevas"});
|
||||||
|
|
||||||
if (github.status !== 200) {
|
if (github.status !== 200) {
|
||||||
return {
|
return {
|
||||||
statusCode: 404,
|
statusCode: 404,
|
||||||
|
@ -12,9 +14,9 @@ const handler: Handler = async () => {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const public_push = github.data.find((e: {type: string; public: boolean}) => e.type === "PushEvent" && e.public);
|
const publicPush = github.data.find((e) => e.type === "PushEvent" && e.public);
|
||||||
const private_push = github.data.find((e: {type: string; public: boolean}) => e.type === "PushEvent" && !e.public);
|
const privatePush = github.data.find((e) => e.type === "PushEvent" && !e.public);
|
||||||
if (!public_push || !private_push) {
|
if (!publicPush || !privatePush) {
|
||||||
return {
|
return {
|
||||||
statusCode: 404,
|
statusCode: 404,
|
||||||
body: "",
|
body: "",
|
||||||
|
@ -23,11 +25,11 @@ const handler: Handler = async () => {
|
||||||
|
|
||||||
const info: GithubInfo = {
|
const info: GithubInfo = {
|
||||||
public: {
|
public: {
|
||||||
repo: public_push.repo.name,
|
repo: publicPush.repo.name,
|
||||||
date: public_push.created_at.substring(0, public_push.created_at.indexOf("T")),
|
date: publicPush.created_at ? publicPush.created_at.substring(0, publicPush.created_at.indexOf("T")) : "",
|
||||||
},
|
},
|
||||||
private: {
|
private: {
|
||||||
date: private_push.created_at.substring(0, private_push.created_at.indexOf("T")),
|
date: privatePush.created_at ? privatePush.created_at.substring(0, privatePush.created_at.indexOf("T")) : "",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ const handler: Handler = async () => {
|
||||||
headers: {
|
headers: {
|
||||||
"PRIVATE-TOKEN": process.env.API_GITLAB!,
|
"PRIVATE-TOKEN": process.env.API_GITLAB!,
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||||
"Accept": "application/json",
|
"Accept": "application/json",
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -19,9 +20,17 @@ const handler: Handler = async () => {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const json = await gitlab.json() as Record<string, any>;
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||||
|
const {created_at} = (await gitlab.json() as Record<string, any>)[0];
|
||||||
|
if (typeof created_at !== "string") {
|
||||||
|
return {
|
||||||
|
statusCode: 404,
|
||||||
|
body: "",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
const activity: GitlabInfo = {
|
const activity: GitlabInfo = {
|
||||||
date: json[0].created_at.substring(0, json[0].created_at.indexOf("T")),
|
date: created_at.substring(0, created_at.indexOf("T")),
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -7,8 +7,7 @@ const handler: Handler = async () => {
|
||||||
profile: {
|
profile: {
|
||||||
activity: HacktheboxInfo[];
|
activity: HacktheboxInfo[];
|
||||||
};
|
};
|
||||||
}>
|
}>("https://www.hackthebox.com/api/v4/profile/activity/1063999");
|
||||||
("https://www.hackthebox.com/api/v4/profile/activity/1063999");
|
|
||||||
|
|
||||||
const pwn = hackthebox.profile.activity.find((a: HacktheboxInfo) => a!.object_type === "machine");
|
const pwn = hackthebox.profile.activity.find((a: HacktheboxInfo) => a!.object_type === "machine");
|
||||||
if (!pwn) {
|
if (!pwn) {
|
||||||
|
|
|
@ -23,8 +23,7 @@ const handler: Handler = async () => {
|
||||||
url: string;
|
url: string;
|
||||||
}>;
|
}>;
|
||||||
};
|
};
|
||||||
}>
|
}>(`http://ws.audioscrobbler.com/2.0/?method=user.getrecenttracks&user=TTTaevas&api_key=${process.env.API_LASTFM}&format=json&limit=1`);
|
||||||
(`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 image = lastfm.recenttracks.track[0].image.find((i) => i.size == "large");
|
||||||
const track: LastfmInfo = {
|
const track: LastfmInfo = {
|
||||||
|
|
|
@ -28,16 +28,15 @@ const handler: Handler = async () => {
|
||||||
mania: {global: 0, country: 0},
|
mania: {global: 0, country: 0},
|
||||||
};
|
};
|
||||||
|
|
||||||
for (let i = 0; i < profile.length; i++) {
|
for (const ruleset of profile) {
|
||||||
const ruleset = profile[i];
|
|
||||||
if (ruleset.rank_history) {
|
if (ruleset.rank_history) {
|
||||||
const stats = ruleset.statistics;
|
const stats = ruleset.statistics;
|
||||||
info[ruleset.rank_history.mode].global = stats.global_rank || 0;
|
info[ruleset.rank_history.mode].global = stats.global_rank ?? 0;
|
||||||
info[ruleset.rank_history.mode].country = stats.country_rank || 0;
|
info[ruleset.rank_history.mode].country = stats.country_rank ?? 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
api.revokeToken();
|
void api.revokeToken();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
statusCode: 200,
|
statusCode: 200,
|
||||||
|
|
|
@ -15,10 +15,9 @@ const handler: Handler = async () => {
|
||||||
date: string;
|
date: string;
|
||||||
};
|
};
|
||||||
}>;
|
}>;
|
||||||
}>
|
}>("https://www.speedrun.com/api/v1/users/j03v45mj/personal-bests");
|
||||||
("https://www.speedrun.com/api/v1/users/j03v45mj/personal-bests");
|
|
||||||
|
|
||||||
const details_to_request = [new Promise((resolve) => {
|
const detailsToRequest = [new Promise((resolve) => {
|
||||||
resolve(api<{
|
resolve(api<{
|
||||||
data: {
|
data: {
|
||||||
names: {
|
names: {
|
||||||
|
@ -30,33 +29,30 @@ const handler: Handler = async () => {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}>
|
}>(`https://www.speedrun.com/api/v1/games/${speedruncom.data[0].run.game}`));
|
||||||
(`https://www.speedrun.com/api/v1/games/${speedruncom.data[0].run.game}`));
|
|
||||||
})];
|
})];
|
||||||
|
|
||||||
if (speedruncom.data[0].run.level) {
|
if (speedruncom.data[0].run.level) {
|
||||||
details_to_request.push(new Promise((resolve) => {
|
detailsToRequest.push(new Promise((resolve) => {
|
||||||
resolve(api<{
|
resolve(api<{
|
||||||
data: {
|
data: {
|
||||||
name: string;
|
name: string;
|
||||||
};
|
};
|
||||||
}>
|
}>(`https://www.speedrun.com/api/v1/levels/${speedruncom.data[0].run.level}`));
|
||||||
(`https://www.speedrun.com/api/v1/levels/${speedruncom.data[0].run.level}`));
|
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (speedruncom.data[0].run.category) {
|
if (speedruncom.data[0].run.category) {
|
||||||
details_to_request.push(new Promise((resolve) => {
|
detailsToRequest.push(new Promise((resolve) => {
|
||||||
resolve(api<{
|
resolve(api<{
|
||||||
data: {
|
data: {
|
||||||
name: string;
|
name: string;
|
||||||
};
|
};
|
||||||
}>
|
}>(`https://www.speedrun.com/api/v1/categories/${speedruncom.data[0].run.category}`));
|
||||||
(`https://www.speedrun.com/api/v1/categories/${speedruncom.data[0].run.category}`));
|
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
const details = await Promise.all(details_to_request) as [Record<string, any>];
|
const details = await Promise.all(detailsToRequest) as [Record<string, any>];
|
||||||
|
|
||||||
const run: SpeedruncomInfo = {
|
const run: SpeedruncomInfo = {
|
||||||
place: speedruncom.data[0].place,
|
place: speedruncom.data[0].place,
|
||||||
|
@ -64,7 +60,7 @@ const handler: Handler = async () => {
|
||||||
date: speedruncom.data[0].run.date,
|
date: speedruncom.data[0].run.date,
|
||||||
thumbnail: details[0].data.assets["cover-tiny"].uri,
|
thumbnail: details[0].data.assets["cover-tiny"].uri,
|
||||||
game: details[0].data.names.international,
|
game: details[0].data.names.international,
|
||||||
details: details.slice(1).map((d) => d.data.name) || [],
|
details: details.slice(1).map((d) => (d.data as {name: string}).name),
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -15,27 +15,30 @@ type Subject = {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
function addStuffToLearn(ids: number[], data: Array<{available_at: string; subject_ids: number[]}>, subjects: Subject[]): Array<{
|
type StuffToLearn = {
|
||||||
available_at: string;
|
available_at: string;
|
||||||
type: string;
|
type: string;
|
||||||
writing: string;
|
writing: string;
|
||||||
meanings: [{
|
meanings: Array<{
|
||||||
meaning: string;
|
meaning: string;
|
||||||
}];
|
}>;
|
||||||
url: string;
|
url: string;
|
||||||
}> {
|
};
|
||||||
const arr: any[] = [];
|
|
||||||
|
|
||||||
for (let i = 0; i < ids.length; i++) {
|
function addStuffToLearn(ids: number[], data: Array<{available_at: string; subject_ids: number[]}>, subjects: Subject[]): StuffToLearn[] {
|
||||||
const summary_data = data.find(lesson => lesson.subject_ids.includes(ids[i]));
|
const arr: StuffToLearn[] = [];
|
||||||
const subject = subjects.find(subject => subject.id === ids[i]);
|
|
||||||
if (!summary_data || !subject) {
|
for (const id of ids) {
|
||||||
console.error("Failed: ", summary_data, subject);
|
const summaryData = data.find(lesson => lesson.subject_ids.includes(id));
|
||||||
|
const subject = subjects.find(subject => subject.id === id);
|
||||||
|
if (!summaryData || !subject) {
|
||||||
|
console.error("Failed: ", summaryData, subject);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
arr.push({
|
arr.push({
|
||||||
available_at: summary_data.available_at,
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||||
|
available_at: summaryData.available_at,
|
||||||
type: subject.object,
|
type: subject.object,
|
||||||
writing: subject.data.characters || subject.data.slug || subject.data.meanings[0].meaning,
|
writing: subject.data.characters || subject.data.slug || subject.data.meanings[0].meaning,
|
||||||
meanings: subject.data.meanings,
|
meanings: subject.data.meanings,
|
||||||
|
@ -95,42 +98,42 @@ const handler: Handler = async () => {
|
||||||
};
|
};
|
||||||
} = data[2];
|
} = data[2];
|
||||||
|
|
||||||
const subject_ids_lessons: number[] = [];
|
const subjectIdsLessons: number[] = [];
|
||||||
const subject_ids_reviews: number[] = [];
|
const subjectIdsReviews: number[] = [];
|
||||||
for (let i = 0; i < summary.data.lessons.length; i++) {
|
for (const lesson of summary.data.lessons) {
|
||||||
for (let e = 0; e < summary.data.lessons[i].subject_ids.length; e++) {
|
for (const subjectId of lesson.subject_ids) {
|
||||||
subject_ids_lessons.push(summary.data.lessons[i].subject_ids[e]);
|
subjectIdsLessons.push(subjectId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let i = 0; i < summary.data.reviews.length; i++) {
|
for (const review of summary.data.reviews) {
|
||||||
for (let e = 0; e < summary.data.reviews[i].subject_ids.length; e++) {
|
for (const subjectId of review.subject_ids) {
|
||||||
subject_ids_reviews.push(summary.data.reviews[i].subject_ids[e]);
|
subjectIdsReviews.push(subjectId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
// next_reviews checks what reviews will be available in the next 23 hours
|
// next_reviews checks what reviews will be available in the next 23 hours
|
||||||
// summary.data.next_reviews_at checks beyond that, but will be the current time if a review is already available
|
// summary.data.next_reviews_at checks beyond that, but will be the current time if a review is already available
|
||||||
const next_reviews = summary.data.reviews
|
const nextReviews = summary.data.reviews
|
||||||
.map((r: {subject_ids: number[]; available_at: Date | string}) => {
|
.map((r: {subject_ids: number[]; available_at: Date | string}) => {
|
||||||
r.available_at = new Date(r.available_at); return r;
|
r.available_at = new Date(r.available_at); return r;
|
||||||
})
|
})
|
||||||
.filter((r) => r.available_at > now && r.subject_ids.length) as Array<{subject_ids: number[]; available_at: Date}>;
|
.filter((r) => r.available_at > now && r.subject_ids.length) as Array<{subject_ids: number[]; available_at: Date}>;
|
||||||
const more_things_to_review_at = next_reviews[0] ? next_reviews[0].available_at.toISOString() : summary.data.next_reviews_at ? summary.data.next_reviews_at : null;
|
const moreThingsToReviewAt = nextReviews[0] ? nextReviews[0].available_at.toISOString() : summary.data.next_reviews_at ? summary.data.next_reviews_at : undefined;
|
||||||
|
|
||||||
const subject_ids_all = subject_ids_lessons.concat(subject_ids_reviews);
|
const subjectIdsAll = subjectIdsLessons.concat(subjectIdsReviews);
|
||||||
const subjects = await api<{data: Subject[]}>(`https://api.wanikani.com/v2/subjects?ids=${subject_ids_all.toString()}`, process.env.API_WANIKANI);
|
const subjects = await api<{data: Subject[]}>(`https://api.wanikani.com/v2/subjects?ids=${subjectIdsAll.toString()}`, process.env.API_WANIKANI);
|
||||||
|
|
||||||
const lessons = addStuffToLearn(subject_ids_lessons, summary.data.lessons, subjects.data);
|
const lessons = addStuffToLearn(subjectIdsLessons, summary.data.lessons, subjects.data);
|
||||||
const reviews = addStuffToLearn(subject_ids_reviews, summary.data.reviews, subjects.data);
|
const reviews = addStuffToLearn(subjectIdsReviews, summary.data.reviews, subjects.data);
|
||||||
|
|
||||||
const info: WanikaniInfo = {
|
const info: WanikaniInfo = {
|
||||||
progression,
|
progression,
|
||||||
resets: resets.data,
|
resets: resets.data,
|
||||||
lessons,
|
lessons,
|
||||||
reviews,
|
reviews,
|
||||||
more_things_to_review_at,
|
moreThingsToReviewAt,
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@netlify/functions": "^2.4.0",
|
"@netlify/functions": "^2.4.0",
|
||||||
"@octokit/core": "^6.0.1",
|
"@octokit/rest": "^20.1.0",
|
||||||
"node-fetch": "^3.3.2",
|
"node-fetch": "^3.3.2",
|
||||||
"osu-api-v2-js": "^1.0.3",
|
"osu-api-v2-js": "^1.0.3",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
|
|
|
@ -20,43 +20,29 @@ export type WanikaniInfo = {
|
||||||
target_level: number;
|
target_level: number;
|
||||||
};
|
};
|
||||||
}>;
|
}>;
|
||||||
lessons: Array<{
|
lessons: Item[];
|
||||||
available_at: string;
|
reviews: Item[];
|
||||||
type: string;
|
moreThingsToReviewAt: string | undefined;
|
||||||
writing: string;
|
|
||||||
meanings: [{
|
|
||||||
meaning: string;
|
|
||||||
}];
|
|
||||||
url: string;
|
|
||||||
}>;
|
|
||||||
reviews: Array<{
|
|
||||||
available_at: string;
|
|
||||||
type: string;
|
|
||||||
writing: string;
|
|
||||||
meanings: [{
|
|
||||||
meaning: string;
|
|
||||||
}];
|
|
||||||
url: string;
|
|
||||||
}>;
|
|
||||||
more_things_to_review_at: string | undefined;
|
|
||||||
} | undefined;
|
} | undefined;
|
||||||
|
|
||||||
function Button(lesson: {
|
type Item = {
|
||||||
available_at: string;
|
available_at: string;
|
||||||
type: string;
|
type: string;
|
||||||
writing: string;
|
writing: string;
|
||||||
meanings: [{
|
meanings: Array<{
|
||||||
meaning: string;
|
meaning: string;
|
||||||
}];
|
}>;
|
||||||
url: string;
|
url: string;
|
||||||
}) {
|
};
|
||||||
const colour = lesson.type === "radical" ? "bg-sky-600" : lesson.type === "kanji" ? "bg-pink-500" : "bg-fuchsia-700";
|
|
||||||
const title = `(${lesson.type}) ${lesson.meanings.map((m) => m.meaning).toString().replace(/,/g, ", ")}`;
|
function Button(item: Item) {
|
||||||
|
const colour = item.type === "radical" ? "bg-sky-600" : item.type === "kanji" ? "bg-pink-500" : "bg-fuchsia-700";
|
||||||
|
const title = `(${item.type}) ${item.meanings.map((m) => m.meaning).toString().replace(/,/g, ", ")}`;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<a href={lesson.url} target="_blank" rel="noreferrer">
|
<a href={item.url} target="_blank" rel="noreferrer">
|
||||||
<button title={title} className={`m-1 p-2 ${colour} border-solid border-white border-2 rounded-md`}>
|
<button title={title} className={`m-1 p-2 ${colour} border-solid border-white border-2 rounded-md`}>
|
||||||
{lesson.writing}
|
{item.writing}
|
||||||
</button></a>
|
</button></a>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -119,9 +105,9 @@ export default function Wanikani() {
|
||||||
</div> : <p>No review available for now!</p>;
|
</div> : <p>No review available for now!</p>;
|
||||||
|
|
||||||
let whenNextToReview = <></>;
|
let whenNextToReview = <></>;
|
||||||
if (wanikani.more_things_to_review_at) {
|
if (wanikani.moreThingsToReviewAt) {
|
||||||
const rtf = new Intl.RelativeTimeFormat("en", {style: "long", numeric: "always"});
|
const rtf = new Intl.RelativeTimeFormat("en", {style: "long", numeric: "always"});
|
||||||
const timeDifference = new Date(Math.abs(new Date(wanikani.more_things_to_review_at).getTime() - now.getTime()));
|
const timeDifference = new Date(Math.abs(new Date(wanikani.moreThingsToReviewAt).getTime() - now.getTime()));
|
||||||
const howManyHours = (timeDifference.getUTCHours() + 1) + ((24 * (timeDifference.getUTCDate() - 1)) * (timeDifference.getUTCMonth() + 1));
|
const howManyHours = (timeDifference.getUTCHours() + 1) + ((24 * (timeDifference.getUTCDate() - 1)) * (timeDifference.getUTCMonth() + 1));
|
||||||
whenNextToReview = <p className="mt-2">{`There will be more stuff to review ${rtf.format(howManyHours, "hour")}!`}</p>;
|
whenNextToReview = <p className="mt-2">{`There will be more stuff to review ${rtf.format(howManyHours, "hour")}!`}</p>;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue