Skip to content

Commit 8393945

Browse files
authored
Merge pull request #51 from CalPinSW/pull-playlist-information-from-db
Pull playlist information from db
2 parents 2dc0a74 + ab498af commit 8393945

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+1036
-433
lines changed

backend/src/app.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from flask_cors import CORS
33
from src.controllers.database import database_controller
44
from src.controllers.spotify import spotify_controller
5+
from src.controllers.music_data import music_controller
56
from src.exceptions.Unauthorized import UnauthorizedException
67
from src.flask_config import Config
78
from src.musicbrainz import MusicbrainzClient
@@ -48,6 +49,7 @@ def handle_unauthorized_exception(_):
4849

4950
app.register_blueprint(auth_controller(spotify=spotify))
5051
app.register_blueprint(spotify_controller(spotify=spotify))
52+
app.register_blueprint(music_controller(spotify=spotify))
5153
app.register_blueprint(
5254
database_controller(spotify=spotify, musicbrainz=musicbrainz)
5355
)

backend/src/controllers/database.py

Lines changed: 13 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,8 @@
1010
from src.database.crud.genre import create_genre
1111
from src.database.crud.playlist import (
1212
create_playlist,
13-
get_playlist_albums,
13+
delete_playlist,
1414
get_playlist_by_id_or_none,
15-
get_user_playlists,
16-
update_playlist,
1715
)
1816
from src.database.crud.user import get_or_create_user
1917
from src.musicbrainz import MusicbrainzClient
@@ -30,60 +28,24 @@ def database_controller(spotify: SpotifyClient, musicbrainz: MusicbrainzClient):
3028
def populate_user():
3129
access_token = request.cookies.get("spotify_access_token")
3230
user = spotify.get_current_user(access_token)
31+
(db_user, _) = get_or_create_user(user)
3332
simplified_playlists = spotify.get_all_playlists(
3433
user_id=user.id, access_token=access_token
3534
)
36-
(db_user,) = get_or_create_user(user)
3735

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

8850
return make_response("Playlist data populated", 201)
8951

