import logging from yuxi.channel.extensions.tlon.utils import normalize_ship logger = logging.getLogger(__name__) async def list_contacts(api) -> list[dict]: try: data = await api.scry("/contacts/all.json") if not data: data = await api.scry("/contacts/v1/all.json") result = [] contacts = data.get("contacts", data) for ship, contact in contacts.items(): if not isinstance(contact, dict): continue result.append({ "ship": ship, "nickname": contact.get("nickname", ""), "bio": contact.get("bio", ""), "status": contact.get("status", ""), "avatar": contact.get("avatar", ""), "cover": contact.get("cover", ""), }) return result except Exception as e: logger.warning("[tlon] Failed to list contacts: %s", e) return [] async def add_contact(api, ship: str, nickname: str = "", bio: str = "", status: str = "") -> None: payload = {"add": {"ship": normalize_ship(ship)}} if nickname: payload["add"]["nickname"] = nickname if bio: payload["add"]["bio"] = bio if status: payload["add"]["status"] = status await api.poke(app="contacts", mark="contact-action-1", json_data=payload) async def remove_contact(api, ship: str) -> None: await api.poke(app="contacts", mark="contact-action-1", json_data={"del": {"ship": normalize_ship(ship)}}) async def update_profile(api, ship: str, nickname: str = "", bio: str = "", status: str = "", avatar: str = "", cover: str = "") -> None: edit_payload = {"ship": normalize_ship(ship)} if nickname: edit_payload["nickname"] = nickname if bio: edit_payload["bio"] = bio if status: edit_payload["status"] = status if avatar: edit_payload["avatar"] = avatar if cover: edit_payload["cover"] = cover await api.poke(app="contacts", mark="contact-action-1", json_data={"edit": edit_payload}) async def sync_contacts(api) -> list[dict]: await api.poke(app="contacts", mark="contact-action-1", json_data={"sync": {}}) return await list_contacts(api)