mirror of
https://github.com/Dvorinka/swingmusic-extended.git
synced 2026-06-03 20:13:02 +00:00
handle XDG_CONFIG_HOME specification ...
+ fix bug that caused duplicate artist color entries to db + check if app is windows (prep for windows build) + remove caribou migrations lib + rename all api blueprints to "api" + unregister child directories when customizing root dirs + misc
This commit is contained in:
+11
-20
@@ -5,17 +5,8 @@ This module combines all API blueprints into a single Flask app instance.
|
||||
from flask import Flask
|
||||
from flask_cors import CORS
|
||||
|
||||
from app.api import (
|
||||
album,
|
||||
artist,
|
||||
favorites,
|
||||
folder,
|
||||
playlist,
|
||||
search,
|
||||
track,
|
||||
settings,
|
||||
imgserver,
|
||||
)
|
||||
from app.api import (album, artist, favorites, folder, imgserver, playlist,
|
||||
search, settings, track)
|
||||
|
||||
|
||||
def create_api():
|
||||
@@ -27,14 +18,14 @@ def create_api():
|
||||
|
||||
with app.app_context():
|
||||
|
||||
app.register_blueprint(album.albumbp)
|
||||
app.register_blueprint(artist.artistbp)
|
||||
app.register_blueprint(track.trackbp)
|
||||
app.register_blueprint(search.searchbp)
|
||||
app.register_blueprint(folder.folderbp)
|
||||
app.register_blueprint(playlist.playlistbp)
|
||||
app.register_blueprint(favorites.favbp)
|
||||
app.register_blueprint(imgserver.imgbp)
|
||||
app.register_blueprint(settings.settingsbp)
|
||||
app.register_blueprint(album.api)
|
||||
app.register_blueprint(artist.api)
|
||||
app.register_blueprint(track.api)
|
||||
app.register_blueprint(search.api)
|
||||
app.register_blueprint(folder.api)
|
||||
app.register_blueprint(playlist.api)
|
||||
app.register_blueprint(favorites.api)
|
||||
app.register_blueprint(imgserver.api)
|
||||
app.register_blueprint(settings.api)
|
||||
|
||||
return app
|
||||
|
||||
+4
-5
@@ -12,15 +12,14 @@ from app.db.sqlite.favorite import SQLiteFavoriteMethods as favdb
|
||||
from app.db.store import Store
|
||||
from app.models import FavType, Track
|
||||
|
||||
|
||||
get_album_by_id = adb.get_album_by_id
|
||||
get_albums_by_albumartist = adb.get_albums_by_albumartist
|
||||
check_is_fav = favdb.check_is_favorite
|
||||
|
||||
albumbp = Blueprint("album", __name__, url_prefix="")
|
||||
api = Blueprint("album", __name__, url_prefix="")
|
||||
|
||||
|
||||
@albumbp.route("/album", methods=["POST"])
|
||||
@api.route("/album", methods=["POST"])
|
||||
def get_album():
|
||||
"""Returns all the tracks in the given album."""
|
||||
|
||||
@@ -88,7 +87,7 @@ def get_album():
|
||||
return {"tracks": tracks, "info": album}
|
||||
|
||||
|
||||
@albumbp.route("/album/<albumhash>/tracks", methods=["GET"])
|
||||
@api.route("/album/<albumhash>/tracks", methods=["GET"])
|
||||
def get_album_tracks(albumhash: str):
|
||||
"""
|
||||
Returns all the tracks in the given album.
|
||||
@@ -105,7 +104,7 @@ def get_album_tracks(albumhash: str):
|
||||
return {"tracks": tracks}
|
||||
|
||||
|
||||
@albumbp.route("/album/from-artist", methods=["POST"])
|
||||
@api.route("/album/from-artist", methods=["POST"])
|
||||
def get_artist_albums():
|
||||
data = request.get_json()
|
||||
|
||||
|
||||
+5
-5
@@ -5,12 +5,12 @@ from collections import deque
|
||||
|
||||
from flask import Blueprint, request
|
||||
|
||||
from app.db.sqlite.favorite import SQLiteFavoriteMethods as favdb
|
||||
from app.db.store import Store
|
||||
from app.models import Album, FavType, Track
|
||||
from app.utils import remove_duplicates
|
||||
from app.db.sqlite.favorite import SQLiteFavoriteMethods as favdb
|
||||
|
||||
artistbp = Blueprint("artist", __name__, url_prefix="/")
|
||||
api = Blueprint("artist", __name__, url_prefix="/")
|
||||
|
||||
|
||||
class CacheEntry:
|
||||
@@ -156,7 +156,7 @@ def add_albums_to_cache(artisthash: str):
|
||||
# =======================================================
|
||||
|
||||
|
||||
@artistbp.route("/artist/<artisthash>", methods=["GET"])
|
||||
@api.route("/artist/<artisthash>", methods=["GET"])
|
||||
def get_artist(artisthash: str):
|
||||
"""
|
||||
Get artist data.
|
||||
@@ -203,7 +203,7 @@ def get_artist(artisthash: str):
|
||||
return {"artist": artist, "tracks": tracks[:limit]}
|
||||
|
||||
|
||||
@artistbp.route("/artist/<artisthash>/albums", methods=["GET"])
|
||||
@api.route("/artist/<artisthash>/albums", methods=["GET"])
|
||||
def get_artist_albums(artisthash: str):
|
||||
limit = request.args.get("limit")
|
||||
|
||||
@@ -261,7 +261,7 @@ def get_artist_albums(artisthash: str):
|
||||
}
|
||||
|
||||
|
||||
@artistbp.route("/artist/<artisthash>/tracks", methods=["GET"])
|
||||
@api.route("/artist/<artisthash>/tracks", methods=["GET"])
|
||||
def get_artist_tracks(artisthash: str):
|
||||
"""
|
||||
Returns all artists by a given artist.
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
from flask import Blueprint, request
|
||||
|
||||
from app.db.sqlite.favorite import SQLiteFavoriteMethods as favdb
|
||||
from app.db.store import Store
|
||||
from app.models import FavType
|
||||
from app.utils import UseBisection
|
||||
|
||||
favbp = Blueprint("favorite", __name__, url_prefix="/")
|
||||
api = Blueprint("favorite", __name__, url_prefix="/")
|
||||
|
||||
|
||||
def remove_none(items: list):
|
||||
return [i for i in items if i is not None]
|
||||
|
||||
|
||||
@favbp.route("/favorite/add", methods=["POST"])
|
||||
@api.route("/favorite/add", methods=["POST"])
|
||||
def add_favorite():
|
||||
"""
|
||||
Adds a favorite to the database.
|
||||
@@ -32,7 +33,7 @@ def add_favorite():
|
||||
return {"msg": "Added to favorites"}
|
||||
|
||||
|
||||
@favbp.route("/favorite/remove", methods=["POST"])
|
||||
@api.route("/favorite/remove", methods=["POST"])
|
||||
def remove_favorite():
|
||||
"""
|
||||
Removes a favorite from the database.
|
||||
@@ -53,7 +54,7 @@ def remove_favorite():
|
||||
return {"msg": "Removed from favorites"}
|
||||
|
||||
|
||||
@favbp.route("/albums/favorite")
|
||||
@api.route("/albums/favorite")
|
||||
def get_favorite_albums():
|
||||
limit = request.args.get("limit")
|
||||
|
||||
@@ -77,7 +78,7 @@ def get_favorite_albums():
|
||||
return {"albums": fav_albums[:limit]}
|
||||
|
||||
|
||||
@favbp.route("/tracks/favorite")
|
||||
@api.route("/tracks/favorite")
|
||||
def get_favorite_tracks():
|
||||
limit = request.args.get("limit")
|
||||
|
||||
@@ -100,7 +101,7 @@ def get_favorite_tracks():
|
||||
return {"tracks": tracks[:limit]}
|
||||
|
||||
|
||||
@favbp.route("/artists/favorite")
|
||||
@api.route("/artists/favorite")
|
||||
def get_favorite_artists():
|
||||
limit = request.args.get("limit")
|
||||
|
||||
@@ -124,7 +125,7 @@ def get_favorite_artists():
|
||||
return {"artists": artists[:limit]}
|
||||
|
||||
|
||||
@favbp.route("/favorites")
|
||||
@api.route("/favorites")
|
||||
def get_all_favorites():
|
||||
"""
|
||||
Returns all the favorites in the database.
|
||||
@@ -191,7 +192,7 @@ def get_all_favorites():
|
||||
}
|
||||
|
||||
|
||||
@favbp.route("/favorites/check")
|
||||
@api.route("/favorites/check")
|
||||
def check_favorite():
|
||||
"""
|
||||
Checks if a favorite exists in the database.
|
||||
|
||||
+8
-8
@@ -2,16 +2,16 @@
|
||||
Contains all the folder routes.
|
||||
"""
|
||||
import os
|
||||
|
||||
from flask import Blueprint, request
|
||||
|
||||
from app import settings
|
||||
from app.lib.folderslib import GetFilesAndDirs
|
||||
|
||||
|
||||
folderbp = Blueprint("folder", __name__, url_prefix="/")
|
||||
api = Blueprint("folder", __name__, url_prefix="/")
|
||||
|
||||
|
||||
@folderbp.route("/folder", methods=["POST"])
|
||||
@api.route("/folder", methods=["POST"])
|
||||
def get_folder_tree():
|
||||
"""
|
||||
Returns a list of all the folders and tracks in the given folder.
|
||||
@@ -21,10 +21,10 @@ def get_folder_tree():
|
||||
if data is not None:
|
||||
req_dir: str = data["folder"]
|
||||
else:
|
||||
req_dir = settings.HOME_DIR
|
||||
req_dir = settings.USER_HOME_DIR
|
||||
|
||||
if req_dir == "$home":
|
||||
req_dir = settings.HOME_DIR
|
||||
req_dir = settings.USER_HOME_DIR
|
||||
|
||||
tracks, folders = GetFilesAndDirs(req_dir)()
|
||||
|
||||
@@ -34,7 +34,7 @@ def get_folder_tree():
|
||||
}
|
||||
|
||||
|
||||
@folderbp.route("/folder/dir-browser", methods=["POST"])
|
||||
@api.route("/folder/dir-browser", methods=["POST"])
|
||||
def list_folders():
|
||||
"""
|
||||
Returns a list of all the folders in the given folder.
|
||||
@@ -44,10 +44,10 @@ def list_folders():
|
||||
try:
|
||||
req_dir: str = data["folder"]
|
||||
except KeyError:
|
||||
req_dir = settings.HOME_DIR
|
||||
req_dir = settings.USER_HOME_DIR
|
||||
|
||||
if req_dir == "$home":
|
||||
req_dir = settings.HOME_DIR
|
||||
req_dir = settings.USER_HOME_DIR
|
||||
|
||||
entries = os.scandir(req_dir)
|
||||
|
||||
|
||||
+10
-11
@@ -1,14 +1,13 @@
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
from flask import Blueprint, send_from_directory
|
||||
|
||||
imgbp = Blueprint("imgserver", __name__, url_prefix="/img")
|
||||
from app.settings import APP_DIR
|
||||
|
||||
api = Blueprint("imgserver", __name__, url_prefix="/img")
|
||||
SUPPORTED_IMAGES = (".jpg", ".png", ".webp", ".jpeg")
|
||||
|
||||
HOME = os.path.expanduser("~")
|
||||
|
||||
APP_DIR = Path(HOME) / ".swing"
|
||||
APP_DIR = Path(APP_DIR)
|
||||
IMG_PATH = APP_DIR / "images"
|
||||
ASSETS_PATH = APP_DIR / "assets"
|
||||
|
||||
@@ -23,7 +22,7 @@ ARTIST_SM_PATH = ARTIST_PATH / "small"
|
||||
PLAYLIST_PATH = IMG_PATH / "playlists"
|
||||
|
||||
|
||||
@imgbp.route("/")
|
||||
@api.route("/")
|
||||
def hello():
|
||||
return "<h1>Image Server</h1>"
|
||||
|
||||
@@ -37,7 +36,7 @@ def send_fallback_img(filename: str = "default.webp"):
|
||||
return send_from_directory(ASSETS_PATH, filename)
|
||||
|
||||
|
||||
@imgbp.route("/t/<imgpath>")
|
||||
@api.route("/t/<imgpath>")
|
||||
def send_lg_thumbnail(imgpath: str):
|
||||
fpath = LG_THUMB_PATH / imgpath
|
||||
|
||||
@@ -47,7 +46,7 @@ def send_lg_thumbnail(imgpath: str):
|
||||
return send_fallback_img()
|
||||
|
||||
|
||||
@imgbp.route("/t/s/<imgpath>")
|
||||
@api.route("/t/s/<imgpath>")
|
||||
def send_sm_thumbnail(imgpath: str):
|
||||
fpath = SM_THUMB_PATH / imgpath
|
||||
|
||||
@@ -57,7 +56,7 @@ def send_sm_thumbnail(imgpath: str):
|
||||
return send_fallback_img()
|
||||
|
||||
|
||||
@imgbp.route("/a/<imgpath>")
|
||||
@api.route("/a/<imgpath>")
|
||||
def send_lg_artist_image(imgpath: str):
|
||||
fpath = ARTIST_LG_PATH / imgpath
|
||||
|
||||
@@ -67,7 +66,7 @@ def send_lg_artist_image(imgpath: str):
|
||||
return send_fallback_img("artist.webp")
|
||||
|
||||
|
||||
@imgbp.route("/a/s/<imgpath>")
|
||||
@api.route("/a/s/<imgpath>")
|
||||
def send_sm_artist_image(imgpath: str):
|
||||
fpath = ARTIST_SM_PATH / imgpath
|
||||
|
||||
@@ -77,7 +76,7 @@ def send_sm_artist_image(imgpath: str):
|
||||
return send_fallback_img("artist.webp")
|
||||
|
||||
|
||||
@imgbp.route("/p/<imgpath>")
|
||||
@api.route("/p/<imgpath>")
|
||||
def send_playlist_image(imgpath: str):
|
||||
fpath = PLAYLIST_PATH / imgpath
|
||||
|
||||
|
||||
+8
-8
@@ -13,7 +13,7 @@ from app.db.store import Store
|
||||
from app.lib import playlistlib
|
||||
from app.utils import create_new_date, remove_duplicates
|
||||
|
||||
playlistbp = Blueprint("playlist", __name__, url_prefix="/")
|
||||
api = Blueprint("playlist", __name__, url_prefix="/")
|
||||
|
||||
PL = SQLitePlaylistMethods
|
||||
|
||||
@@ -30,7 +30,7 @@ delete_playlist = PL.delete_playlist
|
||||
# get_tracks_by_trackhashes = SQLiteTrackMethods.get_tracks_by_trackhashes
|
||||
|
||||
|
||||
@playlistbp.route("/playlists", methods=["GET"])
|
||||
@api.route("/playlists", methods=["GET"])
|
||||
def send_all_playlists():
|
||||
"""
|
||||
Gets all the playlists.
|
||||
@@ -46,7 +46,7 @@ def send_all_playlists():
|
||||
return {"data": playlists}
|
||||
|
||||
|
||||
@playlistbp.route("/playlist/new", methods=["POST"])
|
||||
@api.route("/playlist/new", methods=["POST"])
|
||||
def create_playlist():
|
||||
"""
|
||||
Creates a new playlist. Accepts POST method with a JSON body.
|
||||
@@ -79,7 +79,7 @@ def create_playlist():
|
||||
return {"playlist": playlist}, 201
|
||||
|
||||
|
||||
@playlistbp.route("/playlist/<playlist_id>/add", methods=["POST"])
|
||||
@api.route("/playlist/<playlist_id>/add", methods=["POST"])
|
||||
def add_track_to_playlist(playlist_id: str):
|
||||
"""
|
||||
Takes a playlist ID and a track hash, and adds the track to the playlist
|
||||
@@ -102,7 +102,7 @@ def add_track_to_playlist(playlist_id: str):
|
||||
return {"msg": "Done"}, 200
|
||||
|
||||
|
||||
@playlistbp.route("/playlist/<playlistid>")
|
||||
@api.route("/playlist/<playlistid>")
|
||||
def get_playlist(playlistid: str):
|
||||
"""
|
||||
Gets a playlist by id, and if it exists, it gets all the tracks in the playlist and returns them.
|
||||
@@ -123,7 +123,7 @@ def get_playlist(playlistid: str):
|
||||
return {"info": playlist, "tracks": tracks}
|
||||
|
||||
|
||||
@playlistbp.route("/playlist/<playlistid>/update", methods=["PUT"])
|
||||
@api.route("/playlist/<playlistid>/update", methods=["PUT"])
|
||||
def update_playlist_info(playlistid: str):
|
||||
if playlistid is None:
|
||||
return {"error": "Playlist ID not provided"}, 400
|
||||
@@ -188,7 +188,7 @@ def update_playlist_info(playlistid: str):
|
||||
# return {"data": artists}
|
||||
|
||||
|
||||
@playlistbp.route("/playlist/delete", methods=["POST"])
|
||||
@api.route("/playlist/delete", methods=["POST"])
|
||||
def remove_playlist():
|
||||
"""
|
||||
Deletes a playlist by ID.
|
||||
@@ -209,7 +209,7 @@ def remove_playlist():
|
||||
return {"msg": "Done"}, 200
|
||||
|
||||
|
||||
@playlistbp.route("/playlist/<pid>/set-image-pos", methods=["POST"])
|
||||
@api.route("/playlist/<pid>/set-image-pos", methods=["POST"])
|
||||
def update_image_position(pid: int):
|
||||
data = request.get_json()
|
||||
message = {"msg": "No data provided"}
|
||||
|
||||
+6
-6
@@ -8,7 +8,7 @@ from app import models, utils
|
||||
from app.db.store import Store
|
||||
from app.lib import searchlib
|
||||
|
||||
searchbp = Blueprint("search", __name__, url_prefix="/")
|
||||
api = Blueprint("search", __name__, url_prefix="/")
|
||||
|
||||
|
||||
SEARCH_COUNT = 12
|
||||
@@ -95,7 +95,7 @@ class DoSearch:
|
||||
# self.search_playlists()
|
||||
|
||||
|
||||
@searchbp.route("/search/tracks", methods=["GET"])
|
||||
@api.route("/search/tracks", methods=["GET"])
|
||||
def search_tracks():
|
||||
"""
|
||||
Searches for tracks that match the search query.
|
||||
@@ -113,7 +113,7 @@ def search_tracks():
|
||||
}
|
||||
|
||||
|
||||
@searchbp.route("/search/albums", methods=["GET"])
|
||||
@api.route("/search/albums", methods=["GET"])
|
||||
def search_albums():
|
||||
"""
|
||||
Searches for albums.
|
||||
@@ -131,7 +131,7 @@ def search_albums():
|
||||
}
|
||||
|
||||
|
||||
@searchbp.route("/search/artists", methods=["GET"])
|
||||
@api.route("/search/artists", methods=["GET"])
|
||||
def search_artists():
|
||||
"""
|
||||
Searches for artists.
|
||||
@@ -167,7 +167,7 @@ def search_artists():
|
||||
# }
|
||||
|
||||
|
||||
@searchbp.route("/search/top", methods=["GET"])
|
||||
@api.route("/search/top", methods=["GET"])
|
||||
def get_top_results():
|
||||
"""
|
||||
Returns the top results for the search query.
|
||||
@@ -188,7 +188,7 @@ def get_top_results():
|
||||
}
|
||||
|
||||
|
||||
@searchbp.route("/search/loadmore")
|
||||
@api.route("/search/loadmore")
|
||||
def search_load_more():
|
||||
"""
|
||||
Returns more songs, albums or artists from a search query.
|
||||
|
||||
+22
-7
@@ -1,10 +1,17 @@
|
||||
from flask import Blueprint, request
|
||||
|
||||
from app.db.sqlite.settings import SettingsSQLMethods as sdb
|
||||
|
||||
settingsbp = Blueprint("settings", __name__, url_prefix="/")
|
||||
api = Blueprint("settings", __name__, url_prefix="/")
|
||||
|
||||
|
||||
@settingsbp.route("/settings/add-root-dirs", methods=["POST"])
|
||||
def get_child_dirs(parent: str, children: list[str]):
|
||||
"""Returns child directories in a list, given a parent directory"""
|
||||
|
||||
return [dir for dir in children if dir.startswith(parent)]
|
||||
|
||||
|
||||
@api.route("/settings/add-root-dirs", methods=["POST"])
|
||||
def add_root_dirs():
|
||||
"""
|
||||
Add custom root directories to the database.
|
||||
@@ -17,18 +24,26 @@ def add_root_dirs():
|
||||
return msg, 400
|
||||
|
||||
try:
|
||||
new_dirs = data["new_dirs"]
|
||||
removed_dirs = data["removed"]
|
||||
new_dirs: list[str] = data["new_dirs"]
|
||||
removed_dirs: list[str] = data["removed"]
|
||||
except KeyError:
|
||||
return msg, 400
|
||||
|
||||
# --- Unregister child directories ---
|
||||
db_dirs = sdb.get_root_dirs()
|
||||
|
||||
for _dir in new_dirs:
|
||||
children = get_child_dirs(_dir, db_dirs)
|
||||
removed_dirs.extend(children)
|
||||
# ------------------------------------
|
||||
|
||||
sdb.add_root_dirs(new_dirs)
|
||||
sdb.remove_root_dirs(removed_dirs)
|
||||
|
||||
return {"msg": "Added root directories to the database."}
|
||||
return {"msg": "Updated!"}
|
||||
|
||||
|
||||
@settingsbp.route("/settings/get-root-dirs", methods=["GET"])
|
||||
@api.route("/settings/get-root-dirs", methods=["GET"])
|
||||
def get_root_dirs():
|
||||
"""
|
||||
Get custom root directories from the database.
|
||||
@@ -39,7 +54,7 @@ def get_root_dirs():
|
||||
|
||||
|
||||
# CURRENTLY UNUSED ROUTE 👇
|
||||
@settingsbp.route("/settings/remove-root-dirs", methods=["POST"])
|
||||
@api.route("/settings/remove-root-dirs", methods=["POST"])
|
||||
def remove_root_dirs():
|
||||
"""
|
||||
Remove custom root directories from the database.
|
||||
|
||||
+3
-2
@@ -2,12 +2,13 @@
|
||||
Contains all the track routes.
|
||||
"""
|
||||
from flask import Blueprint, send_file
|
||||
|
||||
from app.db.store import Store
|
||||
|
||||
trackbp = Blueprint("track", __name__, url_prefix="/")
|
||||
api = Blueprint("track", __name__, url_prefix="/")
|
||||
|
||||
|
||||
@trackbp.route("/file/<trackhash>")
|
||||
@api.route("/file/<trackhash>")
|
||||
def send_track_file(trackhash: str):
|
||||
"""
|
||||
Returns an audio file that matches the passed id to the client.
|
||||
|
||||
Reference in New Issue
Block a user