@@ -92,12 +54,8 @@ def populate_additional_album_details():
9254
access_token = request.cookies.get("spotify_access_token")
9355
user = spotify.get_current_user(access_token)
9456
albums = get_user_albums(user.id)
95-
albums_without_label = [album for album in albums] # if album.label is None]
96-
if albums_without_label == []:
97-
return make_response("No Albums to process", 204)
98-
batch_albums = split_list(albums_without_label, 20)
57+
batch_albums = split_list(albums, 20)
9958
for album_chunk in batch_albums:
100-
sleep(0.5)
10159
albums = spotify.get_multiple_albums(
10260
access_token=access_token, ids=[album.id for album in album_chunk]
10361
)
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
from flask import Blueprint, jsonify, make_response, request
2+
from src.database.crud.playlist import (
3+
get_playlist_albums_with_genres,
4+
get_playlist_by_id_or_none,
5+
get_playlist_duration,
6+
get_playlist_duration_up_to_track,
7+
get_playlist_track_list,
8+
get_recent_user_playlists,
9+
get_user_playlists,
10+
search_playlist_names,
11+
update_playlist_info,
12+
)
13+
from src.dataclasses.playlist import Playlist
14+
from src.spotify import SpotifyClient
15+
16+
17+
def music_controller(spotify: SpotifyClient):
18+
music_controller = Blueprint(
19+
name="music_controller", import_name=__name__, url_prefix="/music"
20+
)
21+
22+
@music_controller.route("playlists")
23+
def index():
24+
user_id = request.cookies.get("user_id")
25+
limit = request.args.get("limit", type=int)
26+
offset = request.args.get("offset", type=int)
27+
search = request.args.get("search")
28+
sort_by = request.args.get("sort_by")
29+
desc = request.args.get("desc") == "True"
30+
return jsonify(
31+
get_user_playlists(
32+
user_id=user_id,
33+
limit=limit,
34+
offset=offset,
35+
search=search,
36+
sort_by=sort_by,
37+
desc=desc,
38+
as_dicts=True,
39+
)
40+
)
41+
42+
@music_controller.route("playlists/recent")
43+
def recent_playlists():
44+
user_id = request.cookies.get("user_id")
45+
limit = request.args.get("limit", type=int)
46+
offset = request.args.get("offset", type=int)
47+
search = request.args.get("search")
48+
49+
return jsonify(
50+
get_recent_user_playlists(
51+
user_id=user_id, limit=limit, offset=offset, search=search
52+
)
53+
)
54+
55+
@music_controller.route("playlist/<id>", methods=["GET"])
56+
def get_playlist(id):
57+
db_playlist = get_playlist_by_id_or_none(id)
58+
if db_playlist is not None:
59+
return db_playlist.__data__
60+
else:
61+
access_token = request.cookies.get("spotify_access_token")
62+
playlist = spotify.get_playlist(access_token=access_token, id=id)
63+
return playlist.model_dump()
64+
65+
@music_controller.route("playlist/<id>", methods=["POST"])
66+
def post_edit_playlist(id):
67+
access_token = request.cookies.get("spotify_access_token")
68+
name = request.json.get("name")
69+
description = request.json.get("description")
70+
update_playlist_info(id=id, name=name, description=description)
71+
spotify.update_playlist(
72+
access_token=access_token,
73+
id=id,
74+
name=name,
75+
description=description,
76+
)
77+
return make_response("playlist updated", 204)
78+
79+
@music_controller.route("playlist/<id>/albums", methods=["GET"])
80+
def get_playlist_album_info(id):
81+
db_playlist = get_playlist_by_id_or_none(id)
82+
if db_playlist is not None:
83+
album_info_list = get_playlist_albums_with_genres(id)
84+
return jsonify(album_info_list)
85+
else:
86+
access_token = request.cookies.get("spotify_access_token")
87+
return [
88+
album.model_dump()
89+
for album in spotify.get_playlist_album_info(
90+
access_token=access_token, id=id
91+
)
92+
]
93+
94+
@music_controller.route("playlist/<id>/tracks", methods=["GET"])
95+
def get_playlist_tracks(id):
96+
db_playlist = get_playlist_by_id_or_none(id)
97+
if db_playlist is not None:
98+
track_list = get_playlist_track_list(id)
99+
return jsonify(track_list)
100+
else:
101+
access_token = request.cookies.get("spotify_access_token")
102+
return [
103+
album.model_dump()
104+
for album in spotify.get_playlist_album_info(
105+
access_token=access_token, id=id
106+
)
107+
]
108+
109+
@music_controller.route("playlist/search", methods=["POST"])
110+
def find_associated_playlists():
111+
user_id = request.cookies.get("user_id")
112+
search = request.json
113+
return search_playlist_names(user_id, search)
114+
115+
@music_controller.route("playback", methods=["GET"])
116+
def get_playback_info():
117+
access_token = request.cookies.get("spotify_access_token")
118+
playback_info = spotify.get_my_current_playback(access_token=access_token)
119+
if playback_info is None:
120+
return ("", 204)
121+
if playback_info.playlist_id is not None:
122+
playlist_name = get_playlist_by_id_or_none(playback_info.playlist_id).name
123+
playlist_duration = get_playlist_duration(playback_info.playlist_id)
124+
playlist_progress = (
125+
get_playlist_duration_up_to_track(
126+
playback_info.playlist_id, playback_info.track_id
127+
)
128+
+ playback_info.track_progress
129+
)
130+
131+
playback_info_with_playlist = playback_info.model_dump()
132+
playback_info_with_playlist["playlist"] = {
133+
"id": playback_info.playlist_id,
134+
"title": playlist_name,
135+
"progress": playlist_progress,
136+
"duration": playlist_duration,
137+
}
138+
return playback_info_with_playlist
139+
140+
return playback_info.model_dump_json()
141+
142+
return music_controller

backend/src/controllers/spotify.py

Lines changed: 4 additions & 8 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):
@@ -53,7 +50,7 @@ def delete_playlist_by_id(id):
5350
spotify.delete_playlist(access_token=access_token, id=id)
5451
return make_response("playlist deleted", 200)
5552

56-
@spotify_controller.route("edit-playlist/<id>", methods=["GET"])
53+
@spotify_controller.route("playlist/<id>", methods=["GET"])
5754
def get_edit_playlist(id):
5855
access_token = request.cookies.get("spotify_access_token")
5956
playlist = spotify.get_playlist(access_token=access_token, id=id)
@@ -101,13 +98,12 @@ def get_playlist_progress():
10198
return ("", 204)
10299
return playlist_progression.model_dump_json()
103100

104-
@spotify_controller.route("find_associated_playlists", methods=["POST"])
105-
def find_associated_playlists():
101+
@spotify_controller.route("find_associated_playlists/<id>", methods=["GET"])
102+
def find_associated_playlists(playlist_id):
106103
access_token = request.cookies.get("spotify_access_token")
107104
user_id = request.cookies.get("user_id")
108-
playlist = Playlist.model_validate(request.json)
109105
associated_playlists = spotify.find_associated_playlists(
110-
user_id=user_id, access_token=access_token, playlist=playlist
106+
user_id=user_id, access_token=access_token, playlist_id=playlist_id
111107
)
112108
return [
113109
associated_playlist.model_dump()

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

0 commit comments

Comments
 (0)