Skip to content

Commit

Permalink
Merge pull request #51 from CalPinSW/pull-playlist-information-from-db
Browse files Browse the repository at this point in the history
Pull playlist information from db
  • Loading branch information
CalPinSW authored Sep 16, 2024
2 parents 2dc0a74 + ab498af commit 8393945
Show file tree
Hide file tree
Showing 42 changed files with 1,036 additions and 433 deletions.
2 changes: 2 additions & 0 deletions backend/src/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from flask_cors import CORS
from src.controllers.database import database_controller
from src.controllers.spotify import spotify_controller
from src.controllers.music_data import music_controller
from src.exceptions.Unauthorized import UnauthorizedException
from src.flask_config import Config
from src.musicbrainz import MusicbrainzClient
Expand Down Expand Up @@ -48,6 +49,7 @@ def handle_unauthorized_exception(_):

app.register_blueprint(auth_controller(spotify=spotify))
app.register_blueprint(spotify_controller(spotify=spotify))
app.register_blueprint(music_controller(spotify=spotify))
app.register_blueprint(
database_controller(spotify=spotify, musicbrainz=musicbrainz)
)
Expand Down
68 changes: 13 additions & 55 deletions backend/src/controllers/database.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,8 @@
from src.database.crud.genre import create_genre
from src.database.crud.playlist import (
create_playlist,
get_playlist_albums,
delete_playlist,
get_playlist_by_id_or_none,
get_user_playlists,
update_playlist,
)
from src.database.crud.user import get_or_create_user
from src.musicbrainz import MusicbrainzClient
Expand All @@ -30,60 +28,24 @@ def database_controller(spotify: SpotifyClient, musicbrainz: MusicbrainzClient):
def populate_user():
access_token = request.cookies.get("spotify_access_token")
user = spotify.get_current_user(access_token)
(db_user, _) = get_or_create_user(user)
simplified_playlists = spotify.get_all_playlists(
user_id=user.id, access_token=access_token
)
(db_user,) = get_or_create_user(user)

for simplified_playlist in simplified_playlists:
if "Albums" in simplified_playlist.name:
db_playlist = get_playlist_by_id_or_none(simplified_playlist.id)

if db_playlist is None:
[playlist, albums] = [
spotify.get_playlist(
access_token=access_token, id=simplified_playlist.id
),
spotify.get_playlist_album_info(
access_token=access_token, id=simplified_playlist.id
),
]
create_playlist(playlist, albums, db_user)
else:
if db_playlist.snapshot_id != simplified_playlist.snapshot_id:
[playlist, albums] = [
spotify.get_playlist(
access_token=access_token, id=simplified_playlist.id
),
spotify.get_playlist_album_info(
access_token=access_token, id=simplified_playlist.id
),
]
update_playlist(playlist, albums)

return make_response("Playlist data populated", 201)

@database_controller.route(
"populate_additional_album_details_from_playlist", methods=["GET"]
)
def populate_additional_album_details_from_playlist():
access_token = request.cookies.get("spotify_access_token")
user = spotify.get_current_user(access_token)
playlists = get_user_playlists(user.id)

for playlist in playlists:
albums = get_playlist_albums(playlist.id)
if albums == []:
continue
batch_albums = split_list(albums, 20)
for album_chunk in batch_albums:
sleep(0.5)
albums = spotify.get_multiple_albums(
access_token=access_token, ids=[album.id for album in album_chunk]
)
for db_album in albums:
album = spotify.get_album(access_token=access_token, id=db_album.id)
update_album(album)
if (
db_playlist is None
or db_playlist.snapshot_id != simplified_playlist.snapshot_id
):
if db_playlist is not None:
delete_playlist(db_playlist.id)
playlist = spotify.get_playlist(
access_token=access_token, id=simplified_playlist.id
)
create_playlist(playlist, db_user)

return make_response("Playlist data populated", 201)

