add route to get all tracks in path

+ add routes to save album and artist as a playlist
This commit is contained in:
mungai-njoroge 2023-08-04 13:40:48 +03:00
parent efb6aae927
commit 655fd8bc22
7 changed files with 169 additions and 38 deletions

View File

@ -83,7 +83,7 @@ def get_album_tracks_and_info():
album.is_favorite = check_is_fav(albumhash, FavType.album)
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,
}
@ -210,3 +210,5 @@ def get_similar_albums():
pass
return {"albums": [serialize_for_card(a) for a in albums[:limit]]}

View File

@ -1,22 +1,21 @@
"""
Contains all the artist(s) routes.
"""
from collections import deque
import random
from collections import deque
from flask import Blueprint, request
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.serializers.album import serialize_for_card_many
from app.serializers.track import serialize_tracks
from app.utils.remove_duplicates import remove_duplicates
from app.store.albums import AlbumStore
from app.store.tracks import TrackStore
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="/")
@ -159,7 +158,7 @@ def add_albums_to_cache(artisthash: str):
"""
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:
return False
@ -197,7 +196,7 @@ def get_artist(artisthash: str):
if tracks_cached:
tracks = ArtistsCache.get_tracks(artisthash)
else:
tracks = TrackStore.get_tracks_by_artist(artisthash)
tracks = TrackStore.get_tracks_by_artisthash(artisthash)
albumhashes = set(t.albumhash for t in tracks)
hashes_from_albums = set(
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.
"""
tracks = TrackStore.get_tracks_by_artist(artisthash)
tracks = TrackStore.get_tracks_by_artisthash(artisthash)
return {"tracks": serialize_tracks(tracks)}

View File

@ -2,16 +2,18 @@
Contains all the folder routes.
"""
import os
import psutil
from pathlib import Path
import psutil
from flask import Blueprint, request
from showinfm import show_in_file_manager
from app import settings
from app.lib.folderslib import GetFilesAndDirs, get_folders
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="")
@ -129,3 +131,19 @@ def open_in_file_manager():
show_in_file_manager(path)
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],
}

View File

@ -135,6 +135,31 @@ def create_playlist():
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"])
def add_track_to_playlist(playlist_id: str):
"""
@ -145,9 +170,28 @@ def add_track_to_playlist(playlist_id: str):
if data is None:
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:
return {"error": "Track already exists in playlist"}, 409
@ -328,6 +372,10 @@ def remove_tracks_from_playlist(pid: int):
return {"msg": "Done"}, 200
def playlist_exists(name: str) -> bool:
return count_playlist_by_name(name) > 0
@api.route("/playlist/save-folder", methods=["POST"])
def save_folder_as_folder():
data = request.get_json()
@ -342,17 +390,10 @@ def save_folder_as_folder():
if path is None or name is None:
return msg
p_count = count_playlist_by_name(name)
if p_count > 0:
if playlist_exists(name):
return {"error": "Playlist already exists"}, 409
tracks = TrackStore.get_tracks_in_path(path)
# sort tracks by last_mod
tracks = sorted(tracks, key=lambda t: t.last_mod)
trackhashes = [t.trackhash for t in tracks]
trackhashes = get_path_trackhashes(path)
if len(trackhashes) == 0:
return {"error": "No tracks found in folder"}, 404
@ -365,3 +406,67 @@ def save_folder_as_folder():
PL.update_last_updated(playlist.id)
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

View File

@ -96,8 +96,7 @@ class SQLitePlaylistMethods:
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.
Takes the playlist ID, a field name,
an item to add to the field, and an error to raise if the item is already in the field.
Takes the playlist ID, a field name, an item to add to the field.
"""
sql = f"SELECT {field} FROM playlists WHERE id = ?"
@ -121,6 +120,9 @@ class SQLitePlaylistMethods:
@classmethod
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)
@staticmethod

View File

@ -1,30 +1,35 @@
from dataclasses import asdict
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)
to_remove = {
props = {
"date",
"genre",
"last_mod",
"og_title",
"og_album",
}.union(_remove)
"copyright",
"disc",
"track",
}.union(to_remove)
if not retain_disc:
to_remove.union("disc", "track")
if not remove_disc:
props.remove("disc")
props.remove("track")
to_remove.update(key for key in album_dict.keys() if key.startswith("is_"))
to_remove.remove('is_favorite')
props.update(key for key in album_dict.keys() if key.startswith("is_"))
props.remove("is_favorite")
for key in to_remove:
for key in props:
album_dict.pop(key, None)
return album_dict
def serialize_tracks(
tracks: list[Track], _remove: set = {}, retain_disc=False
tracks: list[Track], _remove: set = {}, remove_disc=True
) -> list[dict]:
return [track_serializer(t, _remove, retain_disc) for t in tracks]
return [track_serializer(t, _remove, remove_disc) for t in tracks]

View File

@ -160,7 +160,7 @@ class TrackStore:
return remove_duplicates(tracks)
@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.
"""