BREAKING: Replace hour/interval inputs with flexible time lists in Immich Album Watcher

Replace interval-based scheduling with explicit time lists for more flexibility:
- Periodic Summary: Replace interval_hours + start_hour with notification_times
- Scheduled Assets: Replace interval_hours + start_hour with notification_times
- Memory Mode: Replace start_hour with notification_times

Changes:
- Remove `periodic_interval_hours` and `periodic_start_hour` inputs
- Remove `scheduled_assets_interval_hours` and `scheduled_assets_start_hour` inputs
- Replace `memory_mode_start_hour` with `memory_mode_notification_times`
- Add three new time text inputs accepting comma-separated HH:MM format
- Replace hourly time_pattern trigger with three template triggers
- Update trigger logic to match current time against configured times
- Update documentation to reflect new time-based scheduling

Users can now specify any times (e.g., "09:00, 14:30, 21:00") instead of
calculating intervals. Times must use 24-hour format with leading zeros.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-02-09 12:50:23 +03:00
parent 06177cb9f0
commit 6848c3f903
3 changed files with 84 additions and 107 deletions

View File

@@ -156,7 +156,7 @@ Select input_text entities containing Telegram chat IDs. Can be user IDs (positi
## Periodic Summary ## Periodic Summary
Sends a summary notification of tracked albums at regular intervals. Album names and share URLs are automatically read from the Album ID Entity's `album_name` and `share_url` attributes (if available). Sends a summary notification of tracked albums at configured times. Album names and share URLs are automatically read from the Album ID Entity's `album_name` and `share_url` attributes (if available). You can configure multiple notification times (e.g., "12:00, 18:00") using comma-separated 24-hour format with leading zeros.
When Telegram media is enabled, an optional image can be attached to the summary message. By default, the official Immich logo is used. Set the **Summary Image URL** to empty to send text-only notifications. When Telegram media is enabled, an optional image can be attached to the summary message. By default, the official Immich logo is used. Set the **Summary Image URL** to empty to send text-only notifications.
@@ -189,7 +189,7 @@ To target a specific automation, set its Automation ID in config and include it
## Scheduled Assets ## Scheduled Assets
Sends scheduled notifications with existing assets from tracked albums. Uses the `immich_album_watcher.get_assets` service to fetch assets. Sends scheduled notifications with existing assets from tracked albums at configured times. Uses the `immich_album_watcher.get_assets` service to fetch assets. You can configure multiple notification times (e.g., "09:00, 21:00") using comma-separated 24-hour format with leading zeros.
### Album Modes ### Album Modes
@@ -244,14 +244,14 @@ Send scheduled notifications with photos taken on today's date in previous years
| Option | Description | | Option | Description |
|--------|-------------| |--------|-------------|
| `enable_memory_mode` | Enable/disable memory notifications | | `enable_memory_mode` | Enable/disable memory notifications |
| `start_hour` | Hour of day for the daily notification (0-23) | | `notification_times` | Comma-separated times in 24-hour format (e.g., "09:00, 18:00") |
| `album_mode` | per_album, combined, or random | | `album_mode` | per_album, combined, or random |
| `limit` | Maximum number of assets to fetch (1-100) | | `limit` | Maximum number of assets to fetch (1-100) |
| `favorite_only` | Only fetch favorite assets | | `favorite_only` | Only fetch favorite assets |
| `asset_type` | Filter by type (all, photo, video) | | `asset_type` | Filter by type (all, photo, video) |
| `min_rating` | Minimum rating filter (1-5, 0 = no filter) | | `min_rating` | Minimum rating filter (1-5, 0 = no filter) |
Memory notifications are sent once per day at the configured start hour. Memory notifications are sent at the configured times. Times must use 24-hour format with leading zeros (e.g., "09:00" not "9:00").
### Memory Mode Message Template Variables ### Memory Mode Message Template Variables

View File

@@ -489,30 +489,14 @@ blueprint:
selector: selector:
boolean: boolean:
periodic_interval_hours: periodic_notification_times:
name: Summary Interval (Hours) name: Summary Notification Times
description: "How often to send the summary notification (in hours)"
default: 24
selector:
number:
min: 1
max: 168
unit_of_measurement: hours
mode: slider
periodic_start_hour:
name: Summary Start Hour
description: > description: >
Hour of day (0-23) when the first summary should be sent. Comma-separated list of times to send periodic summaries in
Subsequent summaries are sent at this hour plus the interval. 24-hour format with leading zeros (e.g., "12:00, 18:00").
Example: Start hour 12 with 24h interval = daily at 12:00. default: "12:00"
default: 12
selector: selector:
number: text:
min: 0
max: 23
unit_of_measurement: hour
mode: slider
periodic_summary_message: periodic_summary_message:
name: Summary Message Template name: Summary Message Template
@@ -560,29 +544,14 @@ blueprint:
selector: selector:
boolean: boolean:
scheduled_assets_interval_hours: scheduled_assets_notification_times:
name: Interval (Hours) name: Notification Times
description: "How often to send scheduled asset notifications (in hours)"
default: 24
selector:
number:
min: 1
max: 168
unit_of_measurement: hours
mode: slider
scheduled_assets_start_hour:
name: Start Hour
description: > description: >
Hour of day (0-23) when the first notification should be sent. Comma-separated list of times to send scheduled asset notifications
Example: Start hour 9 with 24h interval = daily at 09:00. in 24-hour format with leading zeros (e.g., "09:00, 21:00").
default: 9 default: "09:00"
selector: selector:
number: text:
min: 0
max: 23
unit_of_measurement: hour
mode: slider
scheduled_assets_album_mode: scheduled_assets_album_mode:
name: Album Mode name: Album Mode
@@ -723,18 +692,14 @@ blueprint:
selector: selector:
boolean: boolean:
memory_mode_start_hour: memory_mode_notification_times:
name: Start Hour name: Notification Times
description: > description: >
Hour of day (0-23) when the daily memory notification should be sent. Comma-separated list of times to send memory notifications in
Memory notifications are sent once per day at this hour. 24-hour format with leading zeros (e.g., "09:00, 18:00").
default: 9 default: "09:00"
selector: selector:
number: text:
min: 0
max: 23
unit_of_measurement: hour
mode: slider
memory_mode_album_mode: memory_mode_album_mode:
name: Album Mode name: Album Mode
@@ -844,6 +809,14 @@ blueprint:
mode: queued mode: queued
max: 10 max: 10
# =============================================================================
# TRIGGER VARIABLES (available in trigger templates)
# =============================================================================
trigger_variables:
input_periodic_times: !input periodic_notification_times
input_scheduled_times: !input scheduled_assets_notification_times
input_memory_times: !input memory_mode_notification_times
# ============================================================================= # =============================================================================
# TRIGGERS # TRIGGERS
# ============================================================================= # =============================================================================
@@ -869,12 +842,21 @@ trigger:
event_type: immich_album_watcher_album_deleted event_type: immich_album_watcher_album_deleted
id: "album_deleted" id: "album_deleted"
# Hourly timer trigger for periodic summary and scheduled assets # Time-based triggers for periodic summary, scheduled assets, and memory mode
# Note: Uses template to dynamically set interval, but HA requires static value - platform: template
# so we trigger every hour and check interval in conditions value_template: >
- platform: time_pattern {{ now().strftime('%H:%M') in (input_periodic_times.split(',') | map('trim') | list) }}
hours: "/1" id: "periodic_summary_timer"
id: "hourly_timer"
- platform: template
value_template: >
{{ now().strftime('%H:%M') in (input_scheduled_times.split(',') | map('trim') | list) }}
id: "scheduled_assets_timer"
- platform: template
value_template: >
{{ now().strftime('%H:%M') in (input_memory_times.split(',') | map('trim') | list) }}
id: "memory_mode_timer"
# Manual trigger for testing periodic summary # Manual trigger for testing periodic summary
# Fire this event from Developer Tools > Events to test periodic summary immediately # Fire this event from Developer Tools > Events to test periodic summary immediately
@@ -947,16 +929,12 @@ variables:
# Periodic Summary Settings # Periodic Summary Settings
enable_periodic_summary: !input enable_periodic_summary enable_periodic_summary: !input enable_periodic_summary
periodic_interval_hours: !input periodic_interval_hours
periodic_start_hour: !input periodic_start_hour
periodic_summary_message_template: !input periodic_summary_message periodic_summary_message_template: !input periodic_summary_message
periodic_album_template: !input periodic_album_template periodic_album_template: !input periodic_album_template
periodic_summary_image_url: !input periodic_summary_image_url periodic_summary_image_url: !input periodic_summary_image_url
# Scheduled Assets Settings # Scheduled Assets Settings
enable_scheduled_assets: !input enable_scheduled_assets enable_scheduled_assets: !input enable_scheduled_assets
scheduled_assets_interval_hours: !input scheduled_assets_interval_hours
scheduled_assets_start_hour: !input scheduled_assets_start_hour
scheduled_assets_album_mode: !input scheduled_assets_album_mode scheduled_assets_album_mode: !input scheduled_assets_album_mode
scheduled_assets_limit: !input scheduled_assets_limit scheduled_assets_limit: !input scheduled_assets_limit
scheduled_assets_favorite_only: !input scheduled_assets_favorite_only scheduled_assets_favorite_only: !input scheduled_assets_favorite_only
@@ -970,7 +948,6 @@ variables:
# Memory Mode Settings # Memory Mode Settings
enable_memory_mode: !input enable_memory_mode enable_memory_mode: !input enable_memory_mode
memory_mode_start_hour: !input memory_mode_start_hour
memory_mode_album_mode: !input memory_mode_album_mode memory_mode_album_mode: !input memory_mode_album_mode
memory_mode_limit: !input memory_mode_limit memory_mode_limit: !input memory_mode_limit
memory_mode_favorite_only: !input memory_mode_favorite_only memory_mode_favorite_only: !input memory_mode_favorite_only
@@ -1270,15 +1247,14 @@ variables:
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# Periodic Summary Variables # Periodic Summary Variables
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# Check if periodic summary should run (every N hours starting from start_hour) # Check if periodic summary should run (at configured times)
# Formula: (current_hour - start_hour) % interval == 0
# Example: start_hour=12, interval=24 → sends at 12:00 daily
# Example: start_hour=9, interval=12 → sends at 09:00 and 21:00
# Manual test event (immich_album_watcher_test_periodic_summary) bypasses time check # Manual test event (immich_album_watcher_test_periodic_summary) bypasses time check
# If event data contains automation_id, only matching automations respond # If event data contains automation_id, only matching automations respond
should_send_periodic_summary: > should_send_periodic_summary: >
{% if trigger.id in ['hourly_timer', 'periodic_summary'] and enable_periodic_summary %} {% if enable_periodic_summary %}
{% if trigger.platform == 'event' and trigger.event.event_type == 'immich_album_watcher_test_periodic_summary' %} {% if trigger.id == 'periodic_summary_timer' %}
{{ true }}
{% elif trigger.platform == 'event' and trigger.event.event_type == 'immich_album_watcher_test_periodic_summary' %}
{% set event_automation_id = trigger.event.data.automation_id | default('') %} {% set event_automation_id = trigger.event.data.automation_id | default('') %}
{% if event_automation_id | length > 0 %} {% if event_automation_id | length > 0 %}
{{ automation_id == event_automation_id }} {{ automation_id == event_automation_id }}
@@ -1286,10 +1262,7 @@ variables:
{{ true }} {{ true }}
{% endif %} {% endif %}
{% else %} {% else %}
{% set current_hour = now().hour %} {{ false }}
{% set start = periodic_start_hour | int %}
{% set interval = periodic_interval_hours | int %}
{{ (current_hour - start) % interval == 0 }}
{% endif %} {% endif %}
{% else %} {% else %}
{{ false }} {{ false }}
@@ -1329,22 +1302,23 @@ variables:
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# Scheduled Assets Variables # Scheduled Assets Variables
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# Check if scheduled assets should run (every N hours starting from start_hour) # Check if scheduled assets should run (at configured times)
# Manual test event (immich_album_watcher_test_scheduled_assets) bypasses time check # Manual test event (immich_album_watcher_test_scheduled_assets) bypasses time check
# If event data contains automation_id, only matching automations respond # If event data contains automation_id, only matching automations respond
should_send_scheduled_assets: > should_send_scheduled_assets: >
{% if trigger.id == 'scheduled_assets' and enable_scheduled_assets %} {% if enable_scheduled_assets %}
{% set event_automation_id = trigger.event.data.automation_id | default('') %} {% if trigger.id == 'scheduled_assets_timer' %}
{% if event_automation_id | length > 0 %}
{{ automation_id == event_automation_id }}
{% else %}
{{ true }} {{ true }}
{% elif trigger.platform == 'event' and trigger.event.event_type == 'immich_album_watcher_test_scheduled_assets' %}
{% set event_automation_id = trigger.event.data.automation_id | default('') %}
{% if event_automation_id | length > 0 %}
{{ automation_id == event_automation_id }}
{% else %}
{{ true }}
{% endif %}
{% else %}
{{ false }}
{% endif %} {% endif %}
{% elif trigger.id == 'hourly_timer' and enable_scheduled_assets %}
{% set current_hour = now().hour %}
{% set start = scheduled_assets_start_hour | int %}
{% set interval = scheduled_assets_interval_hours | int %}
{{ (current_hour - start) % interval == 0 }}
{% else %} {% else %}
{{ false }} {{ false }}
{% endif %} {% endif %}
@@ -1360,21 +1334,23 @@ variables:
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# Memory Mode Variables # Memory Mode Variables
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# Check if memory mode should run (every N hours starting from start_hour) # Check if memory mode should run (at configured times)
# Manual test event (immich_album_watcher_test_memory_mode) bypasses time check # Manual test event (immich_album_watcher_test_memory_mode) bypasses time check
# If event data contains automation_id, only matching automations respond # If event data contains automation_id, only matching automations respond
should_send_memory_mode: > should_send_memory_mode: >
{% if trigger.id == 'memory_mode' and enable_memory_mode %} {% if enable_memory_mode %}
{% set event_automation_id = trigger.event.data.automation_id | default('') %} {% if trigger.id == 'memory_mode_timer' %}
{% if event_automation_id | length > 0 %}
{{ automation_id == event_automation_id }}
{% else %}
{{ true }} {{ true }}
{% elif trigger.platform == 'event' and trigger.event.event_type == 'immich_album_watcher_test_memory_mode' %}
{% set event_automation_id = trigger.event.data.automation_id | default('') %}
{% if event_automation_id | length > 0 %}
{{ automation_id == event_automation_id }}
{% else %}
{{ true }}
{% endif %}
{% else %}
{{ false }}
{% endif %} {% endif %}
{% elif trigger.id == 'hourly_timer' and enable_memory_mode %}
{% set current_hour = now().hour %}
{% set start = memory_mode_start_hour | int %}
{{ current_hour == start }}
{% else %} {% else %}
{{ false }} {{ false }}
{% endif %} {% endif %}
@@ -1392,17 +1368,18 @@ variables:
# ============================================================================= # =============================================================================
condition: condition:
# Allow through if: # Allow through if:
# 1. Hourly timer or periodic summary trigger and should send periodic summary, scheduled assets, or memory mode # 1. Time-based triggers (periodic_summary_timer, scheduled_assets_timer, memory_mode_timer)
# 2. Scheduled assets trigger (manual test) # 2. Manual test event triggers (periodic_summary, scheduled_assets, memory_mode)
# 3. Memory mode trigger (manual test) # 3. Event trigger and passes all event-based checks
# 4. Event trigger and passes all event-based checks
- condition: template - condition: template
value_template: > value_template: >
{% if trigger.id == 'scheduled_assets' %} {% if trigger.id == 'periodic_summary_timer' %}
{{ should_send_periodic_summary }}
{% elif trigger.id == 'scheduled_assets_timer' %}
{{ should_send_scheduled_assets }} {{ should_send_scheduled_assets }}
{% elif trigger.id == 'memory_mode' %} {% elif trigger.id == 'memory_mode_timer' %}
{{ should_send_memory_mode }} {{ should_send_memory_mode }}
{% elif trigger.id in ['hourly_timer', 'periodic_summary'] %} {% elif trigger.platform == 'event' and trigger.event.event_type in ['immich_album_watcher_test_periodic_summary', 'immich_album_watcher_test_scheduled_assets', 'immich_album_watcher_test_memory_mode'] %}
{{ should_send_periodic_summary or should_send_scheduled_assets or should_send_memory_mode }} {{ should_send_periodic_summary or should_send_scheduled_assets or should_send_memory_mode }}
{% else %} {% else %}
{{ is_hub_tracked and is_album_tracked and should_notify }} {{ is_hub_tracked and is_album_tracked and should_notify }}

View File

@@ -1,3 +1,3 @@
{ {
"version": "1.35.0" "version": "2.0.0"
} }