72 lines
1.8 KiB
TypeScript
72 lines
1.8 KiB
TypeScript
|
|
import * as ical from 'node-ical';
|
||
|
|
import type { AgendaEvent } from '../todayview';
|
||
|
|
|
||
|
|
export async function fetchICSAgenda(
|
||
|
|
urls: string[]
|
||
|
|
): Promise<AgendaEvent[]> {
|
||
|
|
const now = new Date();
|
||
|
|
const startOfDay = new Date(now);
|
||
|
|
startOfDay.setHours(0, 0, 0, 0);
|
||
|
|
const endOfDay = new Date(now);
|
||
|
|
endOfDay.setHours(23, 59, 59, 999);
|
||
|
|
|
||
|
|
const allEvents = (
|
||
|
|
await Promise.all(urls.map((url) => fetchOne(url, startOfDay, endOfDay)))
|
||
|
|
).flat();
|
||
|
|
|
||
|
|
allEvents.sort((a, b) => a.sortKey - b.sortKey);
|
||
|
|
|
||
|
|
return allEvents.map(({ sortKey, ...event }) => event);
|
||
|
|
}
|
||
|
|
|
||
|
|
interface RawAgendaEvent extends AgendaEvent {
|
||
|
|
sortKey: number;
|
||
|
|
}
|
||
|
|
|
||
|
|
async function fetchOne(
|
||
|
|
url: string,
|
||
|
|
start: Date,
|
||
|
|
end: Date
|
||
|
|
): Promise<RawAgendaEvent[]> {
|
||
|
|
const resp = await fetch(url, {
|
||
|
|
headers: [['User-Agent', 'private TRMNL fetcher']],
|
||
|
|
});
|
||
|
|
const data = await resp.text();
|
||
|
|
const parsed = Object.values(await ical.async.parseICS(data)).filter(
|
||
|
|
(a) => a?.type === 'VEVENT'
|
||
|
|
);
|
||
|
|
|
||
|
|
const events: RawAgendaEvent[] = [];
|
||
|
|
|
||
|
|
for (const event of parsed) {
|
||
|
|
for (const instance of ical.expandRecurringEvent(event, {
|
||
|
|
from: start,
|
||
|
|
to: end,
|
||
|
|
excludeExdates: true,
|
||
|
|
expandOngoing: true,
|
||
|
|
includeOverrides: true,
|
||
|
|
})) {
|
||
|
|
if (instance.isFullDay) continue;
|
||
|
|
|
||
|
|
const startTime = formatTime(instance.start);
|
||
|
|
const endTime = formatTime(instance.end);
|
||
|
|
const location = (instance.event as any).location ?? '';
|
||
|
|
|
||
|
|
events.push({
|
||
|
|
start: startTime,
|
||
|
|
end: endTime,
|
||
|
|
title: (instance.summary as string) ?? '',
|
||
|
|
where: location,
|
||
|
|
kind: '',
|
||
|
|
sortKey: instance.start.valueOf(),
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return events;
|
||
|
|
}
|
||
|
|
|
||
|
|
function formatTime(d: Date): string {
|
||
|
|
return `${String(d.getHours()).padStart(2, '0')}:${String(d.getMinutes()).padStart(2, '0')}`;
|
||
|
|
}
|