forked from GitHubMirrors/silverbullet-icalendar
feat(test): implement Playwright E2E and Dockerized testing infrastructure
Some checks failed
Build SilverBullet Plug / build (push) Has been cancelled
Some checks failed
Build SilverBullet Plug / build (push) Has been cancelled
This commit is contained in:
26
icalendar.ts
26
icalendar.ts
@@ -196,7 +196,7 @@ export async function resolveEventStart(icsEvent: any): Promise<Date | null> {
|
||||
/**
|
||||
* Expands recurring events into individual occurrences.
|
||||
*/
|
||||
export function expandRecurrences(icsEvent: any, windowDays = 365): any[] {
|
||||
export function expandRecurrences(icsEvent: any, windowDays = 365, now = new Date()): any[] {
|
||||
const rruleStr = icsEvent.rrule || (icsEvent as any).recurrenceRule;
|
||||
if (!rruleStr) return [icsEvent];
|
||||
|
||||
@@ -238,17 +238,13 @@ export function expandRecurrences(icsEvent: any, windowDays = 365): any[] {
|
||||
set.exdate(new Date(exdate.includes("Z") ? exdate : exdate + "Z"));
|
||||
}
|
||||
|
||||
const now = new Date();
|
||||
// Start our visible window 7 days ago to catch recent past events
|
||||
const filterStart = new Date(now.getTime() - 7 * 86400000);
|
||||
const windowEnd = new Date(now.getTime() + windowDays * 86400000);
|
||||
|
||||
// Expand from the event's actual start date to ensure all recurrences are calculated correctly
|
||||
// but only take occurrences between (now - 7 days) and (now + windowDays)
|
||||
// Expand from the event's actual start date up to the window end.
|
||||
// This provides "no limit" lookback (bound only by the event's own start date).
|
||||
const occurrences = set.between(dtstart, windowEnd, true);
|
||||
|
||||
return occurrences
|
||||
.filter(occurrenceDate => occurrenceDate >= filterStart)
|
||||
const mapped = occurrences
|
||||
.map(occurrenceDate => {
|
||||
const localIso = localDateString(occurrenceDate);
|
||||
return {
|
||||
@@ -258,6 +254,7 @@ export function expandRecurrences(icsEvent: any, windowDays = 365): any[] {
|
||||
rrule: undefined,
|
||||
};
|
||||
});
|
||||
return mapped;
|
||||
} catch (err) {
|
||||
console.error(`[iCalendar] Error expanding recurrence for ${icsEvent.summary}:`, err);
|
||||
return [icsEvent];
|
||||
@@ -265,7 +262,6 @@ export function expandRecurrences(icsEvent: any, windowDays = 365): any[] {
|
||||
}
|
||||
|
||||
async function fetchAndParseCalendar(source: any, windowDays = 365): Promise<any[]> {
|
||||
console.log(`[iCalendar] Fetching from: ${source.url}`);
|
||||
try {
|
||||
const response = await fetch(source.url);
|
||||
if (!response.ok) {
|
||||
@@ -286,29 +282,31 @@ async function fetchAndParseCalendar(source: any, windowDays = 365): Promise<any
|
||||
if (!finalDate) continue;
|
||||
|
||||
const localIso = localDateString(finalDate);
|
||||
const rawTz = icsEvent.start?.local?.timezone || (icsEvent.start as any)?.timezone || "UTC";
|
||||
const baseEvent = {
|
||||
...icsEvent,
|
||||
name: icsEvent.summary || "Untitled Event",
|
||||
start: localIso,
|
||||
tag: "ical-event",
|
||||
sourceName: source.name
|
||||
sourceName: source.name,
|
||||
timezone: rawTz
|
||||
};
|
||||
|
||||
const rawTz = icsEvent.start?.local?.timezone || (icsEvent.start as any)?.timezone || "UTC";
|
||||
if (rawTz !== "UTC" && rawTz !== "None" && !resolveIanaName(rawTz)) {
|
||||
baseEvent.description = `(Warning: Unknown timezone "${rawTz}") ${baseEvent.description || ""}`;
|
||||
}
|
||||
|
||||
const expanded = expandRecurrences(baseEvent, windowDays);
|
||||
for (const occurrence of expanded) {
|
||||
const uniqueKey = `${occurrence.start}${occurrence.uid || occurrence.summary || ''}`;
|
||||
// Use summary in key to avoid collisions for meetings sharing UID/Start
|
||||
const uniqueKey = `${occurrence.start}${occurrence.uid || ''}${occurrence.summary || ''}`;
|
||||
occurrence.ref = await sha256Hash(uniqueKey);
|
||||
events.push(convertDatesToStrings(occurrence));
|
||||
}
|
||||
}
|
||||
return events;
|
||||
} catch (err) {
|
||||
console.error(`[iCalendar] Error fetching/parsing ${source.name}:`, err);
|
||||
} catch (err: any) {
|
||||
console.error(`[iCalendar] Error fetching/parsing ${source.name}:`, err.message || err, err.stack || "");
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user