diff --git a/packages/server/src/notify_bridge_server/commands/handler.py b/packages/server/src/notify_bridge_server/commands/handler.py index 6db91f7..313509e 100644 --- a/packages/server/src/notify_bridge_server/commands/handler.py +++ b/packages/server/src/notify_bridge_server/commands/handler.py @@ -348,12 +348,23 @@ async def send_reply( bot_token: str, chat_id: str, text: str, reply_to_message_id: int | None = None, session: aiohttp.ClientSession | None = None, ) -> None: - """Send a text reply via TelegramClient.""" + """Send a text reply via TelegramClient. + + Command responses are listings (albums, people, events, ...) that embed + multiple links; Telegram's default behavior of rendering a preview of + the first URL is almost never what the user wants and clashes with the + "Disable link previews" toggle operators set on their Telegram target. + We always pass ``disable_web_page_preview=True`` here. + """ if session is None: from ..services.http_session import get_http_session session = await get_http_session() client = TelegramClient(session, bot_token) - result = await client.send_message(chat_id, text, reply_to_message_id=reply_to_message_id) + result = await client.send_message( + chat_id, text, + reply_to_message_id=reply_to_message_id, + disable_web_page_preview=True, + ) if not result.get("success"): _LOGGER.warning("Telegram reply failed: %s", result.get("error")) diff --git a/packages/server/src/notify_bridge_server/commands/immich/albums.py b/packages/server/src/notify_bridge_server/commands/immich/albums.py index 11afc63..91b0f19 100644 --- a/packages/server/src/notify_bridge_server/commands/immich/albums.py +++ b/packages/server/src/notify_bridge_server/commands/immich/albums.py @@ -6,7 +6,7 @@ import asyncio import logging from typing import Any -from ...database.models import ServiceProvider +from ...database.models import CommandTrackerListener, ServiceProvider from ...services import make_immich_provider from ...services.http_session import get_http_session from ..command_utils import get_trackers_for_provider @@ -17,7 +17,10 @@ _LOGGER = logging.getLogger(__name__) async def _cmd_albums( - provider: ServiceProvider, locale: str, + provider: ServiceProvider, + locale: str, + *, + listener: CommandTrackerListener | None = None, ) -> dict[str, Any]: trackers = await get_trackers_for_provider(provider.id) if not trackers: @@ -31,6 +34,14 @@ async def _cmd_albums( if aid not in seen: seen.add(aid) album_ids.append(aid) + + # Per-chat album scope — match what _cmd_immich does for media commands. + # Without this, /albums leaks the full list of tracked albums into chats + # that were explicitly scoped to a subset. + if listener is not None and listener.allowed_album_ids is not None: + allowed = set(listener.allowed_album_ids) + album_ids = [aid for aid in album_ids if aid in allowed] + if not album_ids: return {"albums": []} diff --git a/packages/server/src/notify_bridge_server/commands/immich/handler.py b/packages/server/src/notify_bridge_server/commands/immich/handler.py index f54ff59..f438508 100644 --- a/packages/server/src/notify_bridge_server/commands/immich/handler.py +++ b/packages/server/src/notify_bridge_server/commands/immich/handler.py @@ -86,7 +86,7 @@ class ImmichCommandHandler(ProviderCommandHandler): ctx = await _cmd_status(provider, locale) return CommandResponse(text=_render_cmd_template(cmd_templates, "status", locale, ctx)) if cmd == "albums": - ctx = await _cmd_albums(provider, locale) + ctx = await _cmd_albums(provider, locale, listener=listener) return CommandResponse(text=_render_cmd_template(cmd_templates, "albums", locale, ctx)) if cmd == "events": ctx = await _cmd_events(provider, count, locale)