From: Marcel van der Veldt Date: Mon, 6 May 2024 00:37:00 +0000 (+0200) Subject: various small tweaks X-Git-Url: https://git.kitaultman.com/?a=commitdiff_plain;h=732ac2b7fba8ca3504c7b8d57fb4c76e93e0f7de;p=music-assistant-server.git various small tweaks --- diff --git a/music_assistant/server/controllers/media/base.py b/music_assistant/server/controllers/media/base.py index 858884eb..7f3b6352 100644 --- a/music_assistant/server/controllers/media/base.py +++ b/music_assistant/server/controllers/media/base.py @@ -235,7 +235,9 @@ class MediaControllerBase(Generic[ItemCls], metaclass=ABCMeta): ) if library_item and (time() - (library_item.metadata.last_refresh or 0)) > REFRESH_INTERVAL: # it's been too long since the full metadata was last retrieved (or never at all) - metadata_lookup = True + if library_item.available: + # do not attempts metadata refresh on unavailable items as it has side effects + metadata_lookup = True if library_item and (force_refresh or metadata_lookup): # get (first) provider item id belonging to this library item add_to_library = True @@ -259,6 +261,10 @@ class MediaControllerBase(Generic[ItemCls], metaclass=ABCMeta): force_refresh=force_refresh, fallback=details, ) + if not details and library_item: + # something went wrong while trying to fetch/refresh this item + # return the existing (unavailable) library item and leave this for another day + return library_item if not details: # we couldn't get a match from any of the providers, raise error msg = f"Item not found: {provider_instance_id_or_domain}/{item_id}" @@ -337,11 +343,11 @@ class MediaControllerBase(Generic[ItemCls], metaclass=ABCMeta): async def get_provider_mapping(self, item: ItemCls) -> tuple[str, str]: """Return (first) provider and item id.""" if not getattr(item, "provider_mappings", None): - # make sure we have a full object - item = await self.get_library_item(item.item_id) + if item.provider == "library": + item = await self.get_library_item(item.item_id) + return (item.provider, item.item_id) for prefer_unique in (True, False): for prov_mapping in item.provider_mappings: - # returns the first provider that is available if not prov_mapping.available: continue if provider := self.mass.get_provider( @@ -352,6 +358,10 @@ class MediaControllerBase(Generic[ItemCls], metaclass=ABCMeta): if prefer_unique and provider.is_streaming_provider: continue return (prov_mapping.provider_instance, prov_mapping.item_id) + # last resort: return just the first entry + for prov_mapping in item.provider_mappings: + return (prov_mapping.provider_domain, prov_mapping.item_id) + return (None, None) async def get_library_item(self, item_id: int | str) -> ItemCls: diff --git a/music_assistant/server/controllers/metadata.py b/music_assistant/server/controllers/metadata.py index 31a5dedb..f9274177 100644 --- a/music_assistant/server/controllers/metadata.py +++ b/music_assistant/server/controllers/metadata.py @@ -186,12 +186,15 @@ class MetaDataController(CoreController): if lang in (locale_code.lower(), lang_name.lower()): self.mass.config.set_raw_core_config_value(self.domain, CONF_LANGUAGE, locale_code) return - # attempt loose match on either language or country code - for locale_code in tuple(LOCALES): - language_code, region_code = locale_code.lower().split("_", 1) - if lang in (language_code, region_code): - self.mass.config.set_raw_core_config_value(self.domain, CONF_LANGUAGE, locale_code) - return + # attempt loose match on language code or region code + for lang_part in (lang[:2], lang[:-2]): + for locale_code in tuple(LOCALES): + language_code, region_code = locale_code.lower().split("_", 1) + if lang_part in (language_code, region_code): + self.mass.config.set_raw_core_config_value( + self.domain, CONF_LANGUAGE, locale_code + ) + return # if we reach this point, we couldn't match the language self.logger.warning("%s is not a valid language", lang) @@ -508,7 +511,7 @@ class MetaDataController(CoreController): # assuming that images do not/rarely change return web.Response( body=image_data, - headers={"Cache-Control": "max-age=31536000"}, + headers={"Cache-Control": "max-age=31536000", "Access-Control-Allow-Origin": "*"}, content_type=f"image/{image_format}", ) return web.Response(status=404) diff --git a/music_assistant/server/providers/musicbrainz/__init__.py b/music_assistant/server/providers/musicbrainz/__init__.py index c2f970ce..469968f4 100644 --- a/music_assistant/server/providers/musicbrainz/__init__.py +++ b/music_assistant/server/providers/musicbrainz/__init__.py @@ -447,7 +447,7 @@ class MusicbrainzProvider(MetadataProvider): if response.status in (502, 503): raise ResourceTemporarilyUnavailable(backoff_time=30) # handle 404 not found, convert to MediaNotFoundError - if response.status == 404: + if response.status in (400, 401, 404): raise MediaNotFoundError(f"{endpoint} not found") response.raise_for_status() return await response.json(loads=json_loads) diff --git a/music_assistant/server/providers/tidal/__init__.py b/music_assistant/server/providers/tidal/__init__.py index fc0820cc..9eab6912 100644 --- a/music_assistant/server/providers/tidal/__init__.py +++ b/music_assistant/server/providers/tidal/__init__.py @@ -218,7 +218,18 @@ class TidalProvider(MusicProvider): async def handle_async_init(self) -> None: """Handle async initialization of the provider.""" self._tidal_user_id: str = self.config.get_value(CONF_USER_ID) - self._tidal_session = await self._get_tidal_session() + try: + self._tidal_session = await self._get_tidal_session() + except Exception as err: + if "401 Client Error: Unauthorized" in str(err): + self.mass.config.set_raw_provider_config_value( + self.instance_id, CONF_AUTH_TOKEN, None + ) + self.mass.config.set_raw_provider_config_value( + self.instance_id, CONF_REFRESH_TOKEN, None + ) + raise LoginFailed("Credentials, expired, you need to re-setup") + raise @property def supported_features(self) -> tuple[ProviderFeature, ...]: