nextcloud/server

Users should be able to choose whether reminders are generated for events in the birthday calendar

nursoda opened this issue Β· 61 comments

I'm not sure if it's correct in "server" component - but it does not only affect calendar or contacts, so it's either both - or "server", thus I report it here. Feel free to point me to re-insert it somewhere else.

Steps to reproduce
Import a vcf file that contains data that contains birthday data.

Actual behaviour
All birthday events in calendar are created with reminder (valarm).

Expected behaviour
The admin should be able to set not to create any EVENT for contacts -or-
The user should be able to opt not to create any EVENT for imported contacts -or-
The admin should be able to set not to create any REMINDER for contacts -or-
The user should be able to opt not to create remindes (valarms) while importing (contacts).

Server configuration
Debian jessie fully patched, Apache 2.4.10 prefork, PHP 5.6.24, MySQL 5.5.52, Nextcloud 10.0 (stable) freshly installed via Webinstaller.

Well you can also just not sync that birthday calendar, to get rid of the events?

True, thanks!

However, that's not the point, is it? I like to be able to see birthdays on all devices, yet not be reminded.

At least not in the middle of the night ;-) But that's a more general request for enhancement to be able to set a fixed time or time offset for default alarms of all-day events. Which in turn could be a per installation, per account or a per calendar setting.

@jancborchardt can we have your input here?

It's indeed extremely annoying (actually was, see workaround at the end of this comment). I moved from owncloud 9.x to nextcloud 10.0.1 yesterday. I didn't experience this problem before. The reminder pops up every time when the SOGO connector (Thunderbird/Lightning) synchronizes the birthday calendar that is automatically derived from the contacts.

I'm not sure whether this is related to importing contacts, though. I had all my contacts in the database already. So I would rephrase the requirement as "Users should be able to choose whether reminders are generated for events in the birthday calendar".

(To avoid unnecessary searching: the corresponding owncloud issue is owncloud/core#26118. It refers to the Thunderbird problem with read-only calendars https://bugzilla.mozilla.org/show_bug.cgi?id=356002. There I found that I can turn off reminders for a specific calendar in lightning -- wasn't aware of that --, which solved the problem for me.)

Yes, silencing a calendar in a user agent (here: TB) works, but it's the wrong way if you don't want/need reminders at all. Problem is that you need to silence ALL user agents. Using Business Calendar on Android for example, I can switch off the SOUND, but not the notification.

Yeah, that's why the issue is still open ;)

The user should be able to opt not to create remindes (valarms) while importing (contacts).

This seems to be the most sensible course of action. It’s definitely not an admin decision.

@georgehrke @raghunayyar @tcitworld we could have a default reminders setting for each calendar, including subscribed ones like birthdays?

I'm not sure if a default setting for each calendar is a good idea. The problem here arises from the special birthday calendar that is generated by the server. And for this generated calendar, it is reasonable to allow the user to control if alarms should be generated along with the dates.

For "ordinary" user maintained calendars it is not the servers job to modify them. It should take and preserve whatever clients send to it. Any different behavior makes things harder to understand.

Of course, I have to admit that if the default setting is to not add alarms to dates without alarms, then the proposed feature would do no harm.

For "ordinary" user maintained calendars it is not the servers job to modify them. It should take and preserve whatever clients send to it. Any different behavior makes things harder to understand.

The server is never ever going to change any events sent by some clients.

There is a CalDAV extension providing some mechanisms for defining default alarms for allDay and timed events (see https://tools.ietf.org/id/draft-daboo-valarm-extensions-01.html#rfc.section.9)
This extension actually requires the server to add the default VAlarms, but it's only used by some Apple clients and also not implemented by the CalDAV server nextcloud uses.

We could use something similar for the birthday calendar though.
Users will be able to define a custom default reminder and the server will take that choice into account when generating the birthday calendar.

@jancborchardt so where should we put this setting? Personal page? Contacts app? Calendar app?

I'd go for the calendar app.

I'd go for the calendar app.

From a user's perspective, I agree. It's the only place where the contact birthday calendar currently appears in the user interface. (And considering the requests to allow modification of color for this calendar just as with the others, it needs an "edit" dialog on the long run anyway.)

Instead of providing default alarms for each calendar, which most clients don't expect anyway, we should simply add a simple select to the calendar settings, that provides the following options:

  • None
  • 9AM on day of birthday
  • 1 day before (9AM)
  • 2 days before (9AM)
  • 1 week before (9AM)

(This select will only influence the birthday calendar, having default alarms for ordinary events is a completely different topic)

@georgehrke sounds good!

@georgehrke

(This select will only influence the birthday calendar, having default alarms for ordinary events is a completely different topic)

I would actually want this feature for ordinary calendars. Should I open a new issue or is there one already regarding this?

I would actually want this feature for ordinary calendars. Should I open a new issue or is there one already regarding this?

What exact feature do you want? :)

I don't think we will go for a dedicated input for each calendar.
But I can very well imagine adding a user-based option for all (non-birthday) calendars.
One for all day and one for timed events.

This option should only affect events created in the calendar app though. As said above, the standard for adding alarms on the server is a very uncommon and used only by apple software (to my knowledge). Implementing it might cause very weird behavior in some clients.

This is what I want:

None
9AM on day of birthday
1 day before (9AM)
2 days before (9AM)
1 week before (9AM)

Works for me. :)

