n8n-nodes-nextcloud-calendar
Version:
n8n Node für die Integration mit Nextcloud Calendar
325 lines • 11.8 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.parseEventResults = parseEventResults;
exports.parseICalEvent = parseICalEvent;
function parseICalDate(date) {
const year = parseInt(date.substr(0, 4));
const month = parseInt(date.substr(4, 2)) - 1;
const day = parseInt(date.substr(6, 2));
if (date.includes('T')) {
const hour = parseInt(date.substr(9, 2));
const minute = parseInt(date.substr(11, 2));
const second = parseInt(date.substr(13, 2));
return new Date(Date.UTC(year, month, day, hour, minute, second));
}
return new Date(Date.UTC(year, month, day));
}
function parseICS(icsData) {
const lines = icsData.split('\n').map(line => line.replace(/\r$/, ''));
const event = {};
let inEvent = false;
for (let i = 0; i < lines.length; i++) {
const rawLine = lines[i].trim();
if (rawLine === 'BEGIN:VEVENT') {
inEvent = true;
continue;
}
if (rawLine === 'END:VEVENT') {
break;
}
if (!inEvent || rawLine.length === 0) {
continue;
}
const colonIdx = rawLine.indexOf(':');
if (colonIdx === -1)
continue;
const keyWithParams = rawLine.slice(0, colonIdx);
const value = rawLine.slice(colonIdx + 1);
const [key, ...paramParts] = keyWithParams.split(';');
const params = {};
for (const part of paramParts) {
const idx = part.indexOf('=');
if (idx > -1) {
const pKey = part.slice(0, idx);
const pVal = part.slice(idx + 1);
params[pKey] = pVal;
}
}
switch (key) {
case 'UID':
event.uid = value;
break;
case 'SUMMARY':
event.summary = value;
break;
case 'DESCRIPTION':
event.description = value;
break;
case 'LOCATION':
event.location = value;
break;
case 'DTSTART':
event.start = parseICalDate(value);
if (params.TZID)
event.tzidStart = params.TZID;
break;
case 'DTEND':
event.end = parseICalDate(value);
if (params.TZID)
event.tzidEnd = params.TZID;
break;
case 'CREATED':
event.created = parseICalDate(value);
break;
case 'LAST-MODIFIED':
event.lastmodified = parseICalDate(value);
break;
case 'STATUS':
event.status = value;
break;
case 'DTSTAMP':
event.dtstamp = parseICalDate(value);
break;
case 'SEQUENCE':
event.sequence = Number(value);
break;
case 'TRANSP':
event.transparency = value;
break;
case 'CATEGORIES':
event.categories = value.split(',').map(v => v.trim()).filter(Boolean);
break;
case 'CLASS':
event.class = value;
break;
case 'RRULE':
event.rrule = value;
break;
case 'RECURRENCE-ID':
event.recurrenceId = value;
break;
case 'EXDATE':
(event.exdate || (event.exdate = [])).push(value);
break;
case 'RDATE':
(event.rdate || (event.rdate = [])).push(value);
break;
case 'PRIORITY':
event.priority = Number(value);
break;
case 'DURATION':
event.duration = value;
break;
case 'GEO': {
const parts = value.split(';');
if (parts.length === 2) {
const lat = Number(parts[0]);
const lon = Number(parts[1]);
if (!Number.isNaN(lat) && !Number.isNaN(lon)) {
event.geo = { latitude: lat, longitude: lon };
}
}
break;
}
case 'ATTENDEE': {
if (!event.attendee) {
event.attendee = [];
}
const [paramsStr, email] = value.split('mailto:');
const attendee = {
val: `mailto:${email}`,
params: {}
};
if (paramsStr) {
paramsStr.split(';').forEach((param) => {
const [paramKey, paramValue] = param.split('=');
if (paramKey && paramValue) {
attendee.params[paramKey] = paramValue;
}
});
}
event.attendee.push(attendee);
break;
}
case 'ORGANIZER': {
const [orgParams, orgEmail] = value.split('mailto:');
event.organizer = {
val: `mailto:${orgEmail}`,
params: {}
};
if (orgParams) {
if (event.organizer && event.organizer.params) {
orgParams.split(';').forEach((param) => {
const [paramKey, paramValue] = param.split('=');
if (paramKey && paramValue && event.organizer) {
event.organizer.params[paramKey] = paramValue;
}
});
}
}
break;
}
default: {
if (!event.raw)
event.raw = {};
if (event.raw[key]) {
const existing = event.raw[key];
if (Array.isArray(existing)) {
existing.push(value);
}
else {
event.raw[key] = [existing, value];
}
}
else {
event.raw[key] = value;
}
break;
}
}
}
return { vevent: event };
}
function parseEventResults(events) {
const eventResults = [];
for (const event of events) {
const eventData = 'data' in event
? event.data
: event.props?.['calendar-data']?._text;
if (!eventData) {
continue;
}
const parsedData = parseICS(eventData);
const eventInfo = parsedData.vevent;
const attendees = [];
if (eventInfo.attendee) {
const attendeeList = Array.isArray(eventInfo.attendee)
? eventInfo.attendee
: eventInfo.attendee
? [eventInfo.attendee]
: [];
for (const attendee of attendeeList) {
const email = attendee?.val?.replace('mailto:', '') ?? '';
const params = attendee?.params || {};
attendees.push({
email,
displayName: params.CN,
role: params.ROLE || 'REQ-PARTICIPANT',
rsvp: params.RSVP === 'TRUE',
status: params.PARTSTAT || 'NEEDS-ACTION',
});
}
}
let organizer = { email: '', displayName: '' };
if (eventInfo.organizer && eventInfo.organizer.val) {
organizer = {
email: eventInfo.organizer.val.replace('mailto:', ''),
displayName: eventInfo.organizer.params?.CN ?? '',
};
}
const url = 'url' in event
? event.url
: event.href ?? '';
const etag = 'etag' in event
? event.etag
: event.props?.getetag?._text ?? '';
eventResults.push({
url: url || '',
etag: etag || '',
uid: eventInfo.uid ?? '',
title: eventInfo.summary ?? '',
start: eventInfo.start?.toISOString(),
end: eventInfo.end?.toISOString(),
tzidStart: eventInfo.tzidStart,
tzidEnd: eventInfo.tzidEnd,
dtstamp: eventInfo.dtstamp?.toISOString(),
description: eventInfo.description ?? '',
location: eventInfo.location ?? '',
created: eventInfo.created,
lastModified: eventInfo.lastmodified,
status: eventInfo.status,
sequence: eventInfo.sequence,
transparency: eventInfo.transparency,
categories: eventInfo.categories,
class: eventInfo.class,
rrule: eventInfo.rrule,
recurrenceId: eventInfo.recurrenceId,
exdate: eventInfo.exdate,
rdate: eventInfo.rdate,
priority: eventInfo.priority,
duration: eventInfo.duration,
geo: eventInfo.geo,
attendees,
organizer,
rawProperties: eventInfo.raw,
});
}
return eventResults.sort((a, b) => {
const startA = a?.start ?? '';
const startB = b?.start ?? '';
if (startA < startB) {
return -1;
}
else if (startA > startB) {
return 1;
}
else {
return 0;
}
});
}
function parseICalEvent(calendarObject) {
const icalData = parseICS(calendarObject.data);
const event = icalData.vevent;
const response = {
uid: event.uid ?? '',
title: event.summary ?? '',
start: event.start?.toISOString(),
end: event.end?.toISOString(),
tzidStart: event.tzidStart,
tzidEnd: event.tzidEnd,
dtstamp: event.dtstamp?.toISOString(),
description: event.description ?? '',
location: event.location ?? '',
url: calendarObject.url ?? '',
etag: calendarObject.etag ?? '',
created: event.created,
lastModified: event.lastmodified,
status: event.status,
sequence: event.sequence,
transparency: event.transparency,
categories: event.categories,
class: event.class,
rrule: event.rrule,
recurrenceId: event.recurrenceId,
exdate: event.exdate,
rdate: event.rdate,
priority: event.priority,
duration: event.duration,
geo: event.geo,
organizer: event.organizer ? {
email: event.organizer.val.replace('mailto:', ''),
displayName: event.organizer.params?.CN,
} : undefined,
attendees: !event.attendee
? undefined
: Array.isArray(event.attendee)
? event.attendee.map((a) => ({
email: a.val.replace('mailto:', ''),
displayName: a.params?.CN,
role: a.params?.ROLE ?? 'REQ-PARTICIPANT',
status: a.params?.PARTSTAT ?? 'NEEDS-ACTION',
rsvp: a.params?.RSVP === 'TRUE',
}))
: [{
email: event.attendee.val.replace('mailto:', ''),
displayName: event.attendee.params?.CN,
role: event.attendee.params?.ROLE ?? 'REQ-PARTICIPANT',
status: event.attendee.params?.PARTSTAT ?? 'NEEDS-ACTION',
rsvp: event.attendee.params?.RSVP === 'TRUE',
}],
rawProperties: event.raw,
};
return response;
}
//# sourceMappingURL=parser.js.map