16 Commits

Author SHA1 Message Date
e6ff0a423a Phase 10: Telegram bot commands + Phase 11: Snackbar notifications
All checks were successful
Validate / Hassfest (push) Successful in 3s
Phase 10 — Telegram Bot Commands:
- Add commands_config JSON field to TelegramBot model (enabled cmds,
  default count, response mode, rate limits, locale)
- Create command handler with 14 commands: /status, /albums, /events,
  /summary, /latest, /memory, /random, /search, /find, /person,
  /place, /favorites, /people, /help
- Add search_smart, search_metadata, search_by_person, get_random,
  download_asset, get_asset_thumbnail to ImmichClient
- Auto-register commands with Telegram setMyCommands API (EN+RU)
- Rate limiting per chat per command category
- Media mode: download thumbnails and send as photos to Telegram
- Webhook handler routes /commands before falling through to AI chat
- Frontend: expandable Commands section per bot with checkboxes,
  count/mode/locale settings, rate limit inputs, sync button

Phase 11 — Snackbar Notifications:
- Create snackbar store (snackbar.svelte.ts) with $state rune
- Create Snackbar component with fly/fade transitions, typed colors
- Mount globally in +layout.svelte
- Replace all alert() calls with typed snackbar notifications
- Add success snacks to all CRUD operations across all pages
- 4 types: success (3s), error (5s), info (3s), warning (4s)
- Max 3 visible, auto-dismiss, manual dismiss via X button

Both: Add ~30 i18n keys (EN+RU) for commands UI and snack messages.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 21:39:05 +03:00
b87b5b2c87 Fix template variable docs to match actual notifier output
All checks were successful
Validate / Hassfest (push) Successful in 3s
Audit and fix all template variable references:
- template_vars.py: Add missing fields (album_id, old_shared,
  new_shared, latitude, longitude, owner_id, people per asset)
- _SAMPLE_CONTEXT: Use proper structured data matching
  build_asset_detail() output (id, owner_id, latitude, longitude,
  people per asset, playback_url for videos)
- i18n: Fix all variable descriptions for accuracy, add missing
  fields, mark scheduler-dependent slots as "not yet implemented"
- Variables modal: Add album_fields section for periodic_summary
- Shared _ASSET_FIELDS and _ALBUM_FIELDS dicts in template_vars.py
  to keep scheduled/memory slots DRY

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 20:58:21 +03:00
a04d5618d0 Fix icon picker horizontal scroll + finalize Phase 10 plan
Some checks failed
Validate / Hassfest (push) Has been cancelled
IconPicker: replace fixed w-8 h-8 buttons with aspect-square +
overflow-x:hidden to eliminate horizontal scrollbar.

Phase 10 plan updates:
- Add /ocr command (text visible in photos)
- Add /find (text search) separate from /search (CLIP semantic)
- All browsing commands accept [N] count limit (default configurable)
- Response mode configurable per bot (media/text) with --text override
- Rate limiting configurable per command category per chat
- Full EN/RU localized command descriptions (15 commands)
- Descriptions editable per bot in UI
- setMyCommands with language_code for both locales

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 18:19:31 +03:00
fa829da8b7 Phase 10: scope to tracked albums only, add /search (CLIP) + /find (text)
Some checks failed
Validate / Hassfest (push) Has been cancelled
- IMPORTANT constraint: all asset commands only search within
  tracked albums, never expose untracked content
- /search uses Immich CLIP semantic search (natural language)
- /find uses text search (filename, description)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 18:09:08 +03:00
a85c557a20 Update Phase 10: remove /trackers, /targets; add /person, /place commands
Some checks failed
Validate / Hassfest (push) Has been cancelled
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 18:08:31 +03:00
69299c055f Add Phase 10 plan: Telegram bot commands
Some checks failed
Validate / Hassfest (push) Has been cancelled
15 commands across 4 categories:
- Informational: /status, /albums, /events
- On-demand: /summary, /latest, /memory, /random
- Asset browsing: /search, /favorites, /people
- Management: /trackers, /targets, /help