But I can very well imagine adding a user-based option for all (non-birthday) calendars.

Okay :)
Can you please open a feature request in the calendar bug tracker?

Unspecified: What shall happen if one already has birthday events and changes the general setting? Re-Create all birthday calendar alarms?

Anyone willing to set a milestone for this issue? ;-)

Sidenote in case someone stumbles upon the mute issue also discussed within this bug: Read-only calendars do not contain alarms since NC 13, see #6903. Mind that e.g. mobile clients cache existing appointments. After I removed and re-connected my account, an event that has an alarm for the "read-only-user" did not have an alarm on my device.

Seems the issue is not mute, as 6903 only concerns shared calendars.
I hope that I'm not seeing something, could you please point me in the right direction on how to get rid of the annoying birthday alarms at midnight?

This issue is still open -> you can't select it yet.

I'm totally for an alarm in a calendar settings. While

None
9AM on day of birthday
1 day before (9AM)
2 days before (9AM)
1 week before (9AM)

Is already good, setting it with more freedom would be better.
For example, I have friends which are further away now, and a 1 month alarm let me organize myself and the other friends to make a surprise and be able to reserve a train/plane in advance, etc.

Hello!

I have nextcloud 14.0.1 running, but didn't manage to find this setting.
Where can I set the default reminders for the birthday calender of contact entries or disable them?

Hi, it would be cool if this could be added to the next milestone :)

@matthias-g Feel free to step in and help implementing this. :)

Any news about this issue yet?

I am also very annoyed by those nightly birthday notifications that I can not disable… πŸ™

After every upgrade I do:
sudo -u www-data sed -i 's#\t$alarm = $vCal#\t/**$alarm = $vCal#g' /var/www/nextcloud/apps/dav/lib/CalDAV/BirthdayService.php sudo -u www-data sed -i 's#$vEvent->add($alarm);#$vEvent->add($alarm);*/#g' /var/www/nextcloud/apps/dav/lib/CalDAV/BirthdayService.php

This comments out the five lines generating the alarms (line 283-287, actually in version 17.0.2.1). That's my workaround for this issue.

After every upgrade I do:
sudo -u www-data sed -i 's#\t$alarm = $vCal#\t/**$alarm = $vCal#g' /var/www/nextcloud/apps/dav/lib/CalDAV/BirthdayService.php sudo -u www-data sed -i 's#$vEvent->add($alarm);#$vEvent->add($alarm);*/#g' /var/www/nextcloud/apps/dav/lib/CalDAV/BirthdayService.php

This comments out the five lines generating the alarms (line 283-287, actually in version 17.0.2.1). That's my workaround for this issue.

Awesome, thank you very much!

