import logging import httpx logger = logging.getLogger(__name__) MESSENGER_API_BASE = "https://graph.facebook.com/v22.0" GREETING_TEXT_MAX = 160 class MessengerProfileAPI: def __init__(self, page_id: str, access_token: str): self._page_id = page_id self._access_token = access_token async def _post_profile(self, payload: dict) -> bool: url = f"{MESSENGER_API_BASE}/me/messenger_profile" try: async with httpx.AsyncClient(timeout=httpx.Timeout(30.0)) as client: resp = await client.post( url, params={"access_token": self._access_token}, json=payload, ) if resp.status_code == 200: return True logger.error(f"messenger profile API failed: {resp.status_code} {resp.text}") return False except Exception: logger.exception("messenger profile API error") return False async def _delete_profile(self, fields: list[str]) -> bool: url = f"{MESSENGER_API_BASE}/me/messenger_profile" try: async with httpx.AsyncClient(timeout=httpx.Timeout(30.0)) as client: resp = await client.delete( url, params={"access_token": self._access_token}, json={"fields": fields}, ) return resp.status_code == 200 except Exception: logger.exception("messenger profile delete error") return False async def set_persistent_menu(self, menu_items: list[dict], composer_input_disabled: bool = False) -> bool: payload = { "persistent_menu": [ { "locale": "default", "composer_input_disabled": composer_input_disabled, "call_to_actions": menu_items, } ] } return await self._post_profile(payload) async def delete_persistent_menu(self) -> bool: return await self._delete_profile(["persistent_menu"]) async def set_greeting(self, greeting_text: str) -> bool: payload = { "greeting": [ { "locale": "default", "text": greeting_text[:GREETING_TEXT_MAX], } ] } return await self._post_profile(payload) async def delete_greeting(self) -> bool: return await self._delete_profile(["greeting"]) async def set_get_started(self, payload_text: str) -> bool: payload = { "get_started": {"payload": payload_text}, } return await self._post_profile(payload) async def delete_get_started(self) -> bool: return await self._delete_profile(["get_started"]) async def set_whitelisted_domains(self, domains: list[str]) -> bool: payload = { "whitelisted_domains": domains, } return await self._post_profile(payload) async def delete_whitelisted_domains(self) -> bool: return await self._delete_profile(["whitelisted_domains"])