Skip to content

Commit

Permalink
Fix Spotify token gets invalidated every hour (#1575)
Browse files Browse the repository at this point in the history
  • Loading branch information
marcelveldt authored Aug 18, 2024
1 parent 8cf33e6 commit a4b41d1
Show file tree
Hide file tree
Showing 26 changed files with 106 additions and 155 deletions.
24 changes: 12 additions & 12 deletions music_assistant/server/controllers/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,11 @@
ProviderConfig,
)
from music_assistant.common.models.enums import EventType, PlayerState, ProviderType
from music_assistant.common.models.errors import InvalidDataError, PlayerUnavailableError
from music_assistant.common.models.errors import (
InvalidDataError,
PlayerUnavailableError,
ProviderUnavailableError,
)
from music_assistant.constants import (
CONF_CORE,
CONF_PLAYERS,
Expand Down Expand Up @@ -300,16 +304,6 @@ async def remove_provider_config_value(self, instance_id: str, key: str) -> None
return
self.remove(conf_key)

async def set_provider_config_value(
self, instance_id: str, key: str, value: ConfigValueType
) -> None:
"""Set single ProviderConfig value."""
config = await self.get_provider_config(instance_id)
config.update({key: value})
config.validate()
conf_key = f"{CONF_PROVIDERS}/{config.instance_id}"
self.set(conf_key, config.to_raw())

@api_command("config/players")
async def get_player_configs(
self, provider: str | None = None, include_values: bool = False
Expand Down Expand Up @@ -609,7 +603,7 @@ def get_raw_provider_config_value(
)

def set_raw_provider_config_value(
self, provider_instance: str, key: str, value: ConfigValueType
self, provider_instance: str, key: str, value: ConfigValueType, encrypted: bool = False
) -> None:
"""
Set (raw) single config(entry) value for a provider.
Expand All @@ -620,6 +614,12 @@ def set_raw_provider_config_value(
# only allow setting raw values if main entry exists
msg = f"Invalid provider_instance: {provider_instance}"
raise KeyError(msg)
if encrypted:
value = self.encrypt_string(value)
# also update the cached value in the provider itself
if not (prov := self.mass.get_provider(provider_instance, return_unavailable=True)):
raise ProviderUnavailableError(provider_instance)
prov.config.values[key].value = value
self.set(f"{CONF_PROVIDERS}/{provider_instance}/values/{key}", value)

def set_raw_core_config_value(self, core_module: str, key: str, value: ConfigValueType) -> None:
Expand Down
3 changes: 3 additions & 0 deletions music_assistant/server/models/provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ def lookup_key(self) -> str:
# should not be overridden in normal circumstances
return self.instance_id if self.manifest.multi_instance else self.domain

async def handle_async_init(self) -> None:
"""Handle async initialization of the provider."""

async def loaded_in_mass(self) -> None:
"""Call after the provider has been loaded."""

Expand Down
4 changes: 1 addition & 3 deletions music_assistant/server/providers/airplay/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,9 +131,7 @@ async def setup(
mass: MusicAssistant, manifest: ProviderManifest, config: ProviderConfig
) -> ProviderInstanceType:
"""Initialize provider(instance) with given configuration."""
prov = AirplayProvider(mass, manifest, config)
await prov.handle_async_init()
return prov
return AirplayProvider(mass, manifest, config)


async def get_config_entries(
Expand Down
4 changes: 1 addition & 3 deletions music_assistant/server/providers/apple_music/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,7 @@ async def setup(
mass: MusicAssistant, manifest: ProviderManifest, config: ProviderConfig
) -> ProviderInstanceType:
"""Initialize provider(instance) with given configuration."""
prov = AppleMusicProvider(mass, manifest, config)
await prov.handle_async_init()
return prov
return AppleMusicProvider(mass, manifest, config)


async def get_config_entries(
Expand Down
2 changes: 1 addition & 1 deletion music_assistant/server/providers/builtin/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,7 @@ async def library_remove(self, prov_item_id: str, media_type: MediaType) -> bool
if media_type == MediaType.PLAYLIST and prov_item_id in BUILTIN_PLAYLISTS:
# user wants to disable/remove one of our builtin playlists
# to prevent it comes back, we mark it as disabled in config
await self.mass.config.set_provider_config_value(self.instance_id, prov_item_id, False)
self.mass.config.set_raw_provider_config_value(self.instance_id, prov_item_id, False)
return True
if media_type == MediaType.TRACK:
# regular manual track URL/path
Expand Down
4 changes: 1 addition & 3 deletions music_assistant/server/providers/deezer/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,9 +123,7 @@ async def setup(
mass: MusicAssistant, manifest: ProviderManifest, config: ProviderConfig
) -> ProviderInstanceType:
"""Initialize provider(instance) with given configuration."""
prov = DeezerProvider(mass, manifest, config)
await prov.handle_async_init()
return prov
return DeezerProvider(mass, manifest, config)


async def get_config_entries(
Expand Down
4 changes: 1 addition & 3 deletions music_assistant/server/providers/dlna/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,9 +94,7 @@ async def setup(
mass: MusicAssistant, manifest: ProviderManifest, config: ProviderConfig
) -> ProviderInstanceType:
"""Initialize provider(instance) with given configuration."""
prov = DLNAPlayerProvider(mass, manifest, config)
await prov.handle_async_init()
return prov
return DLNAPlayerProvider(mass, manifest, config)


async def get_config_entries(
Expand Down
4 changes: 1 addition & 3 deletions music_assistant/server/providers/fanarttv/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,7 @@ async def setup(
mass: MusicAssistant, manifest: ProviderManifest, config: ProviderConfig
) -> ProviderInstanceType:
"""Initialize provider(instance) with given configuration."""
prov = FanartTvMetadataProvider(mass, manifest, config)
await prov.handle_async_init()
return prov
return FanartTvMetadataProvider(mass, manifest, config)


async def get_config_entries(
Expand Down
7 changes: 3 additions & 4 deletions music_assistant/server/providers/filesystem_smb/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,7 @@ async def setup(
if not share or "/" in share or "\\" in share:
msg = "Invalid share name"
raise LoginFailed(msg)
prov = SMBFileSystemProvider(mass, manifest, config)
await prov.handle_async_init()
await prov.check_write_access()
return prov
return SMBFileSystemProvider(mass, manifest, config)


async def get_config_entries(
Expand Down Expand Up @@ -152,6 +149,8 @@ async def handle_async_init(self) -> None:
msg = f"Connection failed for the given details: {err}"
raise LoginFailed(msg) from err

await self.check_write_access()

async def unload(self) -> None:
"""
Handle unload/close of the provider.
Expand Down
4 changes: 1 addition & 3 deletions music_assistant/server/providers/fully_kiosk/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,7 @@ async def setup(
mass: MusicAssistant, manifest: ProviderManifest, config: ProviderConfig
) -> ProviderInstanceType:
"""Initialize provider(instance) with given configuration."""
prov = FullyKioskProvider(mass, manifest, config)
await prov.handle_async_init()
return prov
return FullyKioskProvider(mass, manifest, config)


async def get_config_entries(
Expand Down
4 changes: 1 addition & 3 deletions music_assistant/server/providers/hass/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,7 @@ async def setup(
mass: MusicAssistant, manifest: ProviderManifest, config: ProviderConfig
) -> ProviderInstanceType:
"""Initialize provider(instance) with given configuration."""
prov = HomeAssistant(mass, manifest, config)
await prov.handle_async_init()
return prov
return HomeAssistant(mass, manifest, config)


async def get_config_entries(
Expand Down
4 changes: 1 addition & 3 deletions music_assistant/server/providers/jellyfin/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,7 @@ async def setup(
mass: MusicAssistant, manifest: ProviderManifest, config: ProviderConfig
) -> ProviderInstanceType:
"""Initialize provider(instance) with given configuration."""
prov = JellyfinProvider(mass, manifest, config)
await prov.handle_async_init()
return prov
return JellyfinProvider(mass, manifest, config)


async def get_config_entries(
Expand Down
4 changes: 1 addition & 3 deletions music_assistant/server/providers/musicbrainz/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,7 @@ async def setup(
mass: MusicAssistant, manifest: ProviderManifest, config: ProviderConfig
) -> ProviderInstanceType:
"""Initialize provider(instance) with given configuration."""
prov = MusicbrainzProvider(mass, manifest, config)
await prov.handle_async_init()
return prov
return MusicbrainzProvider(mass, manifest, config)


async def get_config_entries(
Expand Down
4 changes: 1 addition & 3 deletions music_assistant/server/providers/plex/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,9 +99,7 @@ async def setup(
msg = "Invalid login credentials"
raise LoginFailed(msg)

prov = PlexProvider(mass, manifest, config)
await prov.handle_async_init()
return prov
return PlexProvider(mass, manifest, config)


async def get_config_entries( # noqa: PLR0915
Expand Down
4 changes: 1 addition & 3 deletions music_assistant/server/providers/qobuz/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,7 @@ async def setup(
mass: MusicAssistant, manifest: ProviderManifest, config: ProviderConfig
) -> ProviderInstanceType:
"""Initialize provider(instance) with given configuration."""
prov = QobuzProvider(mass, manifest, config)
await prov.handle_async_init()
return prov
return QobuzProvider(mass, manifest, config)


async def get_config_entries(
Expand Down
9 changes: 3 additions & 6 deletions music_assistant/server/providers/radiobrowser/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,7 @@ async def setup(
mass: MusicAssistant, manifest: ProviderManifest, config: ProviderConfig
) -> ProviderInstanceType:
"""Initialize provider(instance) with given configuration."""
prov = RadioBrowserProvider(mass, manifest, config)

await prov.handle_async_init()
return prov
return RadioBrowserProvider(mass, manifest, config)


async def get_config_entries(
Expand Down Expand Up @@ -237,7 +234,7 @@ async def library_add(self, item: MediaItemType) -> bool:
return False
self.logger.debug("Adding radio %s to stored radios", item.item_id)
stored_radios = [*stored_radios, item.item_id]
await self.mass.config.set_provider_config_value(
self.mass.config.set_raw_provider_config_value(
self.instance_id, CONF_STORED_RADIOS, stored_radios
)
return True
Expand All @@ -251,7 +248,7 @@ async def library_remove(self, prov_item_id: str, media_type: MediaType) -> bool
return False
self.logger.debug("Removing radio %s from stored radios", prov_item_id)
stored_radios = [x for x in stored_radios if x != prov_item_id]
await self.mass.config.set_provider_config_value(
self.mass.config.set_raw_provider_config_value(
self.instance_id, CONF_STORED_RADIOS, stored_radios
)
return True
Expand Down
4 changes: 1 addition & 3 deletions music_assistant/server/providers/slimproto/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,9 +141,7 @@ async def setup(
mass: MusicAssistant, manifest: ProviderManifest, config: ProviderConfig
) -> ProviderInstanceType:
"""Initialize provider(instance) with given configuration."""
prov = SlimprotoProvider(mass, manifest, config)
await prov.handle_async_init()
return prov
return SlimprotoProvider(mass, manifest, config)


async def get_config_entries(
Expand Down
4 changes: 1 addition & 3 deletions music_assistant/server/providers/snapcast/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,7 @@ async def setup(
mass: MusicAssistant, manifest: ProviderManifest, config: ProviderConfig
) -> ProviderInstanceType:
"""Initialize provider(instance) with given configuration."""
prov = SnapCastProvider(mass, manifest, config)
await prov.handle_async_init()
return prov
return SnapCastProvider(mass, manifest, config)


async def get_config_entries(
Expand Down
1 change: 0 additions & 1 deletion music_assistant/server/providers/sonos/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,6 @@ async def setup(
logging.getLogger("soco").setLevel(logging.DEBUG)
else:
logging.getLogger("soco").setLevel(prov.logger.level + 10)
await prov.handle_async_init()
return prov


Expand Down
4 changes: 1 addition & 3 deletions music_assistant/server/providers/soundcloud/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,7 @@ async def setup(
if not config.get_value(CONF_CLIENT_ID) or not config.get_value(CONF_AUTHORIZATION):
msg = "Invalid login credentials"
raise LoginFailed(msg)
prov = SoundcloudMusicProvider(mass, manifest, config)
await prov.handle_async_init()
return prov
return SoundcloudMusicProvider(mass, manifest, config)


async def get_config_entries(
Expand Down
Loading

0 comments on commit a4b41d1

Please sign in to comment.