Maybe you can push a commit to make several users happy? πŸ‘

An option for this should be visible to users at settings/admin/groupware

My solution would kill reminders for all users. So it's not a solution, but a workaround. Deactivating the reminders should be an option.

After every upgrade I do:
sudo -u www-data sed -i 's#\t$alarm = $vCal#\t/**$alarm = $vCal#g' /var/www/nextcloud/apps/dav/lib/CalDAV/BirthdayService.php sudo -u www-data sed -i 's#$vEvent->add($alarm);#$vEvent->add($alarm);*/#g' /var/www/nextcloud/apps/dav/lib/CalDAV/BirthdayService.php

This comments out the five lines generating the alarms (line 283-287, actually in version 17.0.2.1). That's my workaround for this issue.

For anyone else that had the BirthdayService.php file at a different path, here's a modified version I've put in a small bash script:

#!/usr/bin/env bash
birthdayServicePath="/var/www/html/apps/dav/lib/CalDAV/BirthdayService.php"
cp "$birthdayServicePath" .
sudo -u www-data sed -i 's#\t$alarm = $vCal#\t/**$alarm = $vCal#g' "$birthdayServicePath" 
sudo -u www-data sed -i 's#$vEvent->add($alarm);#$vEvent->add($alarm);*/#g' "$birthdayServicePath"

If you want to keep the alarm, but don't ring at 00:00 AM
After every upgrade, in BirthdayService.php Change the line:

$alarm->add($vCal->createProperty('TRIGGER', '-PT0M', ['VALUE' => 'DURATION']));

To ring at 9AM on day of birthday:
$alarm->add($vCal->createProperty('TRIGGER', 'PT9H', ['VALUE' => 'DURATION']));

To ring 1 day before (9AM):
$alarm->add($vCal->createProperty('TRIGGER', '-PT15H', ['VALUE' => 'DURATION']));

2 days before (9AM)
$alarm->add($vCal->createProperty('TRIGGER', '-P1DT15H', ['VALUE' => 'DURATION']));

1 week before (9AM)
$alarm->add($vCal->createProperty('TRIGGER', '-P6DT15H', ['VALUE' => 'DURATION']));

Thanks for that admin hack! But NC / Calendar really should offer such an option itself.

eloo commented

If you want to keep the alarm, but don't ring at 00:00 AM
After every upgrade, in BirthdayService.php Change the line:

$alarm->add($vCal->createProperty('TRIGGER', '-PT0M', ['VALUE' => 'DURATION']));

To ring at 9AM on day of birthday:
$alarm->add($vCal->createProperty('TRIGGER', 'PT9H', ['VALUE' => 'DURATION']));

To ring 1 day before (9AM):
$alarm->add($vCal->createProperty('TRIGGER', '-PT15H', ['VALUE' => 'DURATION']));

2 days before (9AM)
$alarm->add($vCal->createProperty('TRIGGER', '-P1DT15H', ['VALUE' => 'DURATION']));

1 week before (9AM)
$alarm->add($vCal->createProperty('TRIGGER', '-P1WT15H', ['VALUE' => 'DURATION']));

I'm also using this hack but as far i know this only applies to new entries.
Do you if its possible to "adjust" already existing events?

Currently my workaround was to remove the calendars and rebuild them. But this is not very good solution :D

Currently my workaround was to remove the calendars and rebuild them. But this is not very good solution :D

Same problem here: Changes are only made for future calendar entries, but not for already existing ones.

So you delete the whole birthday calendar, but how do you rebuild the new one? I thought, if deleted once, it can not be recreated?

So you delete the whole birthday calendar, but how do you rebuild the new one? I thought, if deleted once, it can not be recreated?

It will be recreated by cron. Admins can use dav:sync-birthday-calendar %user%.

It will be recreated by cron. Admins can use dav:sync-birthday-calendar %user%.

So just deleting the birthday calendar via Nextcloud-Web-GUI in "Calendar"-tab will be enough?

Currently my workaround was to remove the calendars and rebuild them. But this is not very good solution :D

