Di fm favorites#3458
Conversation
- Add LIBRARY_RADIOS_EDIT to SUPPORTED_FEATURES - Add CACHE_FAVORITES constant (5 min TTL) - Refactor _api_request to support POST/DELETE methods and JSON bodies - Add _get_user_favorites() to fetch favorites from members/me/favorites - Add _get_channel_id() and _invalidate_favorites_cache() helpers - Update get_library_radios() to yield only user-favorited stations - Add library_add() to POST a station to user favorites - Add library_remove() to DELETE a station from user favorites Co-authored-by: benklop <2729824+benklop@users.noreply.github.com> Agent-Logs-Url: https://github.com/benklop/music-assistant-server/sessions/6025c039-23ca-4ac7-ada7-3d9426e814ee
…imported-api-favorites
There was a problem hiding this comment.
Pull request overview
This PR enhances the Digitally Incorporated provider to expose a read-only “Favorites” radio library by fetching and parsing each network’s favorites.pls, mapping entries to channel keys, and returning only those favorites from get_library_radios.
Changes:
- Add favorites fetching/parsing logic (PLS download + URL-to-channel-key mapping) with a short-lived cache.
- Update
get_library_radiosto yield only favorited stations per enabled network. - Generalize
_api_requestto support arbitrary HTTP methods, optional JSON bodies, and 204 responses.
…it executes after type check
|
This looks good Ben. It is now correctly using get_library_radios, If you can just resolve the two copilot comments which seem fair (although the second one is pretty minor) we can move this forward. Thanks for the quick turnaround! |
apply feedback Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
|
@benklop could you address that final copilot comment? |
…erived slugs. Introduced a new dictionary for lowercased channel keys to improve lookup efficiency.
done. sorry for that. I guess i didn't see that one. |
| # Build a lowercase-keyed view for case-insensitive matching. | ||
| lower_channels_by_key = {key.lower(): value for key, value in channels_by_key.items()} |
There was a problem hiding this comment.
lower_channels_by_key is built on every _channel_data_for_pls_key call but never used, which adds an avoidable O(n) dict construction per favorite lookup.
This can noticeably slow down library loading when a user has many favorites.
Remove this local dict and rely on the already-precomputed channels_lower_by_key passed in (or use the local one instead and stop passing the extra argument).
| # Build a lowercase-keyed view for case-insensitive matching. | |
| lower_channels_by_key = {key.lower(): value for key, value in channels_by_key.items()} |
|
Sorry new copilot comment is valid and is the same as the mypy failure. |
| return channels_lower_by_key[trimmed_lower] | ||
| return None | ||
|
|
||
| def _parse_favorites_pls_channel_keys(self, pls_body: str, network_key: str) -> list[str]: |
There was a problem hiding this comment.
We have a ready to use helper available for pls parsing at music_assistant.helpers.playlists (parse_pls). You could use it like:
def _parse_favorites_pls_channel_keys(self, pls_body: str, network_key: str) -> list[str]:
try:
items = parse_pls(pls_body)
except InvalidDataError:
return []
ordered = []
seen_keys = set()
for item in items:
channel_key = self._stream_url_to_channel_key(item.path, network_key)
if channel_key and channel_key not in seen_keys:
seen_keys.add(channel_key)
ordered.append(channel_key)
return ordered
There was a problem hiding this comment.
So 'pls' use that one ;-)
|
Marking this PR as draft so we can keep track of which PRs needs our attention. Please mark as 'Ready for review' when you want us to have another look 🙏 . |
|
@benklop This is close to done and we are keen to help get it across the line. |
This pull request enhances the Digitally Incorporated provider by adding support for user favorites, allowing users to view (read-only) their favorite radio stations from each network via the
favorites.plsplaylist. The implementation includes robust parsing and mapping of playlist entries to API channel keys, introduces caching for efficiency, and improves error handling and logging. Additionally, the API request method is generalized to support multiple HTTP methods and request bodies.Favorites support and playlist parsing:
favorites.plsfile (read-only), with detailed parsing logic to extract and map stream URLs to channel keys, including handling of codec suffixes and mount prefixes. [1] [2]get_library_radiosmethod to yield only the user's favorite radio stations, using the parsed favorite channel keys and improved error logging. [1] [2]Caching and configuration improvements:
API and internal method enhancements:
_api_requestmethod to support different HTTP methods and optional JSON bodies, improving flexibility for future API interactions. [1] [2]