from __future__ import annotations from typing import Any, TYPE_CHECKING from yuxi.utils.logging_config import logger if TYPE_CHECKING: from .client import UrbitClient class DirectoryQuery: def __init__(self, client: UrbitClient): self._client = client async def list_contacts(self) -> list[dict[str, Any]]: from .scry import scry_contacts try: data = await scry_contacts(self._client) if not data or not isinstance(data, dict): return [] contacts: list[dict[str, Any]] = [] for ship, info in data.items(): if isinstance(info, dict): contacts.append( { "ship": f"~{ship.lstrip('~')}", "nickname": info.get("nickname", ""), "bio": info.get("bio", ""), "status": info.get("status", ""), "avatar": info.get("avatar", ""), "color": info.get("color", ""), } ) logger.info(f"[Urbit] Directory: found {len(contacts)} contacts") return contacts except Exception as e: logger.warning(f"[Urbit] Directory query failed: {e}") return [] async def list_peers(self) -> list[str]: try: r = await self._client.get("/~/peers", timeout=10.0) if r.status_code != 200: logger.warning(f"[Urbit] Directory: /~/peers returned {r.status_code}") return [] data = r.json() peers = [] for peer_key in data: if isinstance(peer_key, str): peers.append(f"~{peer_key.lstrip('~')}") logger.info(f"[Urbit] Directory: found {len(peers)} peers") return peers except Exception as e: logger.warning(f"[Urbit] Directory peers query failed: {e}") return [] async def search_contact(self, query: str) -> list[dict[str, Any]]: contacts = await self.list_contacts() query_lower = query.lower() return [ c for c in contacts if query_lower in c.get("ship", "").lower() or query_lower in c.get("nickname", "").lower() ]