Skip to content

Commit 310d57c

Browse files
committed
Simplify playlist population scripts
1 parent 9e59584 commit 310d57c

File tree

10 files changed

+101
-211
lines changed

10 files changed

+101
-211
lines changed

backend/src/controllers/database.py

Lines changed: 18 additions & 132 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,10 @@
88
update_album,
99
)
1010
from src.database.crud.genre import create_genre
11-
from src.database.crud.track import (
12-
all_tracks_have_artists,
13-
create_track_or_none,
14-
get_album_tracks,
15-
get_user_albums_with_no_tracks,
16-
)
1711
from src.database.crud.playlist import (
18-
add_playlist_album_index,
1912
create_playlist,
20-
get_playlist_albums,
13+
delete_playlist,
2114
get_playlist_by_id_or_none,
22-
get_user_playlists,
23-
playlist_has_null_album_indexes,
24-
update_playlist_with_albums,
2515
)
2616
from src.database.crud.user import get_or_create_user
2717
from src.musicbrainz import MusicbrainzClient
@@ -38,60 +28,28 @@ def database_controller(spotify: SpotifyClient, musicbrainz: MusicbrainzClient):
3828
def populate_user():
3929
access_token = request.cookies.get("spotify_access_token")
4030
user = spotify.get_current_user(access_token)
31+
(db_user, _) = get_or_create_user(user)
4132
simplified_playlists = spotify.get_all_playlists(
4233
user_id=user.id, access_token=access_token
4334
)
44-
(db_user,) = get_or_create_user(user)
4535

4636
for simplified_playlist in simplified_playlists:
47-
if "Albums" in simplified_playlist.name:
37+
if (
38+
"Albums" in simplified_playlist.name
39+
and "New Albums 06/09/24" in simplified_playlist.name
40+
):
41+
delete_playlist("0ubqg4akSDebHReJIG8sbd")
4842
db_playlist = get_playlist_by_id_or_none(simplified_playlist.id)
49-
50-
if db_playlist is None:
51-
[playlist, albums] = [
52-
spotify.get_playlist(
53-
access_token=access_token, id=simplified_playlist.id
54-
),
55-
spotify.get_playlist_album_info(
56-
access_token=access_token, id=simplified_playlist.id
57-
),
58-
]
59-
create_playlist(playlist, albums, db_user)
60-
else:
61-
if db_playlist.snapshot_id != simplified_playlist.snapshot_id:
62-
[playlist, albums] = [
63-
spotify.get_playlist(
64-
access_token=access_token, id=simplified_playlist.id
65-
),
66-
spotify.get_playlist_album_info(
67-
access_token=access_token, id=simplified_playlist.id
68-
),
69-
]
70-
update_playlist_with_albums(playlist, albums)
71-
72-
return make_response("Playlist data populated", 201)
73-
74-
@database_controller.route(
75-
"populate_additional_album_details_from_playlist", methods=["GET"]
76-
)
77-
def populate_additional_album_details_from_playlist():
78-
access_token = request.cookies.get("spotify_access_token")
79-
user = spotify.get_current_user(access_token)
80-
playlists = get_user_playlists(user.id)
81-
82-
for playlist in playlists:
83-
albums = get_playlist_albums(playlist.id)
84-
if albums == []:
85-
continue
86-
batch_albums = split_list(albums, 20)
87-
for album_chunk in batch_albums:
88-
sleep(0.5)
89-
albums = spotify.get_multiple_albums(
90-
access_token=access_token, ids=[album.id for album in album_chunk]
91-
)
92-
for db_album in albums:
93-
album = spotify.get_album(access_token=access_token, id=db_album.id)
94-
update_album(album)
43+
if (
44+
db_playlist is None
45+
or db_playlist.snapshot_id != simplified_playlist.snapshot_id
46+
):
47+
if db_playlist is not None:
48+
delete_playlist(db_playlist.id)
49+
playlist = spotify.get_playlist(
50+
access_token=access_token, id=simplified_playlist.id
51+
)
52+
create_playlist(playlist, db_user)
9553

9654
return make_response("Playlist data populated", 201)
9755

@@ -100,12 +58,8 @@ def populate_additional_album_details():
10058
access_token = request.cookies.get("spotify_access_token")
10159
user = spotify.get_current_user(access_token)
10260
albums = get_user_albums(user.id)
103-
albums_without_label = [album for album in albums] # if album.label is None]
104-
if albums_without_label == []:
105-
return make_response("No Albums to process", 204)
106-
batch_albums = split_list(albums_without_label, 20)
61+
batch_albums = split_list(albums, 20)
10762
for album_chunk in batch_albums:
108-
sleep(0.5)
10963
albums = spotify.get_multiple_albums(
11064
access_token=access_token, ids=[album.id for album in album_chunk]
11165
)
@@ -130,74 +84,6 @@ def populate_user_album_genres():
13084
populate_album_genres_by_user_id(user.id, musicbrainz)
13185
return make_response("User album genres populated", 201)
13286

