Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for brand accounts #421

Merged
merged 1 commit into from
Jul 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 19 additions & 8 deletions music_assistant/music_providers/ytmusic/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,12 @@ def _get_song():
return await loop.run_in_executor(None, _get_song)


async def get_library_artists(headers: Dict[str, str]) -> Dict[str, str]:
async def get_library_artists(headers: Dict[str, str], username: str) -> Dict[str, str]:
"""Async wrapper around the ytmusicapi get_library_artists function."""

def _get_library_artists():
ytm = ytmusicapi.YTMusic(auth=json.dumps(headers))
user = username if is_brand_account(username) else None
ytm = ytmusicapi.YTMusic(auth=json.dumps(headers), user=user)
artists = ytm.get_library_artists(limit=9999)
# Sync properties with uniformal artist object
for artist in artists:
Expand All @@ -101,22 +102,26 @@ def _get_library_artists():
return await loop.run_in_executor(None, _get_library_artists)


async def get_library_albums(headers: Dict[str, str]) -> Dict[str, str]:
async def get_library_albums(headers: Dict[str, str], username: str) -> Dict[str, str]:
"""Async wrapper around the ytmusicapi get_library_albums function."""

def _get_library_albums():
ytm = ytmusicapi.YTMusic(auth=json.dumps(headers))
user = username if is_brand_account(username) else None
ytm = ytmusicapi.YTMusic(auth=json.dumps(headers), user=user)
return ytm.get_library_albums(limit=9999)

loop = asyncio.get_running_loop()
return await loop.run_in_executor(None, _get_library_albums)


async def get_library_playlists(headers: Dict[str, str]) -> Dict[str, str]:
async def get_library_playlists(
headers: Dict[str, str], username: str
) -> Dict[str, str]:
"""Async wrapper around the ytmusicapi get_library_playlists function."""

def _get_library_playlists():
ytm = ytmusicapi.YTMusic(auth=json.dumps(headers))
user = username if is_brand_account(username) else None
ytm = ytmusicapi.YTMusic(auth=json.dumps(headers), user=user)
playlists = ytm.get_library_playlists(limit=9999)
# Sync properties with uniformal playlist object
for playlist in playlists:
Expand All @@ -129,11 +134,12 @@ def _get_library_playlists():
return await loop.run_in_executor(None, _get_library_playlists)


async def get_library_tracks(headers: Dict[str, str]) -> Dict[str, str]:
async def get_library_tracks(headers: Dict[str, str], username: str) -> Dict[str, str]:
"""Async wrapper around the ytmusicapi get_library_tracks function."""

def _get_library_tracks():
ytm = ytmusicapi.YTMusic(auth=json.dumps(headers))
user = username if is_brand_account(username) else None
ytm = ytmusicapi.YTMusic(auth=json.dumps(headers), user=user)
tracks = ytm.get_library_songs(limit=9999)
return tracks

Expand Down Expand Up @@ -173,3 +179,8 @@ def get_playlist_checksum(playlist_obj: dict) -> str:
if key in playlist_obj:
return playlist_obj[key]
return str(int(time()))


def is_brand_account(username: str) -> bool:
"""Check if the provided username is a brand-account."""
return len(username) == 21 and username.isdigit()
16 changes: 12 additions & 4 deletions music_assistant/music_providers/ytmusic/ytmusic.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,25 +123,33 @@ async def search(

async def get_library_artists(self) -> AsyncGenerator[Artist, None]:
"""Retrieve all library artists from Youtube Music."""
artists_obj = await get_library_artists(headers=self._headers)
artists_obj = await get_library_artists(
headers=self._headers, username=self.config.username
)
for artist in artists_obj:
yield await self._parse_artist(artist)

async def get_library_albums(self) -> AsyncGenerator[Album, None]:
"""Retrieve all library albums from Youtube Music."""
albums_obj = await get_library_albums(headers=self._headers)
albums_obj = await get_library_albums(
headers=self._headers, username=self.config.username
)
for album in albums_obj:
yield await self._parse_album(album, album["browseId"])

async def get_library_playlists(self) -> AsyncGenerator[Playlist, None]:
"""Retrieve all library playlists from the provider."""
playlists_obj = await get_library_playlists(headers=self._headers)
playlists_obj = await get_library_playlists(
headers=self._headers, username=self.config.username
)
for playlist in playlists_obj:
yield await self._parse_playlist(playlist)

async def get_library_tracks(self) -> AsyncGenerator[Track, None]:
"""Retrieve library tracks from Youtube Music."""
tracks_obj = await get_library_tracks(headers=self._headers)
tracks_obj = await get_library_tracks(
headers=self._headers, username=self.config.username
)
for track in tracks_obj:
# Library tracks sometimes do not have a valid artist id
# In that case, call the API for track details based on track id
Expand Down