alexei.dolgolyov 309dec2b44 feat(immich): wire cron-fired scheduled/periodic/memory dispatch
The scheduled_enabled / scheduled_times (and the periodic / memory
counterparts) on TrackingConfig had been wired into the model, the
API, and the test-dispatch path — but no production scheduler ever
read them, so users saw the slot in the UI and only ever got fires
through "Test". This adds the missing cron jobs and the dispatch
fan-out, both keyed off the app-level IANA timezone.

* services/scheduled_dispatch.py — production fan-out reusing the
  test-path event builders, picking the slot template per kind, and
  writing an EventLog row per fire so the dashboard reflects it.
* services/scheduler.py — _load_immich_dispatch_jobs builds one
  CronTrigger per (tracker, kind, HH:MM) from the tracker's default
  TrackingConfig; reschedule_immich_dispatch_jobs rebuilds them all
  on any relevant CRUD or timezone change.
* tracker / link / tracking-config CRUD endpoints now invalidate.

Also: skip dispatch when scheduled/memory yield zero matching assets
(prevents header-only "On this day:" spam), and update the EN/RU
default scheduled_assets templates to surface that the delivery is
a scheduled random selection.
2026-04-24 12:49:47 +03:00
2026-04-23 20:18:34 +03:00
2026-04-23 21:12:17 +03:00

Notify Bridge

A generic bridge between service providers and notification targets.

Notify Bridge monitors services (like Immich photo servers) for changes and dispatches notifications to configurable targets (Telegram, webhooks) using customizable templates.

Architecture

  • Service Providers — Connectors to external services (Immich, more coming)
  • Trackers — Monitor specific collections within a provider for changes
  • Tracking Configs — Define what events to watch for and scheduling rules
  • Notification Targets — Where to send notifications (Telegram chats, webhook URLs)
  • Template Configs — Jinja2 templates that format notifications per provider type

Project Structure

packages/
  core/       — Shared library: providers, models, notifications, templates
  server/     — FastAPI REST server with SQLite database
frontend/     — SvelteKit dashboard (Svelte 5, Tailwind CSS v4)

Quick Docker Deploy

docker run -d \
  --name notify-bridge \
  --restart unless-stopped \
  -p 8420:8420 \
  -v notify-bridge-data:/data \
  -e NOTIFY_BRIDGE_SECRET_KEY=$(openssl rand -hex 32) \
  git.dolgolyov-family.by/alexei.dolgolyov/notify-bridge:latest

Then open http://localhost:8420 in your browser.

Environment Variables

Variable Required Default Description
NOTIFY_BRIDGE_SECRET_KEY Yes Secret key for JWT tokens (min 32 chars)
NOTIFY_BRIDGE_PORT No 8420 Server listen port
NOTIFY_BRIDGE_CORS_ALLOWED_ORIGINS No * Comma-separated allowed CORS origins
NOTIFY_BRIDGE_DEBUG No false Enable debug logging

Docker Compose

services:
  notify-bridge:
    image: git.dolgolyov-family.by/alexei.dolgolyov/notify-bridge:latest
    container_name: notify-bridge
    restart: unless-stopped
    ports:
      - "8420:8420"
    volumes:
      - notify-bridge-data:/data
    environment:
      - NOTIFY_BRIDGE_SECRET_KEY=your-secret-key-min-32-characters

volumes:
  notify-bridge-data:

Quick Start (Development)

# Backend
cd packages/server
pip install -e .
NOTIFY_BRIDGE_DATA_DIR=./test-data NOTIFY_BRIDGE_SECRET_KEY=your-secret-key-min-32chars \
  python -m uvicorn notify_bridge_server.main:app --host 0.0.0.0 --port 8420

# Frontend
cd frontend
npm install
npm run dev

Supported Providers

  • Immich — Photo/video server with album change detection
S
Description
Bridge service events (Immich, …) to notification targets (Telegram, webhooks) via customizable Jinja2 templates and commands.
Readme 9.9 MiB
2026-06-05 21:04:57 +03:00
Languages
Python 59.9%
Svelte 26.1%
HTML 7.6%
TypeScript 3.7%
Jinja 2%
Other 0.6%