Expand All @@ -92,12 +54,8 @@ def populate_additional_album_details():
access_token = request.cookies.get("spotify_access_token")
user = spotify.get_current_user(access_token)
albums = get_user_albums(user.id)
albums_without_label = [album for album in albums] # if album.label is None]
if albums_without_label == []:
return make_response("No Albums to process", 204)
batch_albums = split_list(albums_without_label, 20)
batch_albums = split_list(albums, 20)
for album_chunk in batch_albums:
sleep(0.5)
albums = spotify.get_multiple_albums(
access_token=access_token, ids=[album.id for album in album_chunk]
)
Expand Down
142 changes: 142 additions & 0 deletions backend/src/controllers/music_data.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
from flask import Blueprint, jsonify, make_response, request
from src.database.crud.playlist import (
get_playlist_albums_with_genres,
get_playlist_by_id_or_none,
get_playlist_duration,
get_playlist_duration_up_to_track,
get_playlist_track_list,
get_recent_user_playlists,
get_user_playlists,
search_playlist_names,
update_playlist_info,
)
from src.dataclasses.playlist import Playlist
from src.spotify import SpotifyClient


def music_controller(spotify: SpotifyClient):
music_controller = Blueprint(
name="music_controller", import_name=__name__, url_prefix="/music"
)

@music_controller.route("playlists")
def index():
user_id = request.cookies.get("user_id")
limit = request.args.get("limit", type=int)
offset = request.args.get("offset", type=int)
search = request.args.get("search")
sort_by = request.args.get("sort_by")
desc = request.args.get("desc") == "True"
return jsonify(
get_user_playlists(
user_id=user_id,
limit=limit,
offset=offset,
search=search,
sort_by=sort_by,
desc=desc,
as_dicts=True,
)
)

@music_controller.route("playlists/recent")
def recent_playlists():
user_id = request.cookies.get("user_id")
limit = request.args.get("limit", type=int)
offset = request.args.get("offset", type=int)
search = request.args.get("search")

return jsonify(
get_recent_user_playlists(
user_id=user_id, limit=limit, offset=offset, search=search
)
)

@music_controller.route("playlist/<id>", methods=["GET"])
def get_playlist(id):
db_playlist = get_playlist_by_id_or_none(id)
if db_playlist is not None:
return db_playlist.__data__
else:
access_token = request.cookies.get("spotify_access_token")
playlist = spotify.get_playlist(access_token=access_token, id=id)
return playlist.model_dump()

@music_controller.route("playlist/<id>", methods=["POST"])
def post_edit_playlist(id):
access_token = request.cookies.get("spotify_access_token")
name = request.json.get("name")
description = request.json.get("description")
update_playlist_info(id=id, name=name, description=description)
spotify.update_playlist(
access_token=access_token,
id=id,
name=name,
description=description,
)
return make_response("playlist updated", 204)

@music_controller.route("playlist/<id>/albums", methods=["GET"])
def get_playlist_album_info(id):
db_playlist = get_playlist_by_id_or_none(id)
if db_playlist is not None:
album_info_list = get_playlist_albums_with_genres(id)
return jsonify(album_info_list)
else:
access_token = request.cookies.get("spotify_access_token")
return [
album.model_dump()
for album in spotify.get_playlist_album_info(
access_token=access_token, id=id
)
]

@music_controller.route("playlist/<id>/tracks", methods=["GET"])
def get_playlist_tracks(id):
db_playlist = get_playlist_by_id_or_none(id)
if db_playlist is not None:
track_list = get_playlist_track_list(id)
return jsonify(track_list)
else:
access_token = request.cookies.get("spotify_access_token")
return [
album.model_dump()
for album in spotify.get_playlist_album_info(
access_token=access_token, id=id
)
]

@music_controller.route("playlist/search", methods=["POST"])
def find_associated_playlists():
user_id = request.cookies.get("user_id")
search = request.json
return search_playlist_names(user_id, search)

