from __future__ import annotations from typing import Any from yuxi.channels.adapters.bluebubbles.client import BlueBubblesClient EFFECT_MAP: dict[str, str] = { "slam": "com.apple.messages.expressive-send.effect.loud", "loud": "com.apple.messages.expressive-send.effect.loud", "gentle": "com.apple.messages.expressive-send.effect.gentle", "invisible-ink": "com.apple.messages.expressive-send.effect.invisibleInk", "invisible_ink": "com.apple.messages.expressive-send.effect.invisibleInk", "invisibleink": "com.apple.messages.expressive-send.effect.invisibleInk", "invisible": "com.apple.messages.expressive-send.effect.invisibleInk", "confetti": "com.apple.messages.expressive-send.effect.confetti", "lasers": "com.apple.messages.expressive-send.effect.lasers", "fireworks": "com.apple.messages.expressive-send.effect.fireworks", "balloons": "com.apple.messages.expressive-send.effect.balloons", "heart": "com.apple.messages.expressive-send.effect.heart", "love": "com.apple.messages.expressive-send.effect.heart", "hearts": "com.apple.messages.expressive-send.effect.heart", "echo": "com.apple.messages.expressive-send.effect.echo", "spotlight": "com.apple.messages.expressive-send.effect.spotlight", "celebration": "com.apple.messages.expressive-send.effect.sparkles", "sparkles": "com.apple.messages.expressive-send.effect.sparkles", } def _normalize_key(raw: str) -> str: return raw.lower().replace(" ", "").replace("_", "").replace("-", "") _EFFECT_LOOKUP: dict[str, str] = {_normalize_key(k): v for k, v in EFFECT_MAP.items()} def resolve_effect(effect_name: str) -> str | None: compact = _normalize_key(effect_name) if compact in _EFFECT_LOOKUP: return _EFFECT_LOOKUP[compact] exact = EFFECT_MAP.get(effect_name.lower().strip()) if exact: return exact normalized = EFFECT_MAP.get(effect_name.lower().strip().replace(" ", "_")) if normalized: return normalized hyphenated = EFFECT_MAP.get(effect_name.lower().strip().replace(" ", "-")) if hyphenated: return hyphenated return None async def send_with_effect( client: BlueBubblesClient, chat_guid: str, text: str, effect: str, reply_to_guid: str | None = None, ) -> dict[str, Any]: resolved = resolve_effect(effect) if resolved is None: raise ValueError(f"Unknown effect: {effect}") payload: dict[str, Any] = { "chatGuid": chat_guid, "text": text, "isHTML": False, "effectId": resolved, } if reply_to_guid: payload["replyToGuid"] = reply_to_guid return await client.post("/api/v1/message/text", json=payload)