📆 Calendar Notifications & Actions

@Sander1970

Welcome to the community.

{{ trigger.calendar_event.summary }} and your text here

or

your text here {{ trigger.calendar_event.summary }} 

or

your text here {{ trigger.calendar_event.summary }} and some more

Blacky :grinning:

New Update 2.3

Transform Your Calendar: Turn Events Into Notifications and Actions! :calendar: :bell: :gear:

:toolbox: Maintenance

  • Finally Fixed: Removed unnecessary warning messages when some calendar events don’t have a description (e.g., Google Calendar). Automation behavior remains unchanged.

We updated the default title and message in the start & end inputs to

{{ trigger.calendar_event.get('summary', '') }}

{{ trigger.calendar_event.get('description', '') }}

Thanks to @stephanschleichstr13 for doing the testing :+1:


If you like this blueprint? Consider hitting the :heart: button in the top post :+1:

If you like my blueprints, and would like to show your support or just say thank you? Click Here :smiling_face_with_three_hearts:

Enjoy

Blacky :grinning:

1 Like

Feature request / patch: “Day Exclude Keyword(s)” (daily blocklist) for Calendar Notifications & Actions

I’m using the Calendar Notifications & Actions blueprint and needed a way to combine the existing keyword triggering with a daily blocklist.

Use case (real example):

  • Trigger actions if the calendar event contains shift keywords (e.g. Early Shift, Late Shift), but only if there is no all-day absence event on the same date (e.g. Vacation, Sick).
  • In other words: “Include keyword(s)” AND “exclude if any event that day contains X”.

What this patch adds:

  • New optional input: Calendar Trigger - Day Exclude Keyword(s) (comma-separated, like the existing keyword list).
  • On every trigger (start/end), the automation queries the selected calendar for all events between 00:00 and 24:00 of the trigger date using calendar.get_events.
  • If any event on that day contains any of the day-exclude keywords (summary + description), the automation stops immediately.
  • The day blocklist is intended to apply always, regardless of whether include/exclude keyword filtering is enabled.

Motivation:
This pattern is very common in work calendars (shifts + all-day vacation/absence). It also enables more advanced automations later (e.g., determining when an EV must be fully charged based on tomorrow’s shift, but skipping charging logic on vacation days).

Note: This patch/diff was AI-generated (with manual testing/iteration in Home Assistant) and may need minor style adjustments to match the upstream blueprint conventions.

diff --git a/calendar-notifications-and-actions.yaml b/calendar-notifications-and-actions_modified.yaml
--- a/calendar-notifications-and-actions.yaml
+++ b/calendar-notifications-and-actions_modified.yaml
@@ -146,15 +146,33 @@
   calendar_trigger:
     name: Calendar Trigger - Keyword(s)
     description: >
       If you selected **Include Keyword** or **Exclude Keyword** above then enter a single keyword, or a comma-separated list of keywords, to trigger this automation.
@@
     default: []
     selector:
       text:
         multiple: false
         multiline: false
+  day_exclude_trigger:
+    name: Calendar Trigger - Day Exclude Keyword(s)
+    description: 'Optional: Comma-separated list of keywords that, if found in ANY event on the same day,
+      will block this automation from running. The keyword is checked in both the event summary and event
+      description.
+      '
+    default: []
+    selector:
+      text:
   start_calendar_offset:
     name: Calendar Start - Offset
     description: >
       You can specify an offset from the start of the calendar event for when the trigger should be activated.
       To trigger the automation before the start of the event, use a negative sign "-" followed by the time value.
@@ -812,6 +830,7 @@
 variables:
   calendar: !input calendar
+  day_exclude_trigger: !input day_exclude_trigger
   include_calendar_trigger: !input include_calendar_trigger
   calendar_trigger: !input calendar_trigger
   start_calendar_offset: !input start_calendar_offset
   end_calendar_offset: !input end_calendar_offset
   include_start_notify: !input include_start_notify
@@ -935,8 +954,43 @@
   - condition: and
     conditions: !input global_conditions
 action:
+- variables:
+    _trigger_start_raw: "{{ trigger.calendar_event.start }}"
+    _day_start: "{{ as_datetime(_trigger_start_raw).strftime('%Y-%m-%d 00:00:00') }}"
+    _day_end: "{{ (as_datetime(_trigger_start_raw) + timedelta(days=1)).strftime('%Y-%m-%d 00:00:00') }}"
+
+- choose:
+    - alias: "Day exclude keywords present -> stop"
+      conditions:
+        - condition: template
+          value_template: "{{ (day_exclude_trigger or '') | string | trim != '' }}"
+      sequence:
+        - action: calendar.get_events
+          target:
+            entity_id: !input calendar
+          data:
+            start_date_time: "{{ _day_start }}"
+            end_date_time: "{{ _day_end }}"
+          response_variable: _day_agenda
+
+        - variables:
+            _exclude_keywords: >
+              {% set s = (day_exclude_trigger or '') | string %}
+              {{ s.split(',') | map('trim') | reject('equalto','') | list }}
+            _day_events: "{{ _day_agenda[calendar]['events'] if _day_agenda is mapping and calendar in _day_agenda else [] }}"
+            _haystack: >-
+              {% set ns = namespace(text='') %}
+              {% for ev in _day_events %}
+                {% set ns.text = ns.text ~ (ev.get('summary','') ~ ev.get('description','')) %}
+              {% endfor %}
+              {{ ns.text }}
+            _blocked: "{{ _exclude_keywords | select('in', _haystack) | list | count > 0 }}"
+
+        - choose:
+            - conditions:
+                - condition: template
+                  value_template: "{{ _blocked }}"
+              sequence:
+                - stop: "Blocked by day exclude keyword(s) found in calendar events for this day."
+
 - choose:
   - alias: "Start trigger"
     conditions:
     - condition: trigger
       id: 't0'
     sequence:

Thank you for your consideration

@Tennis

You could probably do this just using the Global condition.

Blacky :grinning:

i tried this with another LLM a few months ago and it did not work. this aproach works fine

I just wanted to thank you. This is what I was looking for. I am using this BP to warn me in advance someone’s birthday is coming. Just wanted to ask - is it possible to trigger the notificatiion when ALL keywords are found? For example - when calendar even contains “Kate” and “birthday” - set the trigger for notification “Kate’s birthday is coming!”. I have more people’s birthday in calendar, but only few of them I want to be notified of.

@petruspce-ctrl

Your welcome, glad you like it.

You will then need to set the keyword you would like to use for the ones you would like to be notified. Maybe you add something like this @birthdaynotification

Blacky :grinning:

1 Like