Auto-registers commands with Telegram setMyCommands API when
config changes. Per-bot command enable/disable in UI.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 18:05:12 +03:00
0200b9929f Phase 8: Server health, album filter, Jinja2 engine, password change
Some checks failed
Validate / Hassfest (push) Has been cancelled
5 features implemented:

1. Server health indicator: green/red/yellow dot on each server card.
   Pings Immich in background on page load. New GET /api/servers/{id}/ping.

2. Album selector filter: search input above album list in tracker form.
   Filters by name as you type (case-insensitive). Shows total count.

3. Album last update time: each album in the selector shows its
   updatedAt date. Backend now returns updatedAt from Immich API.

4. Full Jinja2 template engine in notifier:
   - build_full_context() assembles all ~40 variables from blueprint
   - Common date/location detection across assets
   - Per-asset date/location when they differ
   - Favorite indicator, people formatting, asset list with truncation
   - Video warning for Telegram
   - All template slots from TemplateConfig used contextually

5. Password change: PUT /api/auth/password endpoint (validates current
   password, min 6 chars). UI in sidebar footer with inline form.

Also: Phase 9 plan (Telegram bot management) added.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 17:27:00 +03:00
431069fbdb Add Phase 8 plan: UI polish, template engine, password change
Some checks failed
Validate / Hassfest (push) Has been cancelled
5 tasks:
1. Server health indicator on cards
2. Album selector filter-by-name
3. Album last update time display
4. Review/improve template engine (Jinja2 with full variable context)
5. Change user password (self + admin reset)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 17:16:56 +03:00
42063b7bf6 Mark Phase 7 complete in primary plan
Some checks failed
Validate / Hassfest (push) Has been cancelled
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 15:48:30 +03:00
1ad9b8af1d Add Phase 7 plan: Production UI with i18n, themes, OAuth, blueprint parity
Some checks failed
Validate / Hassfest (push) Has been cancelled
Phase 7 covers:
- i18n (RU/EN), dark/light themes, OAuth via Immich
- 4 notification modes matching HAOS blueprint
- Enhanced tracker config (filtering, sorting, telegram media)
- Full template variable system (40+ vars, per-event templates)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 15:31:02 +03:00
88ffd5d077 Add Claude AI Telegram bot enhancement (Phase 6)
Some checks failed
Validate / Hassfest (push) Has been cancelled
Integrate Claude AI into the notification system for intelligent
conversational interactions and AI-powered captions.

New modules:
- ai/service.py: Claude API client with conversation history,
  caption generation, and album activity summarization
- ai/telegram_webhook.py: Telegram webhook handler for incoming
  bot messages, routes to AI service for responses

Features:
- Conversational bot: users chat with the bot about albums
- AI captions: intelligent notification messages based on album
  context (people, locations, dates) - enabled per target via
  "ai_captions" config flag
- Album summaries: "what's new?" triggers AI-generated overview
- /start command with welcome message
- Webhook register/unregister endpoints

Architecture:
- Per-chat conversation history (in-memory, capped at 20 messages)
- Graceful degradation: AI features completely disabled without
  IMMICH_WATCHER_ANTHROPIC_API_KEY env var (zero impact)
- AI caption failure falls back to Jinja2 template rendering
- Health endpoint reports ai_enabled status

Config: IMMICH_WATCHER_ANTHROPIC_API_KEY, IMMICH_WATCHER_AI_MODEL,
IMMICH_WATCHER_AI_MAX_TOKENS

Server now has 45 API routes (was 42 after Phase 5).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 14:38:51 +03:00
ab1c7ac0db Add HAOS-Server sync for optional centralized management (Phase 5)
Some checks failed
Validate / Hassfest (push) Has been cancelled
Enable the HAOS integration to optionally connect to the standalone
Immich Watcher server for config sync and event reporting.

