Add new calendar from ics-file and continously update it with script?

I have combined 5 different calendars into one by scripting. I can manually import this and create a new calendar but for the future I want to update this calendar using script (in simplest form just replace the existing with a completely new). I have found the occ:commands about migrating calendars from owncloud but have not seen how to import an ics-file by any command or script.

Although I’ve personally not tested it but this could be a possible way to go for you.

I can manually import the combined ics-file to Nextcloud with no problem
I try to import it as a new ics-file using this command

sudo curl -T /home/rollanders/kombineradedit.ics -u User:Password https://mydomain.com/remote.php/dav/calendars/User/kombinerad/

I get this error

<?xml version="1.0" encoding="utf-8"?>

<d:error xmlns:d=“DAV:” xmlns:s=“http://sabredav.org/ns”>
<s:exception>Sabre\DAV\Exception\UnsupportedMediaType</s:exception>
<s:message>Validation error in iCalendar: A calendar object on a CalDAV server may only have components with the same UID.</s:message>
</d:error>

Any hint on what is wrong?

I‘ve never tried importing an iCalendar object manually, but I understand that error message in such a way, that you can only import an iCalender object containing a single iCalendar component.

If this ics-file is an iCalendar object (a single calendar with different components) : can‘t you upload that ics file to some location (with the help of a script after every change) and subscribe to this ics-file in the nextcloud calendar app? It will be shown as a calendar and will also be synced to all connected devices.

Just out of curiosity, I‘ve got a question about:

Is this an iCalendar object containing 5 different iCalendar components (a single calendar with different components), or are you talking about an iCalendar stream containing 5 different iCalendar objects (an ics file containing different calendars)?

Thanks Bernie-O
In NC we have 5 calendars for booking 5 different localities. Those who clean the rooms need to know when they are occupied. I can share all 5 calendars with them, but would prefer to combine them into one single calendar that can be shared by a link.

I have used calcardbackup to extract the 5 calendars from NC as ics-files. Using a script I strip the head and tail from each ics-file, then merge them and finally add the head and tail. I then get a combined ics-file containg events from all the 5 calendars.

I have validated this file here with no errors. The ics-file currently contains about 65 events. It is not a calendar stream but the file is updated daily by o cronjob running the scripts.

I can import this ics-file manually via NCs calendars user interface with no errors. If this import will respond to future changes in the imported file everything is fine, but I assume that the import is just once and will not reflect future changes. That is why I want to do this with a script. I found this ics2dav.sh which I thought would do what I wanted but got the error.

You say that “I understand that error message in such a way, that you can only import an iCalender object containing a single iCalendar component.” So the problem is that the ics-file contains multipe events? I have seen some script that chop an ics-file into multiple files containing only one event. Would that work?

You say “if this ics-file is an iCalendar object (a single calendar with different components) : can‘t you upload that ics file to some location (with the help of a script after every change) and subscribe to this ics-file in the nextcloud calendar app?”

I can copy the ics-file anywhere but how can I subscribe to it? It is such a script I am looking for!
I tried to copy the file to a NC folder, make a share-link and used that to create a calendar subscription, but then I got a message that the server did not gave access to the calendar (error 404).

I am in a hurry right now, so only a short answer, which might be the solution though.

When creating the calendar subscription, did you append /download to the share-link so it looks like:

https://your.nextcloud.domain/index.php/s/XXXXXXXXXXXX/download

Then the subscription should work. The subscribers won‘t be able to create/delete/edit events. But as far as I understood that is not needed in your case.

EDIT: a password protected share link will probably not work!

That worked.
I copy the ics-file from the /home/myfolder/ to /var/nc_data/User/files/folder/combined.ics with a script.

I needed to sudo -u www-data php occ files:scan --all before I could see it.

The shared link, added with /download looks like this https://mydomain.com/s/cEc4tNNLjy8RXCH/download

In the NC calender interface I use this link to subscribe to the calendar. And it was imported OK.

My question now is if this new calender will be updated when the ics file is updated by the scripts? Is the calendar prenumeration “live”? Or do I need a cron job to refresh the calendar?

See this https://github.com/nextcloud/server/issues/15967 which is about a similar situation.

And another problem came up - it seems I cannot share this calendar.

What you also could do is to upload the ics-file with curl. Then you don’t need the possibly resource-hungry occ files:scan --all:

curl -u [USER]:[PASS] -T /local/path/to/ics-file https://[NEXTCLOUD]/remote.php/dav/files/[USERNAME]/[PATH]

See here for a detailed description:
https://docs.nextcloud.com/server/16/user_manual/files/access_webdav.html#accessing-files-using-curl

Yes, that will be the case - maybe you have to wait until cron.php will be run the next time (I am not sure about that though).

Unfortunately this seems to be true. So your users need to subscribe to that calendar.

1 Like

I actually used curl

