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:
geoffrey45
2023-01-22 23:57:12 +03:00
parent 4e6e1f03dc
commit bcc4873766
18 changed files with 163 additions and 179 deletions
+11 -20
View File
@@ -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
View File
@@ -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
View File
@@ -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.
+9 -8
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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.