www-new/lib/events.ts

111 lines
2.9 KiB
TypeScript

import fs from "fs/promises";
import path from "path";
import matter from "gray-matter";
import { MDXRemoteSerializeResult } from "next-mdx-remote";
import { serialize } from "next-mdx-remote/serialize";
const EVENTS_PATH = path.join("content", "events");
const TERMS = ["winter", "spring", "fall"];
export async function getEventYears(): Promise<string[]> {
return (await fs.readdir(EVENTS_PATH, { withFileTypes: true }))
.filter((dirent) => dirent.isDirectory())
.map((dirent) => dirent.name)
.sort();
}
export async function getEventTermsByYear(year: string): Promise<string[]> {
return (
await fs.readdir(path.join(EVENTS_PATH, year), { withFileTypes: true })
)
.filter((dirent) => dirent.isDirectory() && TERMS.includes(dirent.name))
.map((dirent) => dirent.name)
.sort((a, b) => TERMS.indexOf(a) - TERMS.indexOf(b));
}
interface Metadata {
name: string;
short: string;
date: string;
online: boolean;
location: string;
}
export interface Event {
content: MDXRemoteSerializeResult<Record<string, unknown>>;
metadata: Metadata;
}
export async function getEventBySlug(
year: string,
term: string,
slug: string
): Promise<Event> {
const raw = await fs.readFile(
path.join(EVENTS_PATH, year, term, `${slug}.md`),
"utf-8"
);
const { content, data: metadata } = matter(raw);
return {
content: await serialize(content),
metadata: metadata as Metadata,
};
}
export async function getEventsByTerm(
year: string,
term: string
): Promise<string[]> {
return (await fs.readdir(path.join(EVENTS_PATH, year, term)))
.filter((name) => name.endsWith(".md"))
.map((name) => name.slice(0, -".md".length));
}
export async function getUpcomingEvents(): Promise<Event[]> {
const today = new Date();
const currentYear = today.getFullYear();
const currentTerm = Math.trunc(today.getMonth() / 4);
const nextYear = currentTerm < 2 ? currentYear : currentYear + 1;
const nextTerm = (currentTerm + 1) % 3;
let currentEvents: Event[] = [];
try {
currentEvents = await Promise.all(
(
await getEventsByTerm(currentYear.toString(), TERMS[currentTerm])
).map(
async (slug) =>
await getEventBySlug(currentYear.toString(), TERMS[currentTerm], slug)
)
);
} catch (error) {
currentEvents = [];
}
let nextEvents: Event[] = [];
try {
nextEvents = await Promise.all(
(
await getEventsByTerm(nextYear.toString(), TERMS[nextTerm])
).map(
async (slug) =>
await getEventBySlug(nextYear.toString(), TERMS[nextTerm], slug)
)
);
} catch (error) {
nextEvents = [];
}
return currentEvents
.concat(nextEvents)
.filter((ev) => {
return new Date(ev.metadata.date).getTime() > Date.now();
})
.sort((a, b) => {
return (
new Date(a.metadata.date).getTime() -
new Date(b.metadata.date).getTime()
);
});
}