188 lines
5.9 KiB
JavaScript
188 lines
5.9 KiB
JavaScript
/**
|
|
* @copyright Copyright (c) 2020 Georg Ehrke
|
|
*
|
|
* @author Georg Ehrke <oc.list@georgehrke.com>
|
|
*
|
|
* @license AGPL-3.0-or-later
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Affero General Public License as
|
|
* published by the Free Software Foundation, either version 3 of the
|
|
* License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Affero General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Affero General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
import { getParserManager } from '@nextcloud/calendar-js'
|
|
import { getDateFromDateTimeValue } from '../utils/date.js'
|
|
import {
|
|
ITIP_MESSAGE_ADD,
|
|
ITIP_MESSAGE_CANCEL,
|
|
ITIP_MESSAGE_COUNTER,
|
|
ITIP_MESSAGE_DECLINECOUNTER,
|
|
ITIP_MESSAGE_PUBLISH,
|
|
ITIP_MESSAGE_REFRESH,
|
|
ITIP_MESSAGE_REPLY,
|
|
ITIP_MESSAGE_REQUEST,
|
|
} from './consts.js'
|
|
|
|
/**
|
|
* Creates a complete scheduling-object-object based on given props
|
|
*
|
|
* @param {object} props Scheduling-object-props already provided
|
|
* @return {object}
|
|
*/
|
|
const getDefaultSchedulingObject = (props = {}) => Object.assign({}, {
|
|
// Id of the scheduling-object
|
|
id: null,
|
|
// The cdav-library object storing the scheduling-object
|
|
dav: null,
|
|
// The parsed calendar-js object
|
|
calendarComponent: null,
|
|
// The uid of the scheduling-object
|
|
uid: null,
|
|
// Recurrence-id of the scheduling-object
|
|
recurrenceId: null,
|
|
// The uri of the scheduling-object
|
|
uri: null,
|
|
// The scheduling method
|
|
method: null,
|
|
// Whether or not the method is PUBLISH
|
|
isPublish: false,
|
|
// Whether or not the method is REQUEST
|
|
isRequest: false,
|
|
// Whether or not the method is REPLY
|
|
isReply: false,
|
|
// Whether or not the method is ADD
|
|
isAdd: false,
|
|
// Whether or not the method is CANCEL
|
|
isCancel: false,
|
|
// Whether or not the method is REFRESH
|
|
isRefresh: false,
|
|
// Whether or not the method is COUNTER
|
|
isCounter: false,
|
|
// Whether or not the method is DECLINECOUNTER
|
|
isDeclineCounter: false,
|
|
// Whether or not the scheduling-object exists on the server
|
|
existsOnServer: false,
|
|
}, props)
|
|
|
|
/**
|
|
* Maps a calendar-object from c-dav to our calendar-object object
|
|
*
|
|
* @param {VObject} dav The c-dav VObject
|
|
* @return {object}
|
|
*/
|
|
const mapCDavObjectToSchedulingObject = (dav) => {
|
|
const parserManager = getParserManager()
|
|
const parser = parserManager.getParserForFileType('text/calendar', {
|
|
preserveMethod: true,
|
|
processFreeBusy: true,
|
|
})
|
|
|
|
// This should not be the case, but let's just be on the safe side
|
|
if (typeof dav.data !== 'string' || dav.data.trim() === '') {
|
|
throw new Error('Empty scheduling object')
|
|
}
|
|
|
|
parser.parse(dav.data)
|
|
const calendarComponentIterator = parser.getItemIterator()
|
|
const calendarComponent = calendarComponentIterator.next().value
|
|
if (!calendarComponent) {
|
|
throw new Error('Empty scheduling object')
|
|
}
|
|
|
|
const firstVObject = getFirstObjectFromCalendarComponent(calendarComponent)
|
|
|
|
let recurrenceId = null
|
|
if (firstVObject.recurrenceId) {
|
|
recurrenceId = getDateFromDateTimeValue(firstVObject.recurrenceId)
|
|
}
|
|
|
|
if (!calendarComponent.method) {
|
|
throw new Error('Scheduling-object does not have method')
|
|
}
|
|
|
|
return getDefaultSchedulingObject({
|
|
id: btoa(dav.url),
|
|
dav,
|
|
calendarComponent,
|
|
uid: firstVObject.uid,
|
|
uri: dav.url,
|
|
recurrenceId,
|
|
method: calendarComponent.method,
|
|
isPublish: calendarComponent.method === ITIP_MESSAGE_PUBLISH,
|
|
isRequest: calendarComponent.method === ITIP_MESSAGE_REQUEST,
|
|
isReply: calendarComponent.method === ITIP_MESSAGE_REPLY,
|
|
isAdd: calendarComponent.method === ITIP_MESSAGE_ADD,
|
|
isCancel: calendarComponent.method === ITIP_MESSAGE_CANCEL,
|
|
isRefresh: calendarComponent.method === ITIP_MESSAGE_REFRESH,
|
|
isCounter: calendarComponent.method === ITIP_MESSAGE_COUNTER,
|
|
isDeclineCounter: calendarComponent.method === ITIP_MESSAGE_DECLINECOUNTER,
|
|
existsOnServer: true,
|
|
})
|
|
}
|
|
|
|
/**
|
|
* Maps a calendar-component from calendar-js to our calendar-object object
|
|
*
|
|
* @param {CalendarComponent} calendarComponent The calendarComponent to create the calendarObject from
|
|
* @return {object}
|
|
*/
|
|
const mapCalendarJsToSchedulingObject = (calendarComponent) => {
|
|
const firstVObject = getFirstObjectFromCalendarComponent(calendarComponent)
|
|
|
|
let recurrenceId = null
|
|
if (firstVObject.recurrenceId) {
|
|
recurrenceId = getDateFromDateTimeValue(firstVObject.recurrenceId)
|
|
}
|
|
|
|
if (!calendarComponent.method) {
|
|
throw new Error('Scheduling-object does not have method')
|
|
}
|
|
|
|
return getDefaultSchedulingObject({
|
|
calendarComponent,
|
|
uid: firstVObject.uid,
|
|
recurrenceId,
|
|
method: calendarComponent.method,
|
|
isPublish: calendarComponent.method === ITIP_MESSAGE_PUBLISH,
|
|
isRequest: calendarComponent.method === ITIP_MESSAGE_REQUEST,
|
|
isReply: calendarComponent.method === ITIP_MESSAGE_REPLY,
|
|
isAdd: calendarComponent.method === ITIP_MESSAGE_ADD,
|
|
isCancel: calendarComponent.method === ITIP_MESSAGE_CANCEL,
|
|
isRefresh: calendarComponent.method === ITIP_MESSAGE_REFRESH,
|
|
isCounter: calendarComponent.method === ITIP_MESSAGE_COUNTER,
|
|
isDeclineCounter: calendarComponent.method === ITIP_MESSAGE_DECLINECOUNTER,
|
|
})
|
|
}
|
|
|
|
/**
|
|
* Extracts the first object from the calendar-component
|
|
*
|
|
* @param {CalendarComponent} calendarComponent The calendar-component
|
|
* @return {any} First VEvent / VJournal / VTodo / VFreeBusy
|
|
*/
|
|
const getFirstObjectFromCalendarComponent = (calendarComponent) => {
|
|
const vObjectIterator = calendarComponent.getVObjectIterator()
|
|
const firstVObject = vObjectIterator.next().value
|
|
if (firstVObject) {
|
|
return firstVObject
|
|
}
|
|
|
|
const vFreeBusyIterator = calendarComponent.getFreebusyIterator()
|
|
return vFreeBusyIterator.next().value
|
|
}
|
|
|
|
export {
|
|
getDefaultSchedulingObject,
|
|
mapCDavObjectToSchedulingObject,
|
|
mapCalendarJsToSchedulingObject,
|
|
}
|