Phase 10: Telegram bot commands + Phase 11: Snackbar notifications
All checks were successful
Validate / Hassfest (push) Successful in 3s
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>
This commit is contained in:
@@ -9,6 +9,7 @@ import aiohttp
|
||||
|
||||
from immich_watcher_core.telegram.media import TELEGRAM_API_BASE_URL
|
||||
|
||||
from ..ai.commands import register_commands_with_telegram
|
||||
from ..auth.dependencies import get_current_user
|
||||
from ..database.engine import get_session
|
||||
from ..database.models import TelegramBot, User
|
||||
@@ -23,6 +24,7 @@ class BotCreate(BaseModel):
|
||||
|
||||
class BotUpdate(BaseModel):
|
||||
name: str | None = None
|
||||
commands_config: dict | None = None
|
||||
|
||||
|
||||
@router.get("")
|
||||
@@ -69,10 +71,12 @@ async def update_bot(
|
||||
user: User = Depends(get_current_user),
|
||||
session: AsyncSession = Depends(get_session),
|
||||
):
|
||||
"""Update a bot's display name."""
|
||||
"""Update a bot's display name and/or commands config."""
|
||||
bot = await _get_user_bot(session, bot_id, user.id)
|
||||
if body.name is not None:
|
||||
bot.name = body.name
|
||||
if body.commands_config is not None:
|
||||
bot.commands_config = body.commands_config
|
||||
session.add(bot)
|
||||
await session.commit()
|
||||
await session.refresh(bot)
|
||||
@@ -121,6 +125,20 @@ async def list_bot_chats(
|
||||
return chats
|
||||
|
||||
|
||||
@router.post("/{bot_id}/sync-commands")
|
||||
async def sync_commands(
|
||||
bot_id: int,
|
||||
user: User = Depends(get_current_user),
|
||||
session: AsyncSession = Depends(get_session),
|
||||
):
|
||||
"""Register bot commands with Telegram BotFather API."""
|
||||
bot = await _get_user_bot(session, bot_id, user.id)
|
||||
success = await register_commands_with_telegram(bot)
|
||||
if not success:
|
||||
raise HTTPException(status_code=500, detail="Failed to register commands with Telegram")
|
||||
return {"success": True}
|
||||
|
||||
|
||||
# --- Helpers ---
|
||||
|
||||
async def _get_me(token: str) -> dict | None:
|
||||
@@ -171,6 +189,7 @@ def _bot_response(b: TelegramBot) -> dict:
|
||||
"bot_username": b.bot_username,
|
||||
"bot_id": b.bot_id,
|
||||
"token_preview": f"{b.token[:8]}...{b.token[-4:]}" if len(b.token) > 12 else "***",
|
||||
"commands_config": b.commands_config,
|
||||
"created_at": b.created_at.isoformat(),
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user