133-
@database_controller.route("populate_album_tracks", methods=["GET"])
134-
def populate_album_tracks():
135-
access_token = request.cookies.get("spotify_access_token")
136-
user = spotify.get_current_user(access_token)
137-
albums = get_user_albums_with_no_tracks(user.id)
138-
for album in albums:
139-
existing_album_tracks = get_album_tracks(album)
140-
if existing_album_tracks != []:
141-
continue
142-
sleep(0.5)
143-
144-
album_tracks = spotify.get_album(
145-
access_token=access_token, id=album.id
146-
).tracks.items
147-
for track in album_tracks:
148-
create_track_or_none(track, album)
149-
150-
return make_response("User album genres populated", 201)
151-
152-
@database_controller.route("populate_playlist_album_indexes", methods=["GET"])
153-
def populate_playlist_album_indexes():
154-
access_token = request.cookies.get("spotify_access_token")
155-
user = spotify.get_current_user(access_token)
156-
simplified_playlists = spotify.get_all_playlists(
157-
user_id=user.id, access_token=access_token
158-
)
159-
160-
for simplified_playlist in simplified_playlists:
161-
if "Albums" in simplified_playlist.name:
162-
if not playlist_has_null_album_indexes(simplified_playlist.id):
163-
continue
164-
sleep(1)
165-
166-
[playlist, albums] = [
167-
spotify.get_playlist(
168-
access_token=access_token, id=simplified_playlist.id
169-
),
170-
spotify.get_playlist_album_info(
171-
access_token=access_token, id=simplified_playlist.id
172-
),
173-
]
174-
175-
for index, album in enumerate(albums):
176-
add_playlist_album_index(
177-
playlist_id=playlist.id, album_id=album.id, index=index
178-
)
179-
180-
return make_response("Playlist album indexes populated", 201)
181-
182-
@database_controller.route("populate_track_artists", methods=["GET"])
183-
def populate_track_artists():
184-
access_token = request.cookies.get("spotify_access_token")
185-
user = spotify.get_current_user(access_token)
186-
albums = get_user_albums(user.id)
187-
offset = 1800
188-
for index, album in enumerate(albums[offset:]):
189-
if all_tracks_have_artists(album.id):
190-
continue
191-
sleep(0.5)
192-
print(index + offset)
193-
album_tracks = spotify.get_album(
194-
access_token=access_token, id=album.id
195-
).tracks.items
196-
for track in album_tracks:
197-
create_track_or_none(track, album)
198-
199-
return make_response("User album genres populated", 201)
200-
20187
return database_controller
20288

20389

backend/src/controllers/music_data.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ def find_associated_playlists():
125125
associated_playlist.model_dump()
126126
for associated_playlist in associated_playlists
127127
]
128-
128+
129129
@music_controller.route("playback", methods=["GET"])
130130
def get_playback_info():
131131
access_token = request.cookies.get("spotify_access_token")
@@ -134,16 +134,21 @@ def get_playback_info():
134134
return ("", 204)
135135
if playback_info.playlist_id is not None:
136136
playlist_duration = get_playlist_duration(playback_info.playlist_id)
137-
playlist_progress = get_playlist_duration_up_to_track(playback_info.playlist_id, playback_info.track_id) + playback_info.track_progress
137+
playlist_progress = (
138+
get_playlist_duration_up_to_track(
139+
playback_info.playlist_id, playback_info.track_id
140+
)
141+
+ playback_info.track_progress
142+
)
138143
return PlaylistProgression.model_validate(
139144
{
140145
"playlist_id": playback_info.playlist_id,
141-
"playlist_title": playback_info.name,
146+
"playlist_title": "test",
142147
"playlist_progress": playlist_progress,
143148
"playlist_duration": playlist_duration,
144149
}
145150
)
146-
151+
147152
return playback_info.model_dump_json()
148153

149154
return music_controller

backend/src/controllers/spotify.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
1-
from logging import Logger
21
from flask import Blueprint, make_response, request
32
from src.dataclasses.playback_info import PlaybackInfo
43
from src.dataclasses.playback_request import StartPlaybackRequest
5-
from src.dataclasses.playlist import Playlist
64
from src.spotify import SpotifyClient
7-
import sys
85

96

107
def spotify_controller(spotify: SpotifyClient):

backend/src/database/crud/album.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from typing import List
22
from src.database.crud.artist import create_or_update_artist
3+
from src.database.crud.track import create_track_or_none
34
from src.dataclasses.album import Album
45
from src.database.models import (
56
AlbumArtistRelationship,
@@ -12,10 +13,10 @@
1213
)
1314

1415

