A few small bugfixes (#749)
authorMarcel van der Veldt <m.vanderveldt@outlook.com>
Sat, 8 Jul 2023 00:08:01 +0000 (02:08 +0200)
committerGitHub <noreply@github.com>
Sat, 8 Jul 2023 00:08:01 +0000 (02:08 +0200)
* Fix error when enabling an unavailable player

* handle imageproxy on webserver too

* typo

* Fix parsing malformed data in Tunein

music_assistant/server/controllers/config.py
music_assistant/server/controllers/metadata.py
music_assistant/server/controllers/webserver.py
music_assistant/server/helpers/tags.py
music_assistant/server/providers/tunein/__init__.py

index af7718bc4c3ab92f8c5446e7edbabcbd51a6c950..08a2ec8edc48bdcfb79a651f785f9384d951c873 100644 (file)
@@ -299,7 +299,7 @@ class ConfigController:
         self.set(conf_key, value)
 
     @api_command("config/providers/reload")
-    async def reload_provider(self, instance_id: str, config: ProviderConfig | None) -> None:
+    async def reload_provider(self, instance_id: str) -> None:
         """Reload provider."""
         config = await self.get_provider_config(instance_id)
         await self._load_provider_config(config)
@@ -385,7 +385,7 @@ class ConfigController:
             data=config,
         )
         # signal update to the player manager
-        with suppress(PlayerUnavailableError, AttributeError):
+        with suppress(PlayerUnavailableError, AttributeError, KeyError):
             player = self.mass.players.get(config.player_id)
             if config.enabled:
                 player_prov = self.mass.players.get_player_provider(player_id)
index 0635d1cfffe2012e9ebf659785c4eb50c876a1bc..ed8181d29a6cc0f7ed67269698e6dc745ab538ec 100755 (executable)
@@ -57,7 +57,7 @@ class MetaDataController(CoreController):
 
     async def setup(self, config: CoreConfig) -> None:  # noqa: ARG002
         """Async initialize of module."""
-        self.mass.streams.register_dynamic_route("/imageproxy", self._handle_imageproxy)
+        self.mass.streams.register_dynamic_route("/imageproxy", self.handle_imageproxy)
 
     async def close(self) -> None:
         """Handle logic on server stop."""
@@ -334,7 +334,7 @@ class MetaDataController(CoreController):
             thumbnail = f"data:image/png;base64,{enc_image}"
         return thumbnail
 
-    async def _handle_imageproxy(self, request: web.Request) -> web.Response:
+    async def handle_imageproxy(self, request: web.Request) -> web.Response:
         """Handle request for image proxy."""
         path = request.query["path"]
         provider = request.query.get("provider", "url")
index 5f621a984a64503477eda8949ca12cefe6f763fe..24f3ba83eb24d5ec4fcb23aea7383153ccd3376e 100644 (file)
@@ -171,6 +171,8 @@ class WebserverController(CoreController):
         routes.append(("GET", "/info", self._handle_server_info))
         # add websocket api
         routes.append(("GET", "/ws", self._handle_ws_client))
+        # also host the image proxy on the webserver
+        routes.append(("GET", "/imageproxy", self.mass.metadata.handle_imageproxy))
         # start the webserver
         await self._server.setup(
             bind_ip=config.get_value(CONF_BIND_IP),
index 6430bff144c9d000b99f77e3a387e6aa1a2f34e8..5c9adf046d95527fa2bb53d61b71129eaf3ccf47 100644 (file)
@@ -255,7 +255,9 @@ class AudioTags:
     @classmethod
     def parse(cls, raw: dict) -> AudioTags:
         """Parse instance from raw ffmpeg info output."""
-        audio_stream = next(x for x in raw["streams"] if x["codec_type"] == "audio")
+        audio_stream = next((x for x in raw["streams"] if x["codec_type"] == "audio"), None)
+        if audio_stream is None:
+            raise InvalidDataError("No audio stream found")
         has_cover_image = any(x for x in raw["streams"] if x["codec_name"] in ("mjpeg", "png"))
         # convert all tag-keys (gathered from all streams) to lowercase without spaces
         tags = {}
index b0f3ecbc2fe47adc3a2adc7e5d30b9f28811bd79..1b7d0cac41c2555ae64b18f3f33be7202fa92c7c 100644 (file)
@@ -10,7 +10,7 @@ from asyncio_throttle import Throttler
 from music_assistant.common.helpers.util import create_sort_name
 from music_assistant.common.models.config_entries import ConfigEntry, ConfigValueType
 from music_assistant.common.models.enums import ConfigEntryType, ProviderFeature
-from music_assistant.common.models.errors import LoginFailed, MediaNotFoundError
+from music_assistant.common.models.errors import InvalidDataError, LoginFailed, MediaNotFoundError
 from music_assistant.common.models.media_items import (
     AudioFormat,
     ContentType,
@@ -100,13 +100,21 @@ class TuneInProvider(MusicProvider):
                 if item_type == "audio":
                     if "preset_id" not in item:
                         continue
+                    if "- Not Supported" in item.get("name", ""):
+                        continue
+                    if "- Not Supported" in item.get("text", ""):
+                        continue
                     # each radio station can have multiple streams add each one as different quality
                     stream_info = await self.__get_data("Tune.ashx", id=item["preset_id"])
                     for stream in stream_info["body"]:
                         yield await self._parse_radio(item, stream, folder)
                 elif item_type == "link" and item.get("item") == "url":
                     # custom url
-                    yield await self._parse_radio(item)
+                    try:
+                        yield await self._parse_radio(item)
+                    except InvalidDataError as err:
+                        # there may be invalid custom urls, ignore those
+                        self.logger.warning(str(err))
                 elif item_type == "link":
                     # stations are in sublevel (new style)
                     if sublevel := await self.__get_data(item["URL"], render="json"):