Same problem here: Changes are only made for future calendar entries, but not for already existing ones.

So you delete the whole birthday calendar, but how do you rebuild the new one? I thought, if deleted once, it can not be recreated?

In the web interface, go to settings / admin / groupware and uncheck and check again "Automatically generate a birthday calendar"

eloo commented

@galianet

In the web interface, go to settings / admin / groupware and uncheck and check again "Automatically generate a birthday calendar"

Ah this nice..
So i now just need to have a script which is applying php changes on every start. So when my docker image is updated the changes will be applied again

kosli commented

@eloo For such cases I used to build my own container -> Take a Dockerfile, use the official NC docker as base and just apply the file changes (e.g. via patch).... done.... so you don't need to care about updates on the new versions...

Can you please take the off-topic discussions about Docker to help.nextcloud.com?
Thanks!

Again: Please integrate this in the next update!

If you want to keep the alarm, but don't ring at 00:00 AM
After every upgrade, in BirthdayService.php Change the line:

$alarm->add($vCal->createProperty('TRIGGER', '-PT0M', ['VALUE' => 'DURATION']));

To ring at 9AM on day of birthday:
$alarm->add($vCal->createProperty('TRIGGER', 'PT9H', ['VALUE' => 'DURATION']));

To ring 1 day before (9AM):
$alarm->add($vCal->createProperty('TRIGGER', '-PT15H', ['VALUE' => 'DURATION']));

2 days before (9AM)
$alarm->add($vCal->createProperty('TRIGGER', '-P1DT15H', ['VALUE' => 'DURATION']));

1 week before (9AM)
$alarm->add($vCal->createProperty('TRIGGER', '-P6DT15H', ['VALUE' => 'DURATION']));

Nice. Thanks for that info.

here is what i have done:

#!/bin/bash

#### define vars ####
TARGETFILE=/var/www/nextcloud/apps/dav/lib/CalDAV/BirthdayService.php
### NOTIFYTIME_DEFAULT=-PT0M ###
NOTIFYTIME_OLD=-PT0M
NOTIFYTIME_NEW=PT9H  # at 9AM on day of birthday
SEARCHSTRING="\$alarm->add(\$vCal->createProperty('TRIGGER', '$NOTIFYTIME_OLD', ['VALUE' => 'DURATION']));"
REPLACESTRING="\$alarm->add(\$vCal->createProperty('TRIGGER', '$NOTIFYTIME_NEW', ['VALUE' => 'DURATION']));"


#### do it ####
grep -F -q "$SEARCHSTRING" $TARGETFILE && \
  cp $TARGETFILE $TARGETFILE.backup_$(date --iso-8601=seconds) && \
  python replace_string.py "$SEARCHSTRING" "$REPLACESTRING" $TARGETFILE
exit 0

and a python script to get rid of that escaping in 'sed' that would be needed otherways.

#!/usr/bin/python
import sys

# Replace string in a file (in place)
match=sys.argv[1]
replace=sys.argv[2]
filename=sys.argv[3]

print "Replacing strings in",filename

with open(filename,"r") as f:
  data = f.read().replace(match,replace)

with open(filename,"w") as f:
  f.write(data)

But now I have another problem. It's OT but I should share that at least.

My sync via DAVx5 is now "broken" for birthdays.
Each birthday on my phone calendar is now listet as "notify -9 Minutes before" (Simple Calendar Pro by Tibor Kaputa from F-Droid)
I dont know if there are similar issues with other apps.

But in Nextcloud everything is fine.

Would it be possible to have the 'Contact birthdays' as a calendar owned by each user which is automatically populated by the server? This way it'd be possible to change colors and have other customizations, and, of course, set up reminders as wanted.

b-pfl commented

As a calendar user, I would really appreciate the following behavior (or be able to configure is in such a way):

  • As a user, it is up to me to decided whether or not a birthday calendar is shown when opening the nextcloud web calendar.
  • I want to be able to define if and when I want to be reminded of birthday events and where (e.g. whether notifications should pop up as NC notifications or not).

