mirror of
https://github.com/tcsenpai/swingmusic.git
synced 2025-06-07 03:35:35 +00:00
add route to get all tracks in path
+ add routes to save album and artist as a playlist
This commit is contained in:
parent
efb6aae927
commit
655fd8bc22
@ -83,7 +83,7 @@ def get_album_tracks_and_info():
|
|||||||
album.is_favorite = check_is_fav(albumhash, FavType.album)
|
album.is_favorite = check_is_fav(albumhash, FavType.album)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"tracks": [track_serializer(t, retain_disc=True) for t in tracks],
|
"tracks": [track_serializer(t, remove_disc=False) for t in tracks],
|
||||||
"info": album,
|
"info": album,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -210,3 +210,5 @@ def get_similar_albums():
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
return {"albums": [serialize_for_card(a) for a in albums[:limit]]}
|
return {"albums": [serialize_for_card(a) for a in albums[:limit]]}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,22 +1,21 @@
|
|||||||
"""
|
"""
|
||||||
Contains all the artist(s) routes.
|
Contains all the artist(s) routes.
|
||||||
"""
|
"""
|
||||||
from collections import deque
|
|
||||||
import random
|
import random
|
||||||
|
from collections import deque
|
||||||
|
|
||||||
from flask import Blueprint, request
|
from flask import Blueprint, request
|
||||||
|
|
||||||
from app.db.sqlite.favorite import SQLiteFavoriteMethods as favdb
|
from app.db.sqlite.favorite import SQLiteFavoriteMethods as favdb
|
||||||
from app.db.sqlite.lastfm.similar_artists import SQLiteLastFMSimilarArtists as fmdb
|
from app.db.sqlite.lastfm.similar_artists import \
|
||||||
|
SQLiteLastFMSimilarArtists as fmdb
|
||||||
from app.models import Album, FavType, Track
|
from app.models import Album, FavType, Track
|
||||||
from app.serializers.album import serialize_for_card_many
|
from app.serializers.album import serialize_for_card_many
|
||||||
from app.serializers.track import serialize_tracks
|
from app.serializers.track import serialize_tracks
|
||||||
from app.utils.remove_duplicates import remove_duplicates
|
|
||||||
|
|
||||||
from app.store.albums import AlbumStore
|
from app.store.albums import AlbumStore
|
||||||
from app.store.tracks import TrackStore
|
|
||||||
from app.store.artists import ArtistStore
|
from app.store.artists import ArtistStore
|
||||||
|
from app.store.tracks import TrackStore
|
||||||
|
from app.utils.remove_duplicates import remove_duplicates
|
||||||
|
|
||||||
api = Blueprint("artist", __name__, url_prefix="/")
|
api = Blueprint("artist", __name__, url_prefix="/")
|
||||||
|
|
||||||
@ -159,7 +158,7 @@ def add_albums_to_cache(artisthash: str):
|
|||||||
"""
|
"""
|
||||||
Fetches albums and adds them to the cache.
|
Fetches albums and adds them to the cache.
|
||||||
"""
|
"""
|
||||||
tracks = TrackStore.get_tracks_by_artist(artisthash)
|
tracks = TrackStore.get_tracks_by_artisthash(artisthash)
|
||||||
|
|
||||||
if len(tracks) == 0:
|
if len(tracks) == 0:
|
||||||
return False
|
return False
|
||||||
@ -197,7 +196,7 @@ def get_artist(artisthash: str):
|
|||||||
if tracks_cached:
|
if tracks_cached:
|
||||||
tracks = ArtistsCache.get_tracks(artisthash)
|
tracks = ArtistsCache.get_tracks(artisthash)
|
||||||
else:
|
else:
|
||||||
tracks = TrackStore.get_tracks_by_artist(artisthash)
|
tracks = TrackStore.get_tracks_by_artisthash(artisthash)
|
||||||
albumhashes = set(t.albumhash for t in tracks)
|
albumhashes = set(t.albumhash for t in tracks)
|
||||||
hashes_from_albums = set(
|
hashes_from_albums = set(
|
||||||
a.albumhash for a in AlbumStore.get_albums_by_artisthash(artisthash)
|
a.albumhash for a in AlbumStore.get_albums_by_artisthash(artisthash)
|
||||||
@ -291,7 +290,7 @@ def get_all_artist_tracks(artisthash: str):
|
|||||||
"""
|
"""
|
||||||
Returns all artists by a given artist.
|
Returns all artists by a given artist.
|
||||||
"""
|
"""
|
||||||
tracks = TrackStore.get_tracks_by_artist(artisthash)
|
tracks = TrackStore.get_tracks_by_artisthash(artisthash)
|
||||||
|
|
||||||
return {"tracks": serialize_tracks(tracks)}
|
return {"tracks": serialize_tracks(tracks)}
|
||||||
|
|
||||||
|
@ -2,16 +2,18 @@
|
|||||||
Contains all the folder routes.
|
Contains all the folder routes.
|
||||||
"""
|
"""
|
||||||
import os
|
import os
|
||||||
import psutil
|
|
||||||
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
|
import psutil
|
||||||
from flask import Blueprint, request
|
from flask import Blueprint, request
|
||||||
from showinfm import show_in_file_manager
|
from showinfm import show_in_file_manager
|
||||||
|
|
||||||
from app import settings
|
from app import settings
|
||||||
from app.lib.folderslib import GetFilesAndDirs, get_folders
|
|
||||||
from app.db.sqlite.settings import SettingsSQLMethods as db
|
from app.db.sqlite.settings import SettingsSQLMethods as db
|
||||||
from app.utils.wintools import win_replace_slash, is_windows
|
from app.lib.folderslib import GetFilesAndDirs, get_folders
|
||||||
|
from app.serializers.track import track_serializer
|
||||||
|
from app.store.tracks import TrackStore as store
|
||||||
|
from app.utils.wintools import is_windows, win_replace_slash
|
||||||
|
|
||||||
api = Blueprint("folder", __name__, url_prefix="")
|
api = Blueprint("folder", __name__, url_prefix="")
|
||||||
|
|
||||||
@ -129,3 +131,19 @@ def open_in_file_manager():
|
|||||||
show_in_file_manager(path)
|
show_in_file_manager(path)
|
||||||
|
|
||||||
return {"success": True}
|
return {"success": True}
|
||||||
|
|
||||||
|
|
||||||
|
@api.route("/folder/tracks/all")
|
||||||
|
def get_tracks_in_path():
|
||||||
|
path = request.args.get("path")
|
||||||
|
|
||||||
|
if path is None:
|
||||||
|
return {"error": "No path provided."}, 400
|
||||||
|
|
||||||
|
tracks = store.get_tracks_in_path(path)
|
||||||
|
tracks = sorted(tracks, key=lambda i: i.last_mod)
|
||||||
|
tracks = (track_serializer(t) for t in tracks if Path(t.filepath).exists())
|
||||||
|
|
||||||
|
return {
|
||||||
|
"tracks": list(tracks)[:300],
|
||||||
|
}
|
||||||
|
@ -135,6 +135,31 @@ def create_playlist():
|
|||||||
return {"playlist": playlist}, 201
|
return {"playlist": playlist}, 201
|
||||||
|
|
||||||
|
|
||||||
|
def get_path_trackhashes(path: str):
|
||||||
|
"""
|
||||||
|
Returns a list of trackhashes in a folder.
|
||||||
|
"""
|
||||||
|
tracks = TrackStore.get_tracks_in_path(path)
|
||||||
|
tracks = sorted(tracks, key=lambda t: t.last_mod)
|
||||||
|
return [t.trackhash for t in tracks]
|
||||||
|
|
||||||
|
|
||||||
|
def get_album_trackhashes(albumhash: str):
|
||||||
|
"""
|
||||||
|
Returns a list of trackhashes in an album.
|
||||||
|
"""
|
||||||
|
tracks = TrackStore.get_tracks_by_albumhash(albumhash)
|
||||||
|
return [t.trackhash for t in tracks]
|
||||||
|
|
||||||
|
|
||||||
|
def get_artist_trackhashes(artisthash: str):
|
||||||
|
"""
|
||||||
|
Returns a list of trackhashes for an artist.
|
||||||
|
"""
|
||||||
|
tracks = TrackStore.get_tracks_by_artisthash(artisthash)
|
||||||
|
return [t.trackhash for t in tracks]
|
||||||
|
|
||||||
|
|
||||||
@api.route("/playlist/<playlist_id>/add", methods=["POST"])
|
@api.route("/playlist/<playlist_id>/add", methods=["POST"])
|
||||||
def add_track_to_playlist(playlist_id: str):
|
def add_track_to_playlist(playlist_id: str):
|
||||||
"""
|
"""
|
||||||
@ -145,9 +170,28 @@ def add_track_to_playlist(playlist_id: str):
|
|||||||
if data is None:
|
if data is None:
|
||||||
return {"error": "Track hash not provided"}, 400
|
return {"error": "Track hash not provided"}, 400
|
||||||
|
|
||||||
trackhash = data["track"]
|
try:
|
||||||
|
itemtype = data["itemtype"]
|
||||||
|
except KeyError:
|
||||||
|
itemtype = None
|
||||||
|
|
||||||
insert_count = tracks_to_playlist(int(playlist_id), [trackhash])
|
try:
|
||||||
|
itemhash = data["itemhash"]
|
||||||
|
except KeyError:
|
||||||
|
itemhash = None
|
||||||
|
|
||||||
|
if itemtype == "track":
|
||||||
|
trackhashes = [itemhash]
|
||||||
|
elif itemtype == "folder":
|
||||||
|
trackhashes = get_path_trackhashes(itemhash)
|
||||||
|
elif itemtype == "album":
|
||||||
|
trackhashes = get_album_trackhashes(itemhash)
|
||||||
|
elif itemtype == "artist":
|
||||||
|
trackhashes = get_artist_trackhashes(itemhash)
|
||||||
|
else:
|
||||||
|
trackhashes = []
|
||||||
|
|
||||||
|
insert_count = tracks_to_playlist(int(playlist_id), trackhashes)
|
||||||
|
|
||||||
if insert_count == 0:
|
if insert_count == 0:
|
||||||
return {"error": "Track already exists in playlist"}, 409
|
return {"error": "Track already exists in playlist"}, 409
|
||||||
@ -328,6 +372,10 @@ def remove_tracks_from_playlist(pid: int):
|
|||||||
return {"msg": "Done"}, 200
|
return {"msg": "Done"}, 200
|
||||||
|
|
||||||
|
|
||||||
|
def playlist_exists(name: str) -> bool:
|
||||||
|
return count_playlist_by_name(name) > 0
|
||||||
|
|
||||||
|
|
||||||
@api.route("/playlist/save-folder", methods=["POST"])
|
@api.route("/playlist/save-folder", methods=["POST"])
|
||||||
def save_folder_as_folder():
|
def save_folder_as_folder():
|
||||||
data = request.get_json()
|
data = request.get_json()
|
||||||
@ -342,17 +390,10 @@ def save_folder_as_folder():
|
|||||||
if path is None or name is None:
|
if path is None or name is None:
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
p_count = count_playlist_by_name(name)
|
if playlist_exists(name):
|
||||||
|
|
||||||
if p_count > 0:
|
|
||||||
return {"error": "Playlist already exists"}, 409
|
return {"error": "Playlist already exists"}, 409
|
||||||
|
|
||||||
tracks = TrackStore.get_tracks_in_path(path)
|
trackhashes = get_path_trackhashes(path)
|
||||||
|
|
||||||
# sort tracks by last_mod
|
|
||||||
tracks = sorted(tracks, key=lambda t: t.last_mod)
|
|
||||||
trackhashes = [t.trackhash for t in tracks]
|
|
||||||
|
|
||||||
if len(trackhashes) == 0:
|
if len(trackhashes) == 0:
|
||||||
return {"error": "No tracks found in folder"}, 404
|
return {"error": "No tracks found in folder"}, 404
|
||||||
|
|
||||||
@ -365,3 +406,67 @@ def save_folder_as_folder():
|
|||||||
PL.update_last_updated(playlist.id)
|
PL.update_last_updated(playlist.id)
|
||||||
|
|
||||||
return {"playlist_id": playlist.id}, 201
|
return {"playlist_id": playlist.id}, 201
|
||||||
|
|
||||||
|
|
||||||
|
@api.route("/playlist/save-album", methods=["POST"])
|
||||||
|
def save_album_as_playlist():
|
||||||
|
data = request.get_json()
|
||||||
|
msg = {"error": "'albumhash' and 'playlist_name' not provided"}, 400
|
||||||
|
|
||||||
|
if data is None:
|
||||||
|
return msg
|
||||||
|
|
||||||
|
albumhash = data.get("albumhash")
|
||||||
|
name = data.get("playlist_name")
|
||||||
|
|
||||||
|
if albumhash is None or name is None:
|
||||||
|
return msg
|
||||||
|
|
||||||
|
if playlist_exists(name):
|
||||||
|
return {"error": "Playlist already exists"}, 409
|
||||||
|
|
||||||
|
trackhashes = get_album_trackhashes(albumhash)
|
||||||
|
if len(trackhashes) == 0:
|
||||||
|
return {"error": "No tracks found in album"}, 404
|
||||||
|
|
||||||
|
playlist = insert_playlist(name)
|
||||||
|
|
||||||
|
if playlist is None:
|
||||||
|
return {"error": "Playlist could not be created"}, 500
|
||||||
|
|
||||||
|
tracks_to_playlist(playlist.id, trackhashes)
|
||||||
|
PL.update_last_updated(playlist.id)
|
||||||
|
|
||||||
|
return {"playlist_id": playlist.id}, 201
|
||||||
|
|
||||||
|
|
||||||
|
@api.route("/playlist/save-artist", methods=["POST"])
|
||||||
|
def save_artist_as_playlist():
|
||||||
|
data = request.get_json()
|
||||||
|
msg = {"error": "'artisthash' and 'playlist_name' not provided"}, 400
|
||||||
|
|
||||||
|
if data is None:
|
||||||
|
return msg
|
||||||
|
|
||||||
|
artisthash = data.get("artisthash")
|
||||||
|
name = data.get("playlist_name")
|
||||||
|
|
||||||
|
if artisthash is None or name is None:
|
||||||
|
return msg
|
||||||
|
|
||||||
|
if playlist_exists(name):
|
||||||
|
return {"error": "Playlist already exists"}, 409
|
||||||
|
|
||||||
|
trackhashes = get_artist_trackhashes(artisthash)
|
||||||
|
if len(trackhashes) == 0:
|
||||||
|
return {"error": "No tracks found in artist"}, 404
|
||||||
|
|
||||||
|
playlist = insert_playlist(name)
|
||||||
|
|
||||||
|
if playlist is None:
|
||||||
|
return {"error": "Playlist could not be created"}, 500
|
||||||
|
|
||||||
|
tracks_to_playlist(playlist.id, trackhashes)
|
||||||
|
PL.update_last_updated(playlist.id)
|
||||||
|
|
||||||
|
return {"playlist_id": playlist.id}, 201
|
||||||
|
@ -96,8 +96,7 @@ class SQLitePlaylistMethods:
|
|||||||
def add_item_to_json_list(playlist_id: int, field: str, items: set[str]):
|
def add_item_to_json_list(playlist_id: int, field: str, items: set[str]):
|
||||||
"""
|
"""
|
||||||
Adds a string item to a json dumped list using a playlist id and field name.
|
Adds a string item to a json dumped list using a playlist id and field name.
|
||||||
Takes the playlist ID, a field name,
|
Takes the playlist ID, a field name, an item to add to the field.
|
||||||
an item to add to the field, and an error to raise if the item is already in the field.
|
|
||||||
"""
|
"""
|
||||||
sql = f"SELECT {field} FROM playlists WHERE id = ?"
|
sql = f"SELECT {field} FROM playlists WHERE id = ?"
|
||||||
|
|
||||||
@ -121,6 +120,9 @@ class SQLitePlaylistMethods:
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def add_tracks_to_playlist(cls, playlist_id: int, trackhashes: list[str]):
|
def add_tracks_to_playlist(cls, playlist_id: int, trackhashes: list[str]):
|
||||||
|
"""
|
||||||
|
Adds trackhashes to a playlist
|
||||||
|
"""
|
||||||
return cls.add_item_to_json_list(playlist_id, "trackhashes", trackhashes)
|
return cls.add_item_to_json_list(playlist_id, "trackhashes", trackhashes)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
@ -1,30 +1,35 @@
|
|||||||
from dataclasses import asdict
|
from dataclasses import asdict
|
||||||
|
|
||||||
from app.models.track import Track
|
from app.models.track import Track
|
||||||
|
|
||||||
|
|
||||||
def track_serializer(track: Track, _remove: set = {}, retain_disc=False) -> dict:
|
def track_serializer(track: Track, to_remove: set = {}, remove_disc=True) -> dict:
|
||||||
album_dict = asdict(track)
|
album_dict = asdict(track)
|
||||||
to_remove = {
|
props = {
|
||||||
"date",
|
"date",
|
||||||
"genre",
|
"genre",
|
||||||
"last_mod",
|
"last_mod",
|
||||||
"og_title",
|
"og_title",
|
||||||
"og_album",
|
"og_album",
|
||||||
}.union(_remove)
|
"copyright",
|
||||||
|
"disc",
|
||||||
|
"track",
|
||||||
|
}.union(to_remove)
|
||||||
|
|
||||||
if not retain_disc:
|
if not remove_disc:
|
||||||
to_remove.union("disc", "track")
|
props.remove("disc")
|
||||||
|
props.remove("track")
|
||||||
|
|
||||||
to_remove.update(key for key in album_dict.keys() if key.startswith("is_"))
|
props.update(key for key in album_dict.keys() if key.startswith("is_"))
|
||||||
to_remove.remove('is_favorite')
|
props.remove("is_favorite")
|
||||||
|
|
||||||
for key in to_remove:
|
for key in props:
|
||||||
album_dict.pop(key, None)
|
album_dict.pop(key, None)
|
||||||
|
|
||||||
return album_dict
|
return album_dict
|
||||||
|
|
||||||
|
|
||||||
def serialize_tracks(
|
def serialize_tracks(
|
||||||
tracks: list[Track], _remove: set = {}, retain_disc=False
|
tracks: list[Track], _remove: set = {}, remove_disc=True
|
||||||
) -> list[dict]:
|
) -> list[dict]:
|
||||||
return [track_serializer(t, _remove, retain_disc) for t in tracks]
|
return [track_serializer(t, _remove, remove_disc) for t in tracks]
|
||||||
|
@ -160,7 +160,7 @@ class TrackStore:
|
|||||||
return remove_duplicates(tracks)
|
return remove_duplicates(tracks)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_tracks_by_artist(cls, artisthash: str) -> list[Track]:
|
def get_tracks_by_artisthash(cls, artisthash: str) -> list[Track]:
|
||||||
"""
|
"""
|
||||||
Returns all tracks matching the given artist. Duplicate tracks are removed.
|
Returns all tracks matching the given artist. Duplicate tracks are removed.
|
||||||
"""
|
"""
|
||||||
|
Loading…
x
Reference in New Issue
Block a user