alexei.dolgolyov
307871cae5
feat: Google Photos provider backend + API hardening
...
- Add Google Photos provider: client, models, change detector, capabilities
- Add notification templates (en/ru) for all GP event slots
- Add command templates (en/ru) for GP bot commands
- Register GP in slot/command loaders, capabilities, and seeds
- Harden provider API: validate OAuth credentials on create/update
- Add internal URL rewriting for asset fetches (LAN optimization)
- Fix template renderer to handle missing variables gracefully
- Improve webhook command routing for multi-provider support
- Add provider health check endpoint and watcher improvements
2026-03-25 22:07:03 +03:00
alexei.dolgolyov
37388c430c
feat: locale-aware notification templates + UX improvements
...
- Add locale support to notification templates (matching command template
pattern): TemplateSlot now has locale field with (config_id, slot_name,
locale) uniqueness, nested API format {slot: {locale: template}}
- Migration merges separate EN/RU system configs into unified per-provider
configs; seeds create one config per provider with multi-locale slots
- Locale-aware dispatch with EN fallback in NotificationDispatcher
- Frontend locale tabs (EN/RU) on template config editor
- Fix tracking config cards not showing default provider icons
- Global provider filter, search palette, and various UX polish
2026-03-23 19:08:48 +03:00
alexei.dolgolyov
e0bae394ee
feat: comprehensive code review fixes — security, performance, quality
...
Backend security:
- Reject Gitea webhooks when webhook_secret is empty (was silently skipping)
- Add slowapi rate limiting on login (5/min) and setup (3/min) endpoints
- Add CORS middleware with configurable origins
- Mask telegram_webhook_secret in settings API response
- Protect system-owned command template configs from regular user modification
- Increase minimum password length to 8 characters
Backend performance:
- Batch queries in _resolve_command_context (3 queries instead of 3N)
- Concurrent album fetching with asyncio.gather in immich commands
- Singleton Jinja2 SandboxedEnvironment (reuse instead of per-render creation)
- TTLCache for rate limits (bounded memory, auto-eviction)
- Optional aiohttp session reuse in send_reply/send_media_group
Backend code quality:
- Extract dispatch_helpers.py (shared link_data loading + event filtering)
- Extract database/seeds.py from main.py (490 lines → dedicated module)
- Split immich_handler.py (415 lines) into commands/immich/ subpackage
- Replace bare except blocks with logged warnings
- Add per-provider config validation (Pydantic models)
- Truncate command input to 512 chars
- Expose usage_* and desc_* slots in capabilities and variables API
Frontend security:
- CSS.escape() for user-controlled querySelector in highlight.ts
- Client-side password min 8 chars validation on setup and password change
Frontend code quality:
- Replace any types with proper interfaces across top files
- Decompose targets/+page.svelte into TargetForm + ReceiverSection
- Fix $derived.by usage, $state mutation patterns
- Add console.warn to empty catch blocks
Frontend UX:
- Auth redirect via goto() with "Redirecting..." state
- Platform-aware Ctrl/Cmd K keyboard hint
- Remove stat-card hover transform
Frontend accessibility:
- Modal: role=dialog, aria-modal, focus trap, restore focus
- EntitySelect/IconGridSelect: listbox/option roles, aria-selected/disabled
2026-03-23 01:59:51 +03:00
alexei.dolgolyov
751097b347
feat: comprehensive code review fixes + receivers-only architecture
...
Security:
- Refuse startup with default secret_key in production (was just logging)
- Settings endpoint now requires admin role
- Password validation on initial setup
- DOM-based HTML sanitizer replaces regex in template previews
- Add *.log to .gitignore
Performance & reliability:
- Token refresh deduplication prevents race condition on concurrent 401s
- Theme media query listener registered once (no leak)
- IconPicker uses $derived instead of function call per render
- Snackbar uses single-batch state update instead of while loop
- Replace 11 inline hover handlers with CSS :hover in layout
Architecture - receivers-only:
- Delivery endpoints (chat_id, email, url, room_id, topic) now stored
exclusively in TargetReceiver rows, never in target.config
- Migration extracts existing delivery fields to receiver rows
- Notifier and dispatcher remove all config fallbacks
- Frontend targets page shows receivers list per target with
add/remove/toggle/test per receiver
- Single-receiver test endpoint: POST /targets/{id}/receivers/{id}/test
Code quality:
- Extract AuthLayout.svelte from login/setup (150 lines CSS dedup)
- Split telegram-bots page (754→51 lines + 3 tab components)
- Split notification-trackers page (547→432 lines + 4 components)
- Deduplicate _send_reply into shared handler.send_reply()
- Add locale column to template models, replace name-based detection
- Fix delete_notification_tracker dead protection check
- Fix check_telegram_bot query (filter by type, remove bogus OR)
- Add graceful scheduler shutdown in lifespan
- Consistent /bots?tab=telegram URLs across all nav links
i18n:
- Error page, chat actions, target types, provider types internationalized
- All new receiver UI strings in EN + RU
2026-03-22 02:19:31 +03:00
alexei.dolgolyov
b525e3e7f4
refactor: rename /telegram-bots route to /bots
...
Frontend route renamed from /telegram-bots to /bots. All nav links,
CrossLinks, SearchPalette hrefs updated. API endpoints remain as
/api/telegram-bots, /api/email-bots, /api/matrix-bots (backend unchanged).
2026-03-22 01:31:30 +03:00
alexei.dolgolyov
86115f5c75
fix: search palette triggers highlight, restore CSS keyframe blink
...
- SearchPalette now calls requestHighlight(id) before goto()
- Restore smooth CSS @keyframes cardHighlight (0%→none, 25%→glow,
75%→glow, 100%→none) instead of JS interval pulse
- Inline style.animation overrides class-based stagger animation;
cleanup sets animation:'none' (inline beats class, no stagger replay)
2026-03-22 00:13:53 +03:00
alexei.dolgolyov
637a4671cf
feat: add search button to sidebar with Ctrl+K shortcut hint
...
Compact search bar button between sidebar header and nav. Shows
magnifying glass icon + placeholder text + ⌘K kbd hint when expanded,
just the icon when collapsed. Clicking opens the search palette.
2026-03-22 00:03:02 +03:00
alexei.dolgolyov
06b24638cb
feat: IconGridSelect, CrossLink, SearchPalette components + entity crosslinks
...
New components:
- IconGridSelect: Visual grid selector replacing <select> dropdowns,
with icon + label cells, fixed-position popup, smart placement
- CrossLink: Inline clickable badge for cross-entity navigation,
hover highlights primary, used on entity cards
- SearchPalette: Ctrl+K global command palette, searches all entity
types via cached data, grouped results, keyboard navigation
Integration:
- Targets: type selector uses IconGridSelect (4-column grid with icons)
- Targets: bot crosslink on telegram/email/matrix target cards
- Command Trackers: provider and config badges → CrossLinks
- Command Trackers: listener bot name → CrossLink
- Command Configs: template config shown as CrossLink on card
- Notification Trackers: provider CrossLink added to card
- Layout: SearchPalette mounted globally
Infrastructure:
- Added CommandConfig, CommandTemplateConfig, CommandTracker types
- Added notificationTrackersCache, commandTrackersCache to caches
- Added allCaches map and fetchAllCaches() for search palette
- Added searchPalette i18n keys (EN/RU)
2026-03-21 23:44:12 +03:00