handle watching ~/ dir

+ fix bug that caused duplicate album colors in db
This commit is contained in:
geoffrey45
2023-01-23 17:10:05 +03:00
parent d676459b9a
commit 22fa3eef40
7 changed files with 121 additions and 31 deletions
+27 -3
View File
@@ -3,10 +3,14 @@ Contains all the folder routes.
"""
import os
from pathlib import Path
from flask import Blueprint, request
from app import settings
from app.lib.folderslib import GetFilesAndDirs
from app.db.sqlite.settings import SettingsSQLMethods as db
from app.models import Folder
from app.utils import create_folder_hash
api = Blueprint("folder", __name__, url_prefix="/")
@@ -19,12 +23,32 @@ def get_folder_tree():
data = request.get_json()
if data is not None:
req_dir: str = data["folder"]
else:
try:
req_dir: str = data["folder"]
except KeyError:
req_dir = "$home"
root_dirs = db.get_root_dirs()
if req_dir == "$home" and root_dirs[0] == "$home":
req_dir = settings.USER_HOME_DIR
if req_dir == "$home":
req_dir = settings.USER_HOME_DIR
folders = [Path(f) for f in root_dirs]
return {
"folders": [
Folder(
name=f.name,
path=str(f),
has_tracks=True,
is_sym=f.is_symlink(),
path_hash=create_folder_hash(*f.parts[1:]),
)
for f in folders
],
"tracks": [],
}
tracks, folders = GetFilesAndDirs(req_dir)()
+52 -5
View File
@@ -1,6 +1,12 @@
from flask import Blueprint, request
from app import settings
from app.db.sqlite.settings import SettingsSQLMethods as sdb
from app.lib import populate
from app.logger import log
from app.db.store import Store
from app.utils import background
api = Blueprint("settings", __name__, url_prefix="/")
@@ -8,7 +14,22 @@ api = Blueprint("settings", __name__, url_prefix="/")
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)]
return [dir for dir in children if dir.startswith(parent) and dir != parent]
@background
def rebuild_store(db_dirs: list[str]):
log.info("Rebuilding library...")
Store.remove_tracks_by_dir_except(db_dirs)
Store.load_all_tracks()
Store.process_folders()
Store.load_albums()
Store.load_artists()
populate.Populate()
log.info("Rebuilding library... ✅")
@api.route("/settings/add-root-dirs", methods=["POST"])
@@ -29,16 +50,42 @@ def add_root_dirs():
except KeyError:
return msg, 400
# --- Unregister child directories ---
def finalize(new_dirs: list[str], removed_dirs: list[str], db_dirs: list[str]):
sdb.remove_root_dirs(removed_dirs)
sdb.add_root_dirs(new_dirs)
rebuild_store(db_dirs)
# ---
db_dirs = sdb.get_root_dirs()
if db_dirs[0] == "$home" and new_dirs[0] == "$home".strip():
return {"msg": "Not changed!"}
if db_dirs[0] == "$home":
sdb.remove_root_dirs(db_dirs)
try:
if new_dirs[0] == "$home":
finalize(["$home"], db_dirs, [settings.USER_HOME_DIR])
return {"msg": "Updated!"}
except IndexError:
pass
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)
for _dir in removed_dirs:
try:
db_dirs.remove(_dir)
except ValueError:
pass
db_dirs.extend(new_dirs)
finalize(new_dirs, removed_dirs, db_dirs)
return {"msg": "Updated!"}
+5 -11
View File
@@ -130,15 +130,9 @@ class SQLiteTrackMethods:
cur.execute("DELETE FROM tracks WHERE filepath=?", (filepath,))
@staticmethod
def track_exists(filepath: str):
"""
Checks if a track exists in the database using its filepath.
"""
def remove_tracks_by_folders(folders: list[str]):
sql = "DELETE FROM tracks WHERE folder = ?"
with SQLiteManager() as cur:
cur.execute("SELECT * FROM tracks WHERE filepath=?", (filepath,))
row = cur.fetchone()
if row is not None:
return True
return False
for folder in folders:
cur.execute(sql, (folder,))
+19 -3
View File
@@ -88,6 +88,17 @@ class Store:
cls.tracks.remove(track)
break
@classmethod
def remove_tracks_by_dir_except(cls, dirs: list[str]):
"""Removes all tracks not in the root directories."""
to_remove = set()
for track in cls.tracks:
if not track.folder.startswith(tuple(dirs)):
to_remove.add(track.folder)
tdb.remove_tracks_by_folders(to_remove)
@classmethod
def count_tracks_by_hash(cls, trackhash: str) -> int:
"""
@@ -197,6 +208,8 @@ class Store:
"""
Creates a list of folders from the tracks in the store.
"""
cls.folders.clear()
all_folders = [track.folder for track in cls.tracks]
all_folders = set(all_folders)
@@ -212,6 +225,7 @@ class Store:
cls.folders.append(folder)
@classmethod
def get_folder(cls, path: str): # type: ignore
"""
@@ -277,6 +291,8 @@ class Store:
Loads all albums from the database into the store.
"""
cls.albums = []
albumhashes = set(t.albumhash for t in cls.tracks)
for albumhash in tqdm(albumhashes, desc="Loading albums"):
@@ -291,9 +307,9 @@ class Store:
albumhash = album[1]
colors = json.loads(album[2])
for al in cls.albums:
if al.albumhash == albumhash:
al.set_colors(colors)
for _al in cls.albums:
if _al.albumhash == albumhash:
_al.set_colors(colors)
break
@classmethod
+7 -3
View File
@@ -38,9 +38,13 @@ class ProcessAlbumColors:
"""
def __init__(self) -> None:
db_colors = db.get_all_albums()
db_albumhashes = "-".join([album[1] for album in db_colors])
albums = [a for a in Store.albums if a.albumhash not in db_albumhashes]
with SQLiteManager() as cur:
for album in tqdm(Store.albums, desc="Processing album colors"):
for album in tqdm(albums, desc="Processing unprocessed album colors"):
if len(album.colors) == 0:
colors = self.process_color(album)
@@ -71,9 +75,9 @@ class ProcessArtistColors:
def __init__(self) -> None:
db_colors: list[tuple] = list(adb.get_all_artists())
db_artisthashes = "-".join([artist[1] for artist in db_colors])
all_artists = Store.artists
all_artists = [a for a in Store.artists if a.artisthash not in db_artisthashes]
for artist in tqdm(all_artists, desc="Processing artist colors"):
for artist in tqdm(all_artists, desc="Processing unprocessed artist colors"):
if artist.artisthash not in db_artisthashes:
self.process_color(artist)
-1
View File
@@ -1,5 +1,4 @@
import os
import pathlib
from concurrent.futures import ThreadPoolExecutor
from app.db.store import Store
+11 -5
View File
@@ -25,7 +25,7 @@ class Populate:
"""
def __init__(self) -> None:
messages = {
text = {
"root_unset": "The root directory is not set. Trying to scan the default directory: %s",
"default_not_exists": "The directory: %s does not exist. Please open the app in your web browser to set the root directory.",
"no_tracks": "No tracks found in: %s. Please open the app in your web browser to set the root directory.",
@@ -40,17 +40,23 @@ class Populate:
def_dir = "~/Music"
if len(dirs_to_scan) == 0:
log.warning(messages["root_unset"], def_dir)
log.warning(text["root_unset"], def_dir)
print("...")
exists = os.path.exists(settings.MUSIC_DIR)
if not exists:
log.warning(messages["default_not_exists"], def_dir)
log.warning(text["default_not_exists"], def_dir)
return
dirs_to_scan = [settings.MUSIC_DIR]
try:
if dirs_to_scan[0] == "$home":
dirs_to_scan = [settings.USER_HOME_DIR]
except IndexError:
pass
files = []
for _dir in dirs_to_scan:
@@ -59,7 +65,7 @@ class Populate:
untagged = self.filter_untagged(tracks, files)
if initial_dirs_count == 0 and len(untagged) == 0:
log.warning(messages["no_tracks"], def_dir)
log.warning(text["no_tracks"], def_dir)
return
if initial_dirs_count == 0 and len(untagged) > 0:
@@ -76,7 +82,7 @@ class Populate:
settings.TCOLOR.ENDC,
)
sdb.add_root_dirs(dirs_to_scan)
return
# return
if len(untagged) == 0:
log.info("All clear, no unread files.")