(sudo curl -T /home/rollanders/kombineradedit.ics -u User:Password https://mydomain.com/remote.php/dav/calendars/User/kombinerad.ics)

But got the errors.

But anyway occ files:scan is not a problem. Takes a few seconds. And I think I can choose to scan only one folder? Or one user? Need to check that.

But not shareable is a problem. Few users will manage to subscribe to the calendar.

Thanks for your help.

You tried to import the ics file to /dav/calendar with curl. I meant to upload the file to /dav/files

You could add the subscription manually to the database for the according users.

How can I add the subscription manually to the database for the according users.? I am admin but I don’t know how to import icals for other users. That would be very helpful if it can be done.

I realise that what I want is to Import the ics-file as a calender and have some kind of cron-job to do that regularly. This would allow me to share the calendar.
The present solution is to subscribe to the calendar, which does not allow me to share it.
Any hints on how I can script the Import (not Subscription)?

Sorry - I’ve been a bit busy the last couple of days.

As I still don’t think that it is possible to import an ics file with more than one event via command line to Nextcloud - here is how you can add a subscribed calendar to the database for a user (example is for MySQL/MariaDB):

INSERT INTO `[PREFIX]calendarsubscriptions` (`uri`, `principaluri`, `displayname`, `calendarcolor`, `source`, `refreshrate`) VALUES ('[URI]', 'principals/users/[USERNAME]', '[DISPLAYNAME]', '[CALENDARCOLOR]', '[LINK_TO_ICS_FILE]', '[REFRESHRATE]');

You need to adapt:
[PREFIX] - prefix of the database tables (‘dbtableprefix’ in config.php)
[URI] - the uri under that clients will use (only lower case letters and dash allowed)
[USERNAME] - username of the user
[DISPLAYNAME] - the name of the calendar that will be displayed for the user (in Nextcloud calendar app or in clients)
[CALENDARCOLOR] - HEX color value you would like the calendar to have
[LINK_TO_ICS_FILE] - the link to the ics file
[REFRESHREATE] - duration of refreshrate after ISO8601

After you added this to the database you need to run occ maintenance:repair to add a job to the database to cache the webcal events (only for Nextcloud > 15.0).

Hi there,

I’m looking at doing the same thing i.e. importing a calendar through a script (Nextcloud 16.0.4, calendar 1.7.1).

@rollanders did you eventually manage to import the calendar directly from an ics file?

Thanks for your help

I gave it up. But the solution is probably to split the ical-file into multiple files - one for each event. Then it should work with curl as tried. There are such scripts. But have not tried it yet.

I know I’m a bit late to reply - but as you already found my script I think it will fit your needs.

You want to import an (externally) generated *.ics file to a Nextcloud calendar - that’s the same use case I have - just that I get this file through WebDAV. So either you do the same, or you put the script on the same server and set $ics_url to /home/rollanders/kombineradedit.ics and make sure fopen() has access to this file.

Currently my script has no intelligent sync logic in it - it just deletes the old events, and creates new ones (which takes some time and clogs the activity feed), but I didn’t yet have motivation to improve this.

2 Likes

I have a similar problem: I would like to import an ics file into a Nextcloud calendar and delete all calendar entries before.

I found the script from stefan-muc (man thanks :+1: ) that seems to do almost exactly what I want. As I dont’ want to upload the ics file to nextcloud first I changed the source to

$config[‘ICS’][‘url’] = ‘./x.ics’;

If I start it it seems to do something and can find the ics file, but the output also reports some errors:

PHP Notice: Undefined index: DAV::href in […]/include/caldav-client-v2.php on line 758
PHP Notice: Undefined index: in […]/include/caldav-client-v2.php on line 759
PHP Notice: Undefined index: in […]/include/caldav-client-v2.php on line 625
PHP Notice: Undefined offset: 4 in […]/include/caldav-client-v2.php on line 627
PHP Notice: Undefined offset: 4 in […]/include/caldav-client-v2.php on line 628
[2020-09-16 19:37:07] INFO: Deleted 0 events
[2020-09-16 19:37:07] INFO: Not touched 1 events
[2020-09-16 19:37:07] INFO: Created 461 events

I’m using the current version from github cloned 2 hours ago. Dumping the server response before above mentioned line 758 I can see:

<s:message>Node with name ‘MyCal_NC’ could not be found</s:message>

as part of the response. A Calendar with that name exists but I am not sure if the URL built by the config file (“https://www.xxx.yy/nextcloud//remote.php/dav/calendars/username/MyCal_NC/”) is correct if xxx, yyy and username are replaced with the correct values.

What could be the reason for this problem?

I found the reason for the error: the name of the calendar uses upper and lower case letters but for CalDAV the name must be in lower case. Now the script works and manages to import an ICS file.

I like that the script checks for unmodified entries and skips these. My ICS file always contains events for now +/-400 days. So with every update only a few should change. Checking for changed ones is quite fast but creating new events happens one per second (which is limited by Nextcloud on my server).

Looking at the statistics I found one thing a bit strange: if I import the same ICS file multiple times the statistics stays the same but always contains created events (e.g. 0 deleted, 293 not touched and 169 created; the total number of events in the file is 463 thus 1 is missing). All of the (few) “created” ones I checked by hand are exceptions from a series.

I will try to check if the representation of those output by Nextcloud differs from the input and thus creates a different hash.

Not to be knitpicking here, but it may clear things up a bit further and may help others in the future as the last part of the link is not necessarily the calender name in lower case characters. The correct link to the desired calender is:

https://[SERVER]/remote.php/dav/calendars/[USERNAME]/[URI]

where [URI] can be found in table oc_calendars in your Nextcloud database for the according calender (table prefix might be different from oc_ in your installation).

1 Like