Skip to content

feat: ICS Calendars plugin#265

Open
Omar007 wants to merge 1 commit into
tchapi:mainfrom
Omar007:feature/ics-cals
Open

feat: ICS Calendars plugin#265
Omar007 wants to merge 1 commit into
tchapi:mainfrom
Omar007:feature/ics-cals

Conversation

@Omar007
Copy link
Copy Markdown

@Omar007 Omar007 commented May 29, 2026

I was looking to replace my old calendar setup and decided to switch to Davis but coming from DAViCal there was one thing I was really missing; the external bind functionality it provided. As not all clients can automatically handle advertised webcals, I needed work-arounds or would just not have access to certain calendars on certain devices.
This plugin is heavily inspired by that functionality to facilitate something similar by utilizing the subscriptions functionality already present in Davis.

In short, when the plugin is enabled, it will create calendars for each added subscription, re-using any existing data.
When the subscription is removed, so is the calendar (for the given user only or completely if no other user has it anymore).

A (re-)sync can be forced with the dav:sync-ics-calendars console command.

Note that there's very few clients that actually allow you to add subscriptions to the server in the first place. While adding a custom command or BIND method like DAViCal had done would also have been possible, the subscriptions can already be created using a normal MKCALENDAR operation. As such, I opted not to add anything custom.
If anything, expanding the webinterface to allow managing subscriptions would likely be the much better way to go.

In the mean time, to create a subscription you'd use roughly something like:

curl -u '<user>:<pass>' \
  -X MKCALENDAR \
  -H 'Content-Type: application/xml; charset=utf-8' \
  --data '<?xml version="1.0"?>
<C:mkcalendar xmlns:D="DAV:"
    xmlns:C="urn:ietf:params:xml:ns:caldav"
    xmlns:CS="http://calendarserver.org/ns/"
    xmlns:I="http://apple.com/ns/ical/">
  <D:set>
    <D:prop>
      <D:displayname>Subscribed Holidays</D:displayname>
      <D:resourcetype>
        <D:collection/>
        <CS:subscribed/>
      </D:resourcetype>
      <CS:source>
        <D:href>https://calendars.icloud.com/holidays/nl_nl.ics</D:href>
      </CS:source>
      <I:calendar-color>#FF9500FF</I:calendar-color>
      <I:calendar-order>0</I:calendar-order>
    </D:prop>
  </D:set>
</C:mkcalendar>' \
  'http://<host>/dav/calendars/<user>/<subscription-uri>/'

Removal is simply a DELETE on the same URL:

curl -u '<user>:<pass>' \
  -X DELETE \
  'http://<host>/dav/calendars/<user>/<subscription-uri>/'

This results in something like:
screenshot_2026-05-29T18:42:50

Automatic (re-)sync based on a subscription's refreshrate and/or a default fallback interval within Davis itself is currently not implemented. Refreshing on a fixed interval can be done by using the dav:sync-ics-calendars console command (e.g. scheduling it with cron).

@tchapi
Copy link
Copy Markdown
Owner

tchapi commented May 29, 2026

Hi

Thanks for the work. One caveat I see on this server-side subscription feature is that clients that manage client-side subs will end up with twice the same calendar when the plugin is enabled, while clients that do not manage subs will only (correctly) have it once (the "generated" one). Am I correct?

So in my opinion, server-side subscription need to be a different mechanism — not tied to actual, client-side subs

@tchapi tchapi self-assigned this May 29, 2026
@tchapi tchapi added the enhancement New feature or request label May 29, 2026
@Omar007
Copy link
Copy Markdown
Author

Omar007 commented May 29, 2026

You are correct on a technical level but not on a functional level as far as I know.
As you note, technically any clients that does support webcals can see and present both the generated one as well as the original webcal. That said, I have not seen a single calendar client that doesn't allow you to either enable or disable a calendar from being shown or synced.
It could be good to note this alongside the ICSCALENDARS_ENABLED flag at minimum though 🤔
Is there a standard location where the available flags are documented? Is the .env file supposed to fulfil that documentation role?

Only making it available as a completely separate mechanism is certainly possible on a technical level, as is extending this to provide both options (behind a flag or w/e). That would require much more invasive changes though.
As far as I can tell, the only way to do that would be to create separate tables, entrypoints, front-end handling, side-channels/methods to insert, manage and store the bindings separately, etc. You wouldn't be able to rely on any standard components already present aside from the eventually generated calendar 🤔

EDIT: this implementation actually has the exact same effect as the existing birthday calendar plugin. Clients that just use the contact birthday information also get duplicates if you use that plugin unless you disable the generated birthday calendar client side.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants