"""Support for the Asterisk Voicemail interface.""" from __future__ import annotations from functools import partial import logging from typing import Any from asterisk_mbox import ServerError from homeassistant.components.mailbox import CONTENT_TYPE_MPEG, Mailbox, StreamError from homeassistant.core import HomeAssistant, callback from homeassistant.helpers.dispatcher import async_dispatcher_connect from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType from . import DOMAIN as ASTERISK_DOMAIN, AsteriskData _LOGGER = logging.getLogger(__name__) SIGNAL_MESSAGE_REQUEST = "asterisk_mbox.message_request" SIGNAL_MESSAGE_UPDATE = "asterisk_mbox.message_updated" async def async_get_handler( hass: HomeAssistant, config: ConfigType, discovery_info: DiscoveryInfoType | None = None, ) -> Mailbox: """Set up the Asterix VM platform.""" return AsteriskMailbox(hass, ASTERISK_DOMAIN) class AsteriskMailbox(Mailbox): """Asterisk VM Sensor.""" def __init__(self, hass: HomeAssistant, name: str) -> None: """Initialize Asterisk mailbox.""" super().__init__(hass, name) async_dispatcher_connect( self.hass, SIGNAL_MESSAGE_UPDATE, self._update_callback ) @callback def _update_callback(self, msg: str) -> None: """Update the message count in HA, if needed.""" self.async_update() @property def media_type(self) -> str: """Return the supported media type.""" return CONTENT_TYPE_MPEG @property def can_delete(self) -> bool: """Return if messages can be deleted.""" return True @property def has_media(self) -> bool: """Return if messages have attached media files.""" return True async def async_get_media(self, msgid: str) -> bytes: """Return the media blob for the msgid.""" data: AsteriskData = self.hass.data[ASTERISK_DOMAIN] client = data.client try: return await self.hass.async_add_executor_job( partial(client.mp3, msgid, sync=True) ) except ServerError as err: raise StreamError(err) from err async def async_get_messages(self) -> list[dict[str, Any]]: """Return a list of the current messages.""" data: AsteriskData = self.hass.data[ASTERISK_DOMAIN] return data.messages async def async_delete(self, msgid: str) -> bool: """Delete the specified messages.""" data: AsteriskData = self.hass.data[ASTERISK_DOMAIN] client = data.client _LOGGER.info("Deleting: %s", msgid) await self.hass.async_add_executor_job(client.delete, msgid) return True