Allow use of a personal client id for Spotify (#1536)
authorMarcel van der Veldt <m.vanderveldt@outlook.com>
Tue, 30 Jul 2024 10:04:57 +0000 (12:04 +0200)
committerGitHub <noreply@github.com>
Tue, 30 Jul 2024 10:04:57 +0000 (12:04 +0200)
music_assistant/common/models/config_entries.py
music_assistant/server/providers/spotify/__init__.py

index e6a62ba48da864e416db7ddb3585325fc711eede..cd86921c23773b0b698be10dde588e135d492401 100644 (file)
@@ -187,7 +187,7 @@ class Config(DataClassDictMixin):
     def get_value(self, key: str) -> ConfigValueType:
         """Return config value for given key."""
         config_value = self.values[key]
-        if config_value.type == ConfigEntryType.SECURE_STRING:
+        if config_value.type == ConfigEntryType.SECURE_STRING and config_value.value:
             assert isinstance(config_value.value, str)
             assert DECRYPT_CALLBACK is not None
             return DECRYPT_CALLBACK(config_value.value)
index a2fcbf8fc5131a78e21302c8f501df81db64d36f..be7e6ebe7f794b648814dbedd45fd44ba699f794 100644 (file)
@@ -61,6 +61,7 @@ if TYPE_CHECKING:
     from music_assistant.server import MusicAssistant
     from music_assistant.server.models import ProviderInstanceType
 
+CONF_CLIENT_ID = "client_id"
 
 CACHE_DIR = gettempdir()
 LIKED_SONGS_FAKE_PLAYLIST_ID_PREFIX = "liked_songs"
@@ -118,6 +119,15 @@ async def get_config_entries(
             label="Password",
             required=True,
         ),
+        ConfigEntry(
+            key=CONF_CLIENT_ID,
+            type=ConfigEntryType.SECURE_STRING,
+            label="Client ID",
+            description="By default, a generic client ID is used which is heavy rate limited. "
+            "It is advised that you create your own Spotify Developer account and use "
+            "that client ID here to speedup performance.",
+            required=False,
+        ),
     )
 
 
@@ -135,8 +145,11 @@ class SpotifyProvider(MusicProvider):
         """Handle async initialization of the provider."""
         self._cache_dir = CACHE_DIR
         self._ap_workaround = False
-        # try to get a token, raise if that fails
         self._cache_dir = os.path.join(CACHE_DIR, self.instance_id)
+        if self.config.get_value(CONF_CLIENT_ID):
+            # loosen the throttler a bit when a custom client id is used
+            self.throttler.rate_limit = 45
+            self.throttler.period = 30
         # try login which will raise if it fails
         await self.login()
 
@@ -726,7 +739,7 @@ class SpotifyProvider(MusicProvider):
             "-O",
             "-t",
             "--client-id",
-            app_var(2),
+            self.config.get_value(CONF_CLIENT_ID) or app_var(2),
             "--scope",
             scope,
             "-c",