Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 43 additions & 13 deletions custom_components/mass_queue/actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
ATTR_PROVIDERS,
ATTR_QUEUE_ID,
ATTR_QUEUE_ITEM_ID,
ATTR_RELEASE_DATE,
ATTR_VOLUME_LEVEL,
CONF_DOWNLOAD_LOCAL,
DEFAULT_QUEUE_ITEMS_LIMIT,
Expand Down Expand Up @@ -365,6 +366,12 @@ async def get_playlist_details(self, playlist_uri):
LOGGER.debug(f"Getting album details for provider {provider}")
return await self._client.music.get_playlist(item_id, provider)

async def get_podcast_details(self, podcast_uri):
"""Retrieves the details for a podcast."""
provider, item_id = parse_uri(podcast_uri)
LOGGER.debug(f"Getting podcast details for provider {provider}")
return await self._client.music.get_podcast(item_id, provider)

async def get_artist_tracks(self, artist_uri: str, page: int | None = None):
"""Retrieves a limited number of tracks from an artist."""
details = await self.get_artist_details(artist_uri)
Expand Down Expand Up @@ -399,6 +406,17 @@ async def get_album_tracks(self, album_uri: str, page: int | None = None):
)
return [self.format_track_item(item.to_dict()) for item in resp]

async def get_podcast_episodes(self, podcast_uri):
"""Retrieves all episodes for a podcast."""
provider, item_id = parse_uri(podcast_uri)
LOGGER.debug(
f"Getting podcast episodes for provider {provider}, item_id {item_id}",
)
resp: list = await self._client.music.get_podcast_episodes(item_id, provider)
formatted = [self.format_podcast_episode(item.to_dict()) for item in resp]
formatted.sort(key=lambda x: x[ATTR_RELEASE_DATE], reverse=True)
return formatted

async def get_playlist_tracks(self, playlist_uri: str, page: int | None = None):
"""Retrieves all playlist items."""
provider, item_id = parse_uri(playlist_uri)
Expand All @@ -418,25 +436,37 @@ def format_playlist_track(self, playlist_track: dict) -> TRACK_ITEM_SCHEMA:
result[ATTR_POSITION] = playlist_track["position"]
return result

def format_track_item(self, playlist_item: dict) -> TRACK_ITEM_SCHEMA:
"""Processes the individual items in a playlist."""
media_title = playlist_item.get("name") or "N/A"
media_album = playlist_item.get("album") or "N/A"
def format_track_item(self, track_item: dict) -> TRACK_ITEM_SCHEMA:
"""Process an individual track item."""
result = self.format_item(track_item)
media_album = track_item.get("album") or "N/A"
media_album_name = "" if media_album is None else media_album.get("name", "")
media_content_id = playlist_item["uri"]
media_image = find_image(playlist_item) or ""
local_image_encoded = playlist_item.get(ATTR_LOCAL_IMAGE_ENCODED)
favorite = playlist_item["favorite"]
duration = playlist_item["duration"] or 0

artists = playlist_item["artists"]
artists = track_item["artists"]
artist_names = [artist["name"] for artist in artists]
media_artist = ", ".join(artist_names)
result[ATTR_MEDIA_ALBUM_NAME] = media_album_name
result[ATTR_MEDIA_ARTIST] = media_artist
return result

def format_podcast_episode(self, podcast_episode: dict) -> TRACK_ITEM_SCHEMA:
"""Process an individual track item."""
result = self.format_item(podcast_episode)
result[ATTR_RELEASE_DATE] = podcast_episode.get("metadata", {}).get(
"release_date",
)
return result

