taevas.xyz/netlify/functions/wanikani.ts

113 lines
3.3 KiB
TypeScript
Raw Normal View History

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";
2023-11-01 21:15:29 +01:00
2025-02-16 17:05:02 +01:00
interface Subject {
id: number;
object: string;
data: {
characters: string;
slug: string;
document_url: string;
2025-02-16 17:05:02 +01:00
meanings: {
meaning: string;
2025-02-16 17:05:02 +01:00
}[];
};
2025-02-16 17:05:02 +01:00
}
2025-02-16 17:05:02 +01:00
interface StuffToLearn {
available_at: string;
type: string;
writing: string;
2025-02-16 17:05:02 +01:00
meanings: {
meaning: string;
2025-02-16 17:05:02 +01:00
}[];
url: string;
2025-02-16 17:05:02 +01:00
}
2024-04-27 21:22:48 +02:00
2025-02-16 17:05:02 +01:00
function addStuffToLearn(ids: number[], data: {available_at: string; subject_ids: number[]}[], subjects: Subject[]): StuffToLearn[] {
2024-04-27 21:22:48 +02:00
const arr: StuffToLearn[] = [];
for (const id of ids) {
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;
}
arr.push({
2024-04-27 21:22:48 +02:00
available_at: summaryData.available_at,
type: subject.object,
writing: subject.data.characters || subject.data.slug || subject.data.meanings[0].meaning,
meanings: subject.data.meanings,
url: subject.data.document_url,
});
}
return arr;
}
2023-11-05 21:01:24 +01:00
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));
}),
]);
2023-11-02 18:13:47 +01:00
const progression = data[0] as {
total_count: number;
data: WKLevelProgression[];
};
const resets = data[1] as WKResetCollection;
const summary = data[2] as WKSummary;
2024-04-27 21:22:48 +02:00
const subjectIdsLessons: number[] = [];
for (const lesson of summary.data.lessons) {
for (const subjectId of lesson.subject_ids) {
subjectIdsLessons.push(subjectId);
2023-11-01 21:15:29 +01:00
}
}
const subjectIdsReviews: number[] = [];
2024-04-27 21:22:48 +02:00
for (const review of summary.data.reviews) {
for (const subjectId of review.subject_ids) {
subjectIdsReviews.push(subjectId);
2023-11-01 21:15:29 +01:00
}
}
2025-02-16 17:05:02 +01:00
// 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
const now = new Date();
const nextReviews = summary.data.reviews.filter((r) => new Date(r.available_at) > now && r.subject_ids.length);
const moreThingsToReviewAt = nextReviews.at(0)?.available_at ?? summary.data.next_reviews_at;
2023-11-01 21:15:29 +01:00
2024-04-27 21:22:48 +02:00
const subjectIdsAll = subjectIdsLessons.concat(subjectIdsReviews);
const subjects = await api<{data: Subject[]}>(`https://api.wanikani.com/v2/subjects?ids=${subjectIdsAll.toString()}`, process.env.API_WANIKANI);
2023-11-01 21:15:29 +01:00
2024-04-27 21:22:48 +02:00
const lessons = addStuffToLearn(subjectIdsLessons, summary.data.lessons, subjects.data);
const reviews = addStuffToLearn(subjectIdsReviews, summary.data.reviews, subjects.data);
2023-11-01 21:15:29 +01:00
2023-11-05 21:01:24 +01:00
const info: WanikaniInfo = {
2023-11-02 01:22:02 +01:00
progression,
2023-11-01 21:15:29 +01:00
resets: resets.data,
lessons,
2023-11-02 01:22:02 +01:00
reviews,
2024-04-27 21:22:48 +02:00
moreThingsToReviewAt,
};
2023-11-02 01:22:02 +01:00
2023-11-01 21:15:29 +01:00
return {
statusCode: 200,
body: JSON.stringify(info),
};
};
2023-11-01 21:15:29 +01:00
export {handler};