from __future__ import annotations
import logging
-from typing import TYPE_CHECKING
+from typing import TYPE_CHECKING, cast
from music_assistant_models.config_entries import (
Config,
ConfigEntry,
+ ConfigValueOption,
ConfigValueType,
)
from music_assistant_models.enums import ConfigEntryType
from music_assistant_models.event import MassEvent
from music_assistant_models.playback_progress_report import MediaItemPlaybackProgressReport
+ from music_assistant import MusicAssistant
+
class ScrobblerHelper:
"""Base class to aid scrobbling tracks."""
report: MediaItemPlaybackProgressReport = event.data
+ # handle optional user_id filtering
+ if self.config.mass_userids and report.userid not in self.config.mass_userids:
+ self.logger.debug("skipped scrobbling for user %s due to user filter", report.userid)
+ return
+
# poor mans attempt to detect a song on loop
if not report.fully_played and report.uri == self.last_scrobbled:
self.logger.debug(
CONF_VERSION_SUFFIX = "suffix_version"
+CONF_SCROBBLE_USERS = "scrobble_users"
class ScrobblerConfig:
"""Shared configuration options for scrobblers."""
- def __init__(self, suffix_version: bool) -> None:
+ def __init__(self, suffix_version: bool, mass_userids: list[str] | None = None) -> None:
"""Initialize."""
self.suffix_version = suffix_version
+ self.mass_userids = mass_userids or []
@staticmethod
def get_shared_config_entries(values: dict[str, ConfigValueType] | None) -> list[ConfigEntry]:
@staticmethod
def create_from_config(config: Config) -> ScrobblerConfig:
"""Extract relevant shared config values."""
- return ScrobblerConfig(bool(config.get_value(CONF_VERSION_SUFFIX, True)))
+ return ScrobblerConfig(
+ suffix_version=bool(config.get_value(CONF_VERSION_SUFFIX, True)),
+ mass_userids=cast("list[str]", config.get_value(CONF_SCROBBLE_USERS, [])),
+ )
+
+
+async def create_scrobble_users_config_entry(mass: MusicAssistant) -> ConfigEntry:
+ """Create a reusable configentry to specify a userlist for scrobbling providers."""
+ # User options for scrobble filtering
+ ma_user_list = await mass.webserver.auth.list_users() # excludes system users
+ ma_user_list = [user for user in ma_user_list if user.enabled]
+ user_options = [
+ ConfigValueOption(title=user.display_name or user.username, value=user.user_id)
+ for user in ma_user_list
+ ]
+ return ConfigEntry(
+ key=CONF_SCROBBLE_USERS,
+ type=ConfigEntryType.STRING,
+ label="Scrobble for users",
+ required=False,
+ description="Only register scrobbles for the selected users. "
+ "Leave empty to scrobble for all users.",
+ options=user_options,
+ multi_value=True,
+ default_value=[],
+ )
from music_assistant.constants import MASS_LOGGER_NAME
from music_assistant.helpers.auth import AuthenticationHelper
-from music_assistant.helpers.scrobbler import ScrobblerConfig, ScrobblerHelper
+from music_assistant.helpers.scrobbler import (
+ ScrobblerConfig,
+ ScrobblerHelper,
+ create_scrobble_users_config_entry,
+)
from music_assistant.mass import MusicAssistant
from music_assistant.models import ProviderInstanceType
from music_assistant.models.plugin import PluginProvider
required=True,
value=values.get(CONF_API_SECRET) if values else None,
),
+ # add user selection entry
+ await create_scrobble_users_config_entry(mass),
]
# early return so we can assume values are present
from music_assistant_models.playback_progress_report import MediaItemPlaybackProgressReport
from music_assistant_models.provider import ProviderManifest
-from music_assistant.helpers.scrobbler import ScrobblerConfig, ScrobblerHelper
+from music_assistant.helpers.scrobbler import (
+ ScrobblerConfig,
+ ScrobblerHelper,
+ create_scrobble_users_config_entry,
+)
from music_assistant.mass import MusicAssistant
from music_assistant.models import ProviderInstanceType
from music_assistant.models.plugin import PluginProvider
async def get_config_entries(
- mass: MusicAssistant, # noqa: ARG001
+ mass: MusicAssistant,
instance_id: str | None = None, # noqa: ARG001
action: str | None = None, # noqa: ARG001
values: dict[str, ConfigValueType] | None = None,
required=True,
value=values.get(CONF_USER_TOKEN) if values else None,
),
+ # add user selection entry
+ await create_scrobble_users_config_entry(mass),
)