@music_controller.route("playback", methods=["GET"])
def get_playback_info():
access_token = request.cookies.get("spotify_access_token")
playback_info = spotify.get_my_current_playback(access_token=access_token)
if playback_info is None:
return ("", 204)
if playback_info.playlist_id is not None:
playlist_name = get_playlist_by_id_or_none(playback_info.playlist_id).name
playlist_duration = get_playlist_duration(playback_info.playlist_id)
playlist_progress = (
get_playlist_duration_up_to_track(
playback_info.playlist_id, playback_info.track_id
)
+ playback_info.track_progress
)

playback_info_with_playlist = playback_info.model_dump()
playback_info_with_playlist["playlist"] = {
"id": playback_info.playlist_id,
"title": playlist_name,
"progress": playlist_progress,
"duration": playlist_duration,
}
return playback_info_with_playlist

return playback_info.model_dump_json()

return music_controller
12 changes: 4 additions & 8 deletions backend/src/controllers/spotify.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
from logging import Logger
from flask import Blueprint, make_response, request
from src.dataclasses.playback_info import PlaybackInfo
from src.dataclasses.playback_request import StartPlaybackRequest
from src.dataclasses.playlist import Playlist
from src.spotify import SpotifyClient
import sys


def spotify_controller(spotify: SpotifyClient):
Expand Down Expand Up @@ -53,7 +50,7 @@ def delete_playlist_by_id(id):
spotify.delete_playlist(access_token=access_token, id=id)
return make_response("playlist deleted", 200)

@spotify_controller.route("edit-playlist/<id>", methods=["GET"])
@spotify_controller.route("playlist/<id>", methods=["GET"])
def get_edit_playlist(id):
access_token = request.cookies.get("spotify_access_token")
playlist = spotify.get_playlist(access_token=access_token, id=id)
Expand Down Expand Up @@ -101,13 +98,12 @@ def get_playlist_progress():
return ("", 204)
return playlist_progression.model_dump_json()

@spotify_controller.route("find_associated_playlists", methods=["POST"])
def find_associated_playlists():
@spotify_controller.route("find_associated_playlists/<id>", methods=["GET"])
def find_associated_playlists(playlist_id):
access_token = request.cookies.get("spotify_access_token")
user_id = request.cookies.get("user_id")
playlist = Playlist.model_validate(request.json)
associated_playlists = spotify.find_associated_playlists(
user_id=user_id, access_token=access_token, playlist=playlist
user_id=user_id, access_token=access_token, playlist_id=playlist_id
)
return [
associated_playlist.model_dump()
Expand Down
12 changes: 8 additions & 4 deletions backend/src/database/crud/album.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from typing import List
from src.database.crud.artist import create_or_update_artist
from src.database.crud.track import create_track_or_none
from src.dataclasses.album import Album
from src.database.models import (
AlbumArtistRelationship,
Expand All @@ -12,10 +13,10 @@
)


def create_album_or_none(album: Album):
def create_album_or_none(album: Album, ignore_tracks=False):
if DbAlbum.get_or_none(DbAlbum.id == album.id):
return
album = DbAlbum.create(
db_album = DbAlbum.create(
id=album.id,
album_type=album.album_type,
total_tracks=album.total_tracks,
Expand All @@ -26,12 +27,15 @@ def create_album_or_none(album: Album):
label=album.label,
uri=album.uri,
)
for artist in album.artists:
for artist in db_album.artists:
create_or_update_artist(artist)
AlbumArtistRelationship.create(album=album.id, artist=artist.id)
for genre in album.genres or []:
for genre in db_album.genres or []:
db_genre = DbGenre.get_or_create(name=genre)
AlbumGenreRelationship.create(album=album.id, genre=db_genre.id)
if not ignore_tracks:
for track in album.tracks:
create_track_or_none(track, album)

return album

Expand Down
Loading

0 comments on commit 8393945

Please sign in to comment.