"""Search-related Immich bot commands: search, find, person, place.""" from __future__ import annotations from typing import Any from ..handler import _render_cmd_template from .common import _format_assets def _enrich_assets(assets: list[dict[str, Any]], asset_public_urls: dict[str, str]) -> list[dict[str, Any]]: """Add public_url to assets from the pre-built map. Returns new list without mutating inputs.""" if not asset_public_urls: return assets return [ {**asset, "public_url": asset_public_urls.get(asset.get("id", ""), "")} if asset.get("id", "") in asset_public_urls and not asset.get("public_url") else asset for asset in assets ] async def cmd_search( client: Any, args: str, all_album_ids: list[str], count: int, locale: str, response_mode: str, cmd_templates: dict[str, dict[str, str]], asset_public_urls: dict[str, str] | None = None, page: int = 1, ) -> str | dict[str, Any]: """Handle /search command.""" if not args: return _render_cmd_template(cmd_templates, "no_results", locale, {"command": "search", "query": ""}) assets = await client.search_smart(args, album_ids=all_album_ids, limit=count, page=page) _enrich_assets(assets, asset_public_urls or {}) return _format_assets(assets, "search", args, locale, response_mode, client, cmd_templates) async def cmd_find( client: Any, args: str, all_album_ids: list[str], count: int, locale: str, response_mode: str, cmd_templates: dict[str, dict[str, str]], asset_public_urls: dict[str, str] | None = None, page: int = 1, ) -> str | dict[str, Any]: """Handle /find command.""" if not args: return _render_cmd_template(cmd_templates, "no_results", locale, {"command": "find", "query": ""}) assets = await client.search_metadata(args, album_ids=all_album_ids, limit=count, page=page) _enrich_assets(assets, asset_public_urls or {}) return _format_assets(assets, "find", args, locale, response_mode, client, cmd_templates) async def cmd_person( client: Any, args: str, count: int, locale: str, response_mode: str, cmd_templates: dict[str, dict[str, str]], asset_public_urls: dict[str, str] | None = None, ) -> str | dict[str, Any]: """Handle /person command.""" if not args: return _render_cmd_template(cmd_templates, "no_results", locale, {"command": "person", "query": ""}) people = await client.get_people() person_id = None for pid, pname in people.items(): if args.lower() in pname.lower(): person_id = pid break if not person_id: return _render_cmd_template(cmd_templates, "no_results", locale, {"command": "person", "query": args}) assets = await client.search_by_person(person_id, limit=count) _enrich_assets(assets, asset_public_urls or {}) return _format_assets(assets, "person", args, locale, response_mode, client, cmd_templates) async def cmd_place( client: Any, args: str, all_album_ids: list[str], count: int, locale: str, response_mode: str, cmd_templates: dict[str, dict[str, str]], asset_public_urls: dict[str, str] | None = None, ) -> str | dict[str, Any]: """Handle /place command.""" if not args: return _render_cmd_template(cmd_templates, "no_results", locale, {"command": "place", "query": ""}) assets = await client.search_smart( f"photos taken in {args}", album_ids=all_album_ids, limit=count ) _enrich_assets(assets, asset_public_urls or {}) return _format_assets(assets, "place", args, locale, response_mode, client, cmd_templates)