def format_item(self, media_item: dict) -> TRACK_ITEM_SCHEMA:
"""Processes the individual items in a playlist."""
media_title = media_item.get("name") or "N/A"
media_content_id = media_item["uri"]
media_image = find_image(media_item) or ""
local_image_encoded = media_item.get(ATTR_LOCAL_IMAGE_ENCODED)
favorite = media_item["favorite"]
duration = media_item["duration"] or 0
response: ServiceResponse = TRACK_ITEM_SCHEMA(
{
ATTR_MEDIA_TITLE: media_title,
ATTR_MEDIA_ALBUM_NAME: media_album_name,
ATTR_MEDIA_ARTIST: media_artist,
ATTR_MEDIA_CONTENT_ID: media_content_id,
ATTR_DURATION: duration,
ATTR_MEDIA_IMAGE: media_image,
Expand Down
3 changes: 3 additions & 0 deletions custom_components/mass_queue/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
SERVICE_GET_ARTIST_TRACKS = "get_artist_tracks"
SERVICE_GET_PLAYLIST = "get_playlist"
SERVICE_GET_PLAYLIST_TRACKS = "get_playlist_tracks"
SERVICE_GET_PODCAST = "get_podcast"
SERVICE_GET_PODCAST_EPISODES = "get_podcast_episodes"
SERVICE_GET_QUEUE_ITEMS = "get_queue_items"
SERVICE_GET_RECOMMENDATIONS = "get_recommendations"
SERVICE_PLAY_QUEUE_ITEM = "play_queue_item"
Expand Down Expand Up @@ -54,6 +56,7 @@
ATTR_QUEUE_ID = "active_queue"
ATTR_QUEUE_ITEM_ID = "queue_item_id"
ATTR_QUEUE_ITEMS = "queue_items"
ATTR_RELEASE_DATE = "release_date"
ATTR_VOLUME_LEVEL = "volume_level"

CONF_DOWNLOAD_LOCAL = "download_local"
Expand Down
2 changes: 2 additions & 0 deletions custom_components/mass_queue/icons.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
"get_artist_tracks": { "service": "mdi:account-music"},
"get_playlist": { "service": "mdi:playlist-music"},
"get_playlist_tracks": { "service": "mdi:playlist-music"},
"get_podcast": { "service": "mdi:podcast"},
"get_podcast_episodes": { "service": "mdi:podcast"},
"get_queue_items": { "service": "mdi:playlist-music" },
"move_queue_item_down": { "service": "mdi:arrow-down" },
"move_queue_item_next": { "service": "mdi:arrow-collapse-up" },
Expand Down
2 changes: 1 addition & 1 deletion custom_components/mass_queue/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@
"issue_tracker": "https://github.com/droans/mass_queue/issues",
"requirements": ["music-assistant-client"],
"ssdp": [],
"version": "0.9.2",
"version": "0.10.0-b.2",
"zeroconf": ["_mass._tcp.local."]
}
11 changes: 9 additions & 2 deletions custom_components/mass_queue/schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,8 @@
TRACK_ITEM_SCHEMA = vol.Schema(
{
vol.Required(ATTR_MEDIA_TITLE): str,
vol.Required(ATTR_MEDIA_ALBUM_NAME): str,
vol.Required(ATTR_MEDIA_ARTIST): str,
vol.Optional(ATTR_MEDIA_ALBUM_NAME): str,
vol.Optional(ATTR_MEDIA_ARTIST): str,
vol.Required(ATTR_MEDIA_CONTENT_ID): str,
vol.Required(ATTR_MEDIA_IMAGE): str,
vol.Required(ATTR_FAVORITE): bool,
Expand Down Expand Up @@ -137,6 +137,13 @@
},
)

GET_PODCAST_EPISODES_SERVICE_SCHEMA = vol.Schema(
{
vol.Required(ATTR_CONFIG_ENTRY_ID): str,
vol.Required(ATTR_URI): str,
},
)

GET_DATA_SERVICE_SCHEMA = vol.Schema(
{
vol.Required(ATTR_CONFIG_ENTRY_ID): str,
Expand Down
46 changes: 44 additions & 2 deletions custom_components/mass_queue/services.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

from .const import (
ATTR_CONFIG_ENTRY_ID,
ATTR_PAGE,
ATTR_PLAYER_ENTITY,
ATTR_PLAYLIST_ID,
ATTR_POSITIONS_TO_REMOVE,
Expand All @@ -25,6 +26,8 @@
SERVICE_GET_GROUP_VOLUME,
SERVICE_GET_PLAYLIST,
SERVICE_GET_PLAYLIST_TRACKS,
SERVICE_GET_PODCAST,
SERVICE_GET_PODCAST_EPISODES,
SERVICE_GET_QUEUE_ITEMS,
SERVICE_GET_RECOMMENDATIONS,
SERVICE_MOVE_QUEUE_ITEM_DOWN,
Expand All @@ -41,6 +44,7 @@
CLEAR_QUEUE_FROM_HERE_SERVICE_SCHEMA,
GET_DATA_SERVICE_SCHEMA,
GET_GROUP_VOLUME_SERVICE_SCHEMA,
GET_PODCAST_EPISODES_SERVICE_SCHEMA,
GET_RECOMMENDATIONS_SERVICE_SCHEMA,
GET_TRACKS_SERVICE_SCHEMA,
MOVE_QUEUE_ITEM_DOWN_SERVICE_SCHEMA,
Expand Down Expand Up @@ -165,6 +169,13 @@ def register_actions(hass) -> None:
schema=GET_TRACKS_SERVICE_SCHEMA,
supports_response=SupportsResponse.ONLY,
)
hass.services.async_register(
DOMAIN,
SERVICE_GET_PODCAST_EPISODES,
get_podcast_episodes,
schema=GET_PODCAST_EPISODES_SERVICE_SCHEMA,
supports_response=SupportsResponse.ONLY,
)
hass.services.async_register(
DOMAIN,
SERVICE_GET_ALBUM,
Expand All @@ -186,6 +197,13 @@ def register_actions(hass) -> None:
schema=GET_DATA_SERVICE_SCHEMA,
supports_response=SupportsResponse.ONLY,
)
hass.services.async_register(
DOMAIN,
SERVICE_GET_PODCAST,
get_podcast,
schema=GET_DATA_SERVICE_SCHEMA,
supports_response=SupportsResponse.ONLY,
)
hass.services.async_register(
DOMAIN,
SERVICE_REMOVE_PLAYLIST_TRACKS,
Expand Down Expand Up @@ -320,11 +338,12 @@ async def get_album_tracks(call: ServiceCall):
"""Gets all tracks in an album."""
config_entry = call.data[ATTR_CONFIG_ENTRY_ID]
uri = call.data[ATTR_URI]
page = call.data.get(ATTR_PAGE)
hass = call.hass
entry = hass.config_entries.async_get_entry(config_entry)
actions = entry.runtime_data.actions
return {
"tracks": await actions.get_album_tracks(uri),
"tracks": await actions.get_album_tracks(uri, page),
}


Expand All @@ -344,11 +363,24 @@ async def get_playlist_tracks(call: ServiceCall):
"""Gets all tracks in a playlist."""
config_entry = call.data[ATTR_CONFIG_ENTRY_ID]
uri = call.data[ATTR_URI]
page = call.data.get(ATTR_PAGE)
hass = call.hass
entry = hass.config_entries.async_get_entry(config_entry)
actions = entry.runtime_data.actions
return {
"tracks": await actions.get_playlist_tracks(uri),
"tracks": await actions.get_playlist_tracks(uri, page),
}


async def get_podcast_episodes(call: ServiceCall):
"""Gets all episodes for a podcast."""
config_entry = call.data[ATTR_CONFIG_ENTRY_ID]
uri = call.data[ATTR_URI]
hass = call.hass
entry = hass.config_entries.async_get_entry(config_entry)
actions = entry.runtime_data.actions
return {
"episodes": await actions.get_podcast_episodes(uri),
}


Expand Down Expand Up @@ -382,6 +414,16 @@ async def get_playlist(call: ServiceCall):
return (await actions.get_playlist_details(uri)).to_dict()


async def get_podcast(call: ServiceCall):
"""Returns the details about a podcast from the server."""
config_entry = call.data[ATTR_CONFIG_ENTRY_ID]
uri = call.data[ATTR_URI]
hass = call.hass
entry = hass.config_entries.async_get_entry(config_entry)
actions = entry.runtime_data.actions
return (await actions.get_podcast_details(uri)).to_dict()


async def remove_playlist_tracks(call: ServiceCall):
"""Removes one or more items from a playlist."""
config_entry = call.data[ATTR_CONFIG_ENTRY_ID]
Expand Down
30 changes: 30 additions & 0 deletions custom_components/mass_queue/services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,21 @@ get_artist_tracks:
mode: box
required: false
example: 0
get_podcast_episodes:
fields:
config_entry_id:
name: Config Entry ID
required: true
selector:
config_entry:
integration: mass_queue
uri:
name: Podcast URI
description: URI for the podcast
selector:
text:
example: "library://podcast/12"
required: true
get_album:
fields:
config_entry_id:
Expand Down Expand Up @@ -334,6 +349,21 @@ get_playlist:
text:
example: "library://playlist/12"
required: true
get_podcast:
fields:
config_entry_id:
name: Config Entry ID
required: true
selector:
config_entry:
integration: mass_queue
uri:
name: Podcast URI
description: URI for the podcast
selector:
text:
example: "library://podcast/12"
required: true
remove_playlist_tracks:
fields:
config_entry_id:
Expand Down
28 changes: 28 additions & 0 deletions custom_components/mass_queue/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,20 @@
}
}
},
"get_podcast_episodes": {
"name": "Get Podcast Episodes",
"description": "Returns all episodes for the podcast given.",
"fields": {
"config_entry_id": {
"name": "Config Entry ID",
"description": "Config Entry ID for the Music Assistant Queue Items instance."
},
"uri": {
"name": "Podcast URI",
"description": "URI for the podcast."
}
}
},
"get_playlist": {
"name": "Get Playlist",
"description": "Returns information about a playlist from the server.",
Expand Down Expand Up @@ -339,6 +353,20 @@
}
}
},
"get_podcast": {
"name": "Get Podcast",
"description": "Returns information about a podcast from the server.",
"fields": {
"config_entry_id": {
"name": "Config Entry ID",
"description": "Config Entry ID for the Music Assistant Queue Items instance."
},
"uri": {
"name": "Podcast URI",
"description": "URI for the podcast."
}
}
},
"remove_playlist_tracks": {
"name": "Remove Playlist Tracks",
"description": "Removes one or more tracks from a playlist based on position.",
Expand Down
28 changes: 28 additions & 0 deletions custom_components/mass_queue/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,20 @@
}
}
},
"get_podcast_episodes": {
"name": "Get Podcast Episodes",
"description": "Returns all episodes for the podcast given.",
"fields": {
"config_entry_id": {
"name": "Config Entry ID",
"description": "Config Entry ID for the Music Assistant Queue Items instance."
},
"uri": {
"name": "Podcast URI",
"description": "URI for the podcast."
}
}
},
"get_playlist": {
"name": "Get Playlist",
"description": "Returns information about a playlist from the server.",
Expand Down Expand Up @@ -315,6 +329,20 @@
}
}
},
"get_podcast": {
"name": "Get Podcast",
"description": "Returns information about a podcast from the server.",
"fields": {
"config_entry_id": {
"name": "Config Entry ID",
"description": "Config Entry ID for the Music Assistant Queue Items instance."
},
"uri": {
"name": "Podcast URI",
"description": "URI for the podcast."
}
}
},
"remove_playlist_tracks": {
"name": "Remove Playlist Tracks",
"description": "Removes one or more tracks from a playlist based on position.",
Expand Down
Loading