Thanks you all for the ideas on how to solve the issue that the Birthday Cad wakes me up at midnight to remind me to celebrate my friends.
As I could understand, the main reason is that this Calendar is Read-Only imported/created and it remains being like this.
Can we change that ? In general when you import something, you should simply be the Owner right ?
Because if the only way is to have a script (!!) and to run it each time you upgrade (!!!!!) you're killing directly your solution and I'm pretty sure you lost, loose and will be loosing a lot of potential users. Be sure of that.
Being wake up at midnight it's not fun. Even worst when you sleep with someone else and you have to explain why he/she awake once more time by your device. I'm sure you can understand that in 2020 (almost 2021) this cannot be acceptable from a simple User-Experience point of view.
You/We should find a better solution for that issue, bug whatever you called it.

From "where" I'm talking to : even if I'm not a Developer, I worked for a NASDAQ software company in the DevOps team linked to the 'software environment'. So even if I'm not a pure developer, I worked with them every single day (and I love it !!) in order to fix bug but also to make their work useful for our end-users. So please be sure that my comment is motivated by only one idea : to make most people using your nice and important work ! I'm using this solution in order to forget the GAFA solutions...

PS : sorry for my English, I'm French !

Any news?

Hi, just run into this issue myself. I was trying to take a look at fixing it but am struggling to work out where the calendar is actually being generated? Is it in the contacts app and if so where? Pointers appreciated.

@tsvallender Hello,
Many thanks for being interested.
The part you're looking for is in the following file, I've highlighted where the alarm is being added:

$alarm = $vCal->createComponent('VALARM');
$alarm->add($vCal->createProperty('TRIGGER', '-PT0M', ['VALUE' => 'DURATION']));
$alarm->add($vCal->createProperty('ACTION', 'DISPLAY'));
$alarm->add($vCal->createProperty('DESCRIPTION', $vEvent->{'SUMMARY'}));
$vEvent->add($alarm);

My personal opinion would be for this config to be handled in the Groupware user settings alongside availability settings (new in Nextcloud 23), instead of the calendar settings like said above.

We could use the setting introduced in nextcloud/calendar#3001 (basic setting for all calendars) as a default, but I would prefer birthday calendars having their own setting.

Unrelated:
The default alarm setting over CalDAV was removed for some reason from the draft-daboo-valarm-extensions draft, which became RFC 9074, however some projects seem to use it anyway. I'm tracking this in the wiki if anyone's curious.

@tcitworld Thank you for the help! I'm not a PHP guy but I'm going to set up a dev environment and see how far I can get with this.

Hi all,