15-
def create_album_or_none(album: Album):
16+
def create_album_or_none(album: Album, ignore_tracks=False):
1617
if DbAlbum.get_or_none(DbAlbum.id == album.id):
1718
return
18-
album = DbAlbum.create(
19+
db_album = DbAlbum.create(
1920
id=album.id,
2021
album_type=album.album_type,
2122
total_tracks=album.total_tracks,
@@ -26,12 +27,15 @@ def create_album_or_none(album: Album):
2627
label=album.label,
2728
uri=album.uri,
2829
)
29-
for artist in album.artists:
30+
for artist in db_album.artists:
3031
create_or_update_artist(artist)
3132
AlbumArtistRelationship.create(album=album.id, artist=artist.id)
32-
for genre in album.genres or []:
33+
for genre in db_album.genres or []:
3334
db_genre = DbGenre.get_or_create(name=genre)
3435
AlbumGenreRelationship.create(album=album.id, genre=db_genre.id)
36+
if not ignore_tracks:
37+
for track in album.tracks:
38+
create_track_or_none(track, album)
3539

3640
return album
3741

backend/src/database/crud/playlist.py

Lines changed: 33 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from typing import List, Optional
22
from src.database.crud.album import create_album_or_none
3+
from src.database.crud.track import create_track_or_none
34
from src.database.models import (
45
AlbumArtistRelationship,
56
AlbumGenreRelationship,
@@ -22,8 +23,8 @@ def get_playlist_by_id_or_none(id: str):
2223
return DbPlaylist.get_or_none(DbPlaylist.id == id)
2324

2425

25-
def create_playlist(playlist: Playlist, albums: List[Album], user: DbUser):
26-
playlist = DbPlaylist.create(
26+
def create_playlist(playlist: Playlist, user: DbUser):
27+
db_playlist = DbPlaylist.create(
2728
id=playlist.id,
2829
description=playlist.description,
2930
image_url=playlist.images[0].url if playlist.images else None,
@@ -33,11 +34,25 @@ def create_playlist(playlist: Playlist, albums: List[Album], user: DbUser):
3334
uri=playlist.uri,
3435
)
3536

36-
for album in albums:
37-
create_album_or_none(album)
38-
PlaylistAlbumRelationship.create(playlist=playlist.id, album=album.id)
39-
40-
return playlist
37+
album_index = 0
38+
for track in playlist.tracks.items:
39+
create_album_or_none(track.track.album, ignore_tracks=True)
40+
if PlaylistAlbumRelationship.get_or_create(
41+
playlist=playlist.id,
42+
album=track.track.album.id,
43+
defaults={"album_index": album_index},
44+
)[1]:
45+
album_index += 1
46+
create_track_or_none(track.track)
47+
return db_playlist
48+
49+
50+
def delete_playlist(playlist_id: str):
51+
query = PlaylistAlbumRelationship.delete().where(
52+
PlaylistAlbumRelationship.playlist == playlist_id
53+
)
54+
query.execute()
55+
DbPlaylist.delete_by_id(playlist_id)
4156

4257

4358
def update_playlist_info(
@@ -67,25 +82,6 @@ def update_playlist_info(
6782
return None
6883

6984

70-
def update_playlist_with_albums(playlist: Playlist, albums: List[Album]):
71-
playlist = DbPlaylist.update(
72-
id=playlist.id,
73-
description=playlist.description,
74-
image_url=playlist.images[0].url if playlist.images else None,
75-
name=playlist.name,
76-
user_id=playlist.owner.id,
77-
snapshot_id=playlist.snapshot_id,
78-
uri=playlist.uri,
79-
)
80-
PlaylistAlbumRelationship.delete().where(playlist=playlist.id)
81-
82-
for album in albums:
83-
create_album_or_none(album)
84-
PlaylistAlbumRelationship.create(playlist=playlist.id, album=album.id)
85-
86-
return playlist
87-
88-
8985
def get_user_playlists(
9086
user_id: str,
9187
limit: Optional[int] = None,
@@ -304,18 +300,18 @@ def get_playlist_duration(playlist_id):
304300

305301

306302
def get_playlist_duration_up_to_track(playlist_id, track_id):
307-
# Subquery to get albums in the playlist ordered by album_index
308-
albums_in_playlist = (
309-
PlaylistAlbumRelationship.select(PlaylistAlbumRelationship.album)
310-
.where(PlaylistAlbumRelationship.playlist == playlist_id)
311-
.order_by(PlaylistAlbumRelationship.album_index)
312-
)
313-
314-
# Query to get all tracks in those albums, ordered by album_index, disc_number, and track_number
303+
print(playlist_id)
304+
# Query to get all tracks in the albums of the playlist, with proper joins and ordering
315305
tracks_in_playlist = (
316306
DbTrack.select(DbTrack.id, DbTrack.duration_ms)
317-
.join(DbAlbum)
318-
.where(DbTrack.album.in_(albums_in_playlist))
307+
.join(DbAlbum, on=(DbTrack.album == DbAlbum.id)) # Join track with album
308+
.join(
309+
PlaylistAlbumRelationship,
310+
on=(DbTrack.album == PlaylistAlbumRelationship.album),
311+
) # Join to get album_index
312+
.where(
313+
PlaylistAlbumRelationship.playlist == playlist_id
314+
) # Ensure we're only querying tracks in the specific playlist
319315
.order_by(
320316
PlaylistAlbumRelationship.album_index,
321317
DbTrack.disc_number,
@@ -331,5 +327,5 @@ def get_playlist_duration_up_to_track(playlist_id, track_id):
331327
total_duration += track.duration_ms
332328
if track.id == track_id:
333329
break
334-
330+
print(total_duration)
335331
return total_duration

0 commit comments

Comments
 (0)