/org-caldav

Caldav sync for Emacs orgmode

Primary LanguageShellGNU General Public License v3.0GPL-3.0

Cal-sync

Caldav sync for Emacs Orgmode

This package is my personal take on synchronizing to one online calendar via caldav. I was heavily inspired by org-caldav, which wasn’t working the way I wanted, and after some patches I wrote my own version.

This project is a minimal take, it is a step back from org-caldav feature set, yet it solves what annoyed me in a simple way.

What is different?

  • I don’t care about backwards compatibility. I run Arch Linux and only care about supporting my latest version. Same for org-mode.
  • There is no sync. I don’t keep a database (a file with the current state of the calendar events). I download all the events and convert them to org-mode, then I just push my edits to the caldav server. I track my org-files with git.
  • Pushes to the server run asynchronously.
  • There are no checks about events having changed on the server, this exporter just pushes and overwrites. There is no backup.
  • I only support one target calendar.
  • I don’t care about Google’s OAuth, I self-host nextcloud and don’t use OAuth at the moment.
  • Simplified icalendar exporter. I use the org backend instead of ascii backend, thus the syntax does not get damaged on export. It looks fine on the caldav calendar and it is much simpler when importing again from ics to org.
  • No support for org sexp
  • Implemented by an amateur elisper.

Does it work?

Nextcloud
Used regularly
Radicale
Used during development. Without using any authentication

IMPORTANT : Before using this code, please make sure you have backups of your precious Org files and Calendar files. Also, I strongly suggest to create a new, empty calendar on your server for using this package.

ALSO IMPORTANT: When using this package, possibly all Org entries will get an UID property. If you don’t want this, then do not use this package; there is just no way around that. It is the only reliable way to uniquely identify Org entries.

ALSO IMPORTANT An Org entry can store much more information than an iCalendar entry, so there is no one-to-one correspondence between the two formats which makes syncing a bit difficult. The converse is also true, the importer has no idea about concepts like attendees, organizers, reminders and it intentionally ignores recurring events.

Setup

  • Create a new calendar in your server, the name does not matter
  • Set cal-sync-url to the base address of your CalDAV server e.g.:
(setq cal-sync-url "https://nextcloud-server-url/remote.php/dav/calendars/USERID")
  • Set cal-sync-calendar-id to the new calendar you just created.
(setq cal-sync-calendar-id "mycalendar")

Storing authentication information in authinfo/netrc

If you don’t want to enter your user/password every time, you can store it permanently in an authinfo file. In Emacs, the auth-source package takes care of that, but the syntax for https authentication is a bit peculiar. You have to use a line like the following

machine server-fqdn:443 port https login username password secret

Note that you have to specify the port number in the URL and also specify ‘https’ for the port. This is not a bug. For more information, see (info “auth”), especially section “Help for users”.

Since you are storing your password in a file you should encrypt it using GnuPG. Emacs will prompt you for a decryption key when it tries to read the file.

Starting from scratch based on a existing calendar

The next code example shows how you can import your entire calendar into one org file. It is a simple import it does not consider changing in anyway the content of your events(if it had bulletpoints with *, they’ll be org entries). You’ll need to clean this file up. I’ll store it on /tmp/calendar.org.

(defun cal-sync-new-calendar (status targe-file)
  (unless (cal-sync-error-handling status (current-buffer))
    (let ((org-string (mapconcat 'cal-sync--org-entry
                                 (cal-sync-convert-event (current-buffer))
                                 "\n")))
      (with-current-buffer (find-file-noselect targe-file)
        (erase-buffer)
        (org-mode)
        (insert org-string)))))

(url-retrieve "https://nextcloud-server-url/remote.php/dav/calendars/USERID/CALENDAR-ID/?export"
              'cal-sync-new-calendar
              '("/tmp/calendar.org"))

Timezones

Timezone handling is plain horrible, I just keep everything in UTC on the server and let the import/export work locally. If you are not into that the tests, give an example of setting up a timezone.