Server-side:
- New /api/sync/* endpoints: GET trackers, POST template render,
  POST event report
- API key auth via X-API-Key header (accepts JWT access tokens)

Integration-side:
- New sync.py: ServerSyncClient with graceful error handling
  (all methods return defaults on connection failure)
- Options flow: optional server_url and server_api_key fields
  with connection validation
- Coordinator: fire-and-forget event reporting to server when
  album changes are detected
- Translations: en.json and ru.json updated with new fields

The connection is fully additive -- the integration works identically
without a server URL configured. Server failures never break HA.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 14:10:29 +03:00
87ce1bc5ec Add SvelteKit frontend with Tailwind CSS (Phase 4)
Some checks failed
Validate / Hassfest (push) Has been cancelled
Build a modern, calm web UI using SvelteKit 5 + Tailwind CSS v4.

Pages:
- Setup wizard (first-run admin account creation)
- Login with JWT token management and auto-refresh
- Dashboard with stats cards and recent events timeline
- Servers: add/delete Immich server connections with validation
- Trackers: create album trackers with album picker, event type
  selection, target assignment, and scan interval config
- Templates: Jinja2 message template editor with live preview
- Targets: Telegram and webhook notification targets with test
- Users: admin-only user management (create/delete)

Architecture:
- Reactive auth state with Svelte 5 runes
- API client with JWT auth, auto-refresh on 401
- Static adapter builds to 153KB for embedding in FastAPI
- Vite proxy config for dev server -> backend API
- Sidebar layout with navigation and user info

Also adds Rule 2 to primary plan: perform detailed code review
after completing each phase.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 13:46:55 +03:00
58b2281dc6 Add standalone FastAPI server backend (Phase 3)
Some checks failed
Validate / Hassfest (push) Has been cancelled
Build a complete standalone web server for Immich album change
notifications, independent of Home Assistant. Uses the shared
core library from Phase 1.

Server features:
- FastAPI with async SQLite (SQLModel + aiosqlite)
- Multi-user auth with JWT (admin/user roles, setup wizard)
- CRUD APIs: Immich servers, album trackers, message templates,
  notification targets (Telegram + webhook), user management
- APScheduler background polling per tracker
- Jinja2 template rendering with live preview
- Album browser proxied from Immich API
- Event logging and dashboard status endpoint
- Docker deployment (single container, SQLite in volume)

39 API routes, 14 integration tests passing.

Also adds Phase 6 (Claude AI Telegram bot enhancement) to the
primary plan as an optional future phase.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 12:56:22 +03:00
b107cfe67f Refactor HAOS integration to use shared core library (Phase 2)
Some checks failed
Validate / Hassfest (push) Has been cancelled
Wire the integration to delegate all HA-independent logic to
immich-watcher-core, eliminating ~2300 lines of duplicated code.

Changes:
- const.py: Import shared constants from core, keep HA-specific ones
- storage.py: Create HAStorageBackend adapter wrapping HA's Store,
  use core TelegramFileCache and NotificationQueue via adapter
- coordinator.py: Delegate to core ImmichClient for API calls,
  detect_album_changes() for change detection, and asset_utils
  for filtering/sorting/URL building. Keep HA-specific event firing.
- sensor.py: Replace ~1300 lines of Telegram code with 15-line
  delegation to core TelegramClient. Keep entity classes unchanged.
- __init__.py: Use factory functions for creating core instances
  with HA storage backends
- manifest.json: Add immich-watcher-core dependency

Integration line count: 3600 -> 1295 lines (-64%)
Zero behavior changes for end users.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 12:47:18 +03:00
d0783d0b6a Add shared core library and architecture plans (Phase 1)
Some checks failed
Validate / Hassfest (push) Has been cancelled
Extract HA-independent logic from the integration into packages/core/
as a standalone Python library (immich-watcher-core). This is the first
phase of restructuring the project to support a standalone web app
alongside the existing HAOS integration.

Core library modules:
- models: SharedLinkInfo, AssetInfo, AlbumData, AlbumChange dataclasses
- immich_client: Async Immich API client (aiohttp, session-injected)
- change_detector: Pure function for album change detection
- asset_utils: Filtering, sorting, URL building utilities
- telegram/client: Full Telegram Bot API (text, photo, video, media groups)
- telegram/cache: File ID cache with pluggable storage backend
- telegram/media: Media size checks, URL extraction, group splitting
- notifications/queue: Persistent notification queue
- storage: StorageBackend protocol + JSON file implementation

All modules have zero Home Assistant imports. 50 unit tests passing.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 12:40:08 +03:00