mirror of
https://github.com/ajnart/homarr.git
synced 2026-02-26 16:30:57 +01:00
fix(calendar): recurring events not working (#4265)
This commit is contained in:
@@ -1,4 +1,7 @@
|
||||
import type { Agent } from "https";
|
||||
import dayjs from "dayjs";
|
||||
import timezone from "dayjs/plugin/timezone";
|
||||
import utc from "dayjs/plugin/utc";
|
||||
import type { RequestInit as NodeFetchRequestInit } from "node-fetch";
|
||||
import * as ical from "node-ical";
|
||||
import { DAVClient } from "tsdav";
|
||||
@@ -14,6 +17,9 @@ import type { TestingResult } from "../base/test-connection/test-connection-serv
|
||||
import type { ICalendarIntegration } from "../interfaces/calendar/calendar-integration";
|
||||
import type { CalendarEvent } from "../interfaces/calendar/calendar-types";
|
||||
|
||||
dayjs.extend(utc);
|
||||
dayjs.extend(timezone);
|
||||
|
||||
@HandleIntegrationErrors([integrationTsdavHttpErrorHandler])
|
||||
export class NextcloudIntegration extends Integration implements ICalendarIntegration {
|
||||
protected async testingAsync(input: IntegrationTestingInput): Promise<TestingResult> {
|
||||
@@ -41,47 +47,58 @@ export class NextcloudIntegration extends Integration implements ICalendarIntegr
|
||||
)
|
||||
).flat();
|
||||
|
||||
return calendarEvents.map((event): CalendarEvent => {
|
||||
// @ts-expect-error the typescript definitions for this package are wrong
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access
|
||||
const icalData = ical.default.parseICS(event.data) as ical.CalendarResponse;
|
||||
const veventObject = Object.values(icalData).find((data) => data.type === "VEVENT");
|
||||
return calendarEvents
|
||||
.map((event) => {
|
||||
// @ts-expect-error the typescript definitions for this package are wrong
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access
|
||||
const icalData = ical.default.parseICS(event.data) as ical.CalendarResponse;
|
||||
const veventObject = Object.values(icalData).find((data) => data.type === "VEVENT");
|
||||
|
||||
if (!veventObject) {
|
||||
throw new Error(`Invalid event data object: ${JSON.stringify(event.data)}. Unable to process the calendar.`);
|
||||
}
|
||||
if (!veventObject) {
|
||||
throw new Error(`Invalid event data object: ${JSON.stringify(event.data)}. Unable to process the calendar.`);
|
||||
}
|
||||
|
||||
logger.debug(`Converting VEVENT event to ${event.etag} from Nextcloud: ${JSON.stringify(veventObject)}`);
|
||||
logger.debug(`Converting VEVENT event to ${event.etag} from Nextcloud: ${JSON.stringify(veventObject)}`);
|
||||
|
||||
const date = veventObject.start;
|
||||
const eventUrlWithoutHost = new URL(event.url).pathname;
|
||||
const eventSlug = Buffer.from(eventUrlWithoutHost).toString("base64url");
|
||||
|
||||
const eventUrlWithoutHost = new URL(event.url).pathname;
|
||||
const dateInMillis = veventObject.start.valueOf();
|
||||
const startDates = veventObject.rrule ? veventObject.rrule.between(start, end) : [veventObject.start];
|
||||
|
||||
const url = this.url(
|
||||
`/apps/calendar/timeGridWeek/now/edit/sidebar/${Buffer.from(eventUrlWithoutHost).toString("base64url")}/${dateInMillis / 1000}`,
|
||||
);
|
||||
const durationMs = veventObject.end.getTime() - veventObject.start.getTime();
|
||||
|
||||
return {
|
||||
title: veventObject.summary,
|
||||
subTitle: null,
|
||||
description: veventObject.description,
|
||||
startDate: date,
|
||||
endDate: veventObject.end,
|
||||
image: null,
|
||||
location: veventObject.location || null,
|
||||
indicatorColor: "#ff8600",
|
||||
links: [
|
||||
{
|
||||
href: url.toString(),
|
||||
name: "Nextcloud",
|
||||
logo: "/images/apps/nextcloud.svg",
|
||||
color: undefined,
|
||||
isDark: true,
|
||||
},
|
||||
],
|
||||
};
|
||||
});
|
||||
return startDates.map((startDate) => {
|
||||
const timezoneOffsetMinutes = veventObject.rrule?.origOptions.tzid
|
||||
? dayjs(startDate).tz(veventObject.rrule.origOptions.tzid).utcOffset()
|
||||
: 0;
|
||||
const utcStartDate = new Date(startDate.getTime() - timezoneOffsetMinutes * 60 * 1000);
|
||||
const endDate = new Date(utcStartDate.getTime() + durationMs);
|
||||
const dateInMillis = utcStartDate.valueOf();
|
||||
|
||||
return {
|
||||
title: veventObject.summary,
|
||||
subTitle: null,
|
||||
description: veventObject.description,
|
||||
startDate: utcStartDate,
|
||||
endDate,
|
||||
image: null,
|
||||
location: veventObject.location || null,
|
||||
indicatorColor: "#ff8600",
|
||||
links: [
|
||||
{
|
||||
href: this.url(
|
||||
`/apps/calendar/timeGridWeek/now/edit/sidebar/${eventSlug}/${dateInMillis / 1000}`,
|
||||
).toString(),
|
||||
name: "Nextcloud",
|
||||
logo: "/images/apps/nextcloud.svg",
|
||||
color: undefined,
|
||||
isDark: true,
|
||||
},
|
||||
],
|
||||
};
|
||||
});
|
||||
})
|
||||
.flat();
|
||||
}
|
||||
|
||||
private async createCalendarClientAsync(agent?: Agent) {
|
||||
|
||||
Reference in New Issue
Block a user