I have started working on this issue (related PR: #33251).

The next step is adding the configuration option to the UI.

My personal opinion would be for this config to be handled in the groupware user settings alongside availability settings (new in Nextcloud 23), instead of the calendar settings like said above.

In my opinion, such a setting should be located close to the "Enable birthday calendar" option. So, I would propose one of the following:

  1. Place the "Birthday reminder" select box in the calendar settings right below the "Enable birthday calendar" option.
  2. Provide both settings ("Enable birthday calendar" and "Birthday reminder") in the groupware user settings and link to them from the calendar app settings. Here we could either:
    1. keep the option "Enable birthday calendar" in the calendar settings to provide a quick way of en-/disabling it,
    2. or we could remove it there and only provide the link to the groupware user settings.

I have a slight preference for the option 2.ii. What do you guys think? @tcitworld

Thanks for your effort! I vote not to implement 2i as this leads to different howtos and users might expect it to be different and need to experiment instead of knowing straight away. I' also vote for 2ii, seems very clean. Also allows for (yet undeveloped) other apps to provide birthday calendar functionality. Only keeping it with the calendar app as in 1 seems wrong as it is a server feature. But there definitely must remain a link or at least an explanation that there is such feature and what may be configured where.

Suggestion looks good, thanks!

b-pfl commented

Just as an additional thought: As it turns out, the reminders are now also sent for regular calendar events, which is annoying if you use CalDav synchronization on your devices. So if there is a way to disable reminders, this should ideally be possible for all different types of reminders.
I also tend more towards 2ii.
Thanks for starting your work on this issue!

Hey all,

So I have implemented option 2ii (see #33397 and nextcloud/calendar#4402), hoping to resolve this issue :)

Just as an additional thought: As it turns out, the reminders are now also sent for regular calendar events, which is annoying if you use CalDav synchronization on your devices. So if there is a way to disable reminders, this should ideally be possible for all different types of reminders.

Hmm, I'm not sure, if I understand you correctly. You are probably referring to the feature discussed in nextcloud/calendar#629... But as I see, there is already the option "No reminder", and it's chosen by default... Also, as stated earlier in this thread, reminders for regular events are usually created by the client, so it might be the case, that one of your clients adds these reminders (and you could probably disable them there).

May all changes be made by just patching / without building? If not, I'll currently only be able to test a (test) release version.

No, unfortunately, testing the changes in the calendar app requires you to build the calendar app. However, the only changes in the calendar app was the renaming of the link and the removal of the "Enable birthday calendar" checkbox in the settings panel. All the rest should be testable by checking out the feature branch of the server component (for checking the generated birthday events, you can use the latest version of the calendar app).

@tsvallender Hello, Many thanks for being interested. The part you're looking for is in the following file, I've highlighted where the alarm is being added:

$alarm = $vCal->createComponent('VALARM');
$alarm->add($vCal->createProperty('TRIGGER', '-PT0M', ['VALUE' => 'DURATION']));
$alarm->add($vCal->createProperty('ACTION', 'DISPLAY'));
$alarm->add($vCal->createProperty('DESCRIPTION', $vEvent->{'SUMMARY'}));
$vEvent->add($alarm);

Did i unterstand that correctly that the workaround so far is to:

  1. get rid of that 5 lines containing the $alarm string in the apps/dav/lib/CalDAV/BirthdayService.php
  2. save the BirthdayService.php file
  3. Go To "Calendar App" -> "Settings & Import" -> "Enable birthday calendar" and Uncheck the Box
  4. Check the "Enable birthday calendar" again to let the server newly build the Birthday Events without Alarms
  5. Resync on the other devices/apps which are read-only anyway for the birthday calendar? (therefore there should be no backsyncs or old entries left)

So far i got no errors or strange behavior on the server, caldav sync in outlook and DAVx5 Sync on Android
and all the events now dont have a reminder.
I get that this has to be done every update until the settings are permanently implemented, but anyone noticed any issues so far with a workaround like this?

fblz commented

It is almost one year since the patch was created by @cneukom.
The patch itself was not merged but part of it seems to have made it into the dav app as of NC25.
https://github.com/nextcloud/server/blob/v27.0.0/apps/dav/lib/CalDAV/BirthdayService.php#L455 now queries a user preference instead of being hard coded.
Despite this, I was unable to find a corresponding UI element to configure the birthdayCalendarReminderOffset preference.

Am I overlooking something here?

For the time being, I set the preference via SQL:
insert into oc_preferences (appid, configkey, configvalue, userid) values ('dav','birthdayCalendarReminderOffset','-PT0M','<USERNAME_HERE>');

With (some) possible values like this.

If you want to keep the alarm, but don't ring at 00:00 AM After every upgrade, in BirthdayService.php Change the line:

$alarm->add($vCal->createProperty('TRIGGER', '-PT0M', ['VALUE' => 'DURATION']));

To ring at 9AM on day of birthday: $alarm->add($vCal->createProperty('TRIGGER', 'PT9H', ['VALUE' => 'DURATION']));

To ring 1 day before (9AM): $alarm->add($vCal->createProperty('TRIGGER', '-PT15H', ['VALUE' => 'DURATION']));

2 days before (9AM) $alarm->add($vCal->createProperty('TRIGGER', '-P1DT15H', ['VALUE' => 'DURATION']));

1 week before (9AM) $alarm->add($vCal->createProperty('TRIGGER', '-P6DT15H', ['VALUE' => 'DURATION']));