"""Sensor for Last.fm account status.""" from __future__ import annotations import hashlib from pylast import LastFMNetwork, PyLastError, Track, User import voluptuous as vol from homeassistant.components.sensor import PLATFORM_SCHEMA, SensorEntity from homeassistant.config_entries import SOURCE_IMPORT, ConfigEntry from homeassistant.const import CONF_API_KEY from homeassistant.core import HomeAssistant import homeassistant.helpers.config_validation as cv from homeassistant.helpers.device_registry import DeviceEntryType from homeassistant.helpers.entity import DeviceInfo from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.issue_registry import IssueSeverity, async_create_issue from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType from .const import ( ATTR_LAST_PLAYED, ATTR_PLAY_COUNT, ATTR_TOP_PLAYED, CONF_USERS, DEFAULT_NAME, DOMAIN, LOGGER, STATE_NOT_SCROBBLING, ) PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend( { vol.Required(CONF_API_KEY): cv.string, vol.Required(CONF_USERS, default=[]): vol.All(cv.ensure_list, [cv.string]), } ) def format_track(track: Track) -> str: """Format the track.""" return f"{track.artist} - {track.title}" async def async_setup_platform( hass: HomeAssistant, config: ConfigType, async_add_entities: AddEntitiesCallback, discovery_info: DiscoveryInfoType | None = None, ) -> None: """Set up the Last.fm sensor platform from yaml.""" async_create_issue( hass, DOMAIN, "deprecated_yaml", breaks_in_ha_version="2023.8.0", is_fixable=False, severity=IssueSeverity.WARNING, translation_key="deprecated_yaml", ) hass.async_create_task( hass.config_entries.flow.async_init( DOMAIN, context={"source": SOURCE_IMPORT}, data=config ) ) async def async_setup_entry( hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback, ) -> None: """Initialize the entries.""" lastfm_api = LastFMNetwork(api_key=entry.options[CONF_API_KEY]) async_add_entities( ( LastFmSensor(lastfm_api.get_user(user), entry.entry_id) for user in entry.options[CONF_USERS] ), True, ) class LastFmSensor(SensorEntity): """A class for the Last.fm account.""" _attr_attribution = "Data provided by Last.fm" _attr_icon = "mdi:radio-fm" def __init__(self, user: User, entry_id: str) -> None: """Initialize the sensor.""" self._user = user self._attr_unique_id = hashlib.sha256(user.name.encode("utf-8")).hexdigest() self._attr_name = user.name self._attr_device_info = DeviceInfo( configuration_url="https://www.last.fm", entry_type=DeviceEntryType.SERVICE, identifiers={(DOMAIN, f"{entry_id}_{self._attr_unique_id}")}, manufacturer=DEFAULT_NAME, name=f"{DEFAULT_NAME} {user.name}", ) def update(self) -> None: """Update device state.""" self._attr_native_value = STATE_NOT_SCROBBLING try: play_count = self._user.get_playcount() self._attr_entity_picture = self._user.get_image() now_playing = self._user.get_now_playing() top_tracks = self._user.get_top_tracks(limit=1) last_tracks = self._user.get_recent_tracks(limit=1) except PyLastError as exc: self._attr_available = False LOGGER.error("Failed to load LastFM user `%s`: %r", self._user.name, exc) return self._attr_available = True if now_playing: self._attr_native_value = format_track(now_playing) self._attr_extra_state_attributes = { ATTR_PLAY_COUNT: play_count, ATTR_LAST_PLAYED: None, ATTR_TOP_PLAYED: None, } if len(last_tracks) > 0: self._attr_extra_state_attributes[ATTR_LAST_PLAYED] = format_track( last_tracks[0].track ) if len(top_tracks) > 0: self._attr_extra_state_attributes[ATTR_TOP_PLAYED] = format_track( top_tracks[0].item )