fix: absolute config path not resolving

+ skip through empty directories in folder browser
+ handle timestamp table error in migration
This commit is contained in:
mungai-njoroge
2024-04-01 11:02:27 +03:00
parent 95a8e9b215
commit 2f6e705c75
9 changed files with 64 additions and 35 deletions
+9 -5
View File
@@ -64,12 +64,16 @@ def get_folder_tree(body: FolderTree):
else:
req_dir = "/" + req_dir + "/" if not req_dir.startswith("/") else req_dir + "/"
tracks, folders = GetFilesAndDirs(req_dir, tracks_only=tracks_only)()
res = GetFilesAndDirs(req_dir, tracks_only=tracks_only)()
res['folders'] = sorted(res['folders'], key=lambda i: i.name)
return {
"tracks": tracks,
"folders": sorted(folders, key=lambda i: i.name),
}
return res
# return {
# "path": req_dir,
# "tracks": tracks,
# "folders": sorted(folders, key=lambda i: i.name),
# }
def get_all_drives(is_win: bool = False):
+5 -4
View File
@@ -58,7 +58,7 @@ class HandleArgs:
if not value:
log.error(f"WARNING: {key} not set in environment")
#sys.exit(0)
sys.exit(0)
lines.append(f'{key} = "{value}"\n')
@@ -132,12 +132,13 @@ class HandleArgs:
try:
config_path = ARGS[index + 1]
resolved = os.path.abspath(config_path)
if os.path.exists(config_path):
settings.Paths.set_config_dir(config_path)
if os.path.exists(resolved):
settings.Paths.set_config_dir(resolved)
return
log.warn(f"Config path {config_path} doesn't exist")
log.warn(f"Config path {resolved} doesn't exist")
sys.exit(0)
except IndexError:
pass
+26 -4
View File
@@ -48,11 +48,20 @@ class GetFilesAndDirs:
self.path = path
self.tracks_only = tracks_only
def __call__(self) -> tuple[list[Track], list[Folder]]:
def get_files_and_dirs(self, path: str, skip_empty_folders=True):
"""
Given a path, returns a list of tracks and folders in that immediate path.
Can recursively call itself to skip through empty folders.
"""
try:
entries = os.scandir(self.path)
entries = os.scandir(path)
except FileNotFoundError:
return [], []
return {
"path": path,
"tracks": [],
"folders": [],
}
dirs, files = [], []
@@ -86,4 +95,17 @@ class GetFilesAndDirs:
if not self.tracks_only:
folders = get_folders(dirs)
return tracks, folders
if skip_empty_folders and len(folders) == 1 and len(tracks) == 0:
# INFO: When we only have one folder and no tracks,
# skip through empty folders.
# Call recursively with the first folder in the list.
return self.get_files_and_dirs(folders[0].path)
return {
"path": path,
"tracks": tracks,
"folders": folders,
}
def __call__(self):
return self.get_files_and_dirs(self.path)
+13 -6
View File
@@ -10,15 +10,21 @@ class AddTimestampToFavoritesTable(Migration):
@staticmethod
def migrate():
# INFO: add timestamp column with automatic current timestamp
sql = f"ALTER TABLE favorites ADD COLUMN timestamp INTEGER NOT NULL DEFAULT 0"
sql = f"ALTER TABLE favorites ADD COLUMN IF NOT EXISTS timestamp INTEGER NOT NULL DEFAULT 0"
# INFO: execute the sql
with SQLiteManager(userdata_db=True) as cur:
cur.execute(sql)
try:
# INFO: Add the timestamp column to the favorites table
cur.execute(sql)
# INFO: Update the timestamp column with the current timestamp
cur.execute("UPDATE favorites SET timestamp = strftime('%s', 'now')")
cur.close()
# INFO: Set all the timestamps to the current time
cur.execute("UPDATE favorites SET timestamp = strftime('%s', 'now')")
except Exception as e:
# INFO: timestamp column already exists
pass
finally:
cur.close()
class MoveHashesToSha1(Migration):
@@ -28,7 +34,8 @@ class MoveHashesToSha1(Migration):
Thanks to [@tcsenpai](https:github.com/tcsenpai) for the contribution.
"""
pass
# INFO: Apparentlly, every single table is affected by this migration.
# NOTE: Use generators to avoid memory issues.
# NOTE: Use generators to avoid memory issues.
+1 -5
View File
@@ -1,12 +1,12 @@
"""
Requests related to artists
"""
import urllib.parse
import requests
from requests import ConnectionError, HTTPError, ReadTimeout
#from app import settings
from app.utils.hashing import create_hash
@@ -16,10 +16,6 @@ def fetch_similar_artists(name: str):
"""
url = f"https://kerve.last.fm/kerve/similarartists?artist={urllib.parse.quote_plus(name, safe='')}&autocorrect=1&tracks=1&image_size=large&limit=250&format=json"
# REVIEW This is the old way of doing it. The new way is to use the Kerve API.
#url = f"https://ws.audioscrobbler.com/2.0/?method=artist.getsimilar&artist={urllib.parse.quote_plus(name, safe='')}&api_key={settings.Keys.LASTFM_API_KEY}&format=json&limit=250"
# TODO Cannot be tested due to PR message
url = f"https://kerve.last.fm/kerve/similarartists?artist={urllib.parse.quote_plus(name, safe='')}&autocorrect=1&tracks=1&image_size=large&limit=250&format=json"
try:
response = requests.get(url, timeout=10)
response.raise_for_status()
-3
View File
@@ -275,9 +275,6 @@ class Keys:
@classmethod
def load(cls):
# TODO Remove this. Just an handy flag to test the app without the API key
# IS_BUILD = True
if IS_BUILD:
cls.SWINGMUSIC_APP_VERSION = configs.SWINGMUSIC_APP_VERSION
cls.GIT_LATEST_COMMIT_HASH = configs.GIT_LATEST_COMMIT_HASH
+5 -6
View File
@@ -33,10 +33,9 @@ def create_hash(*args: str, decode=False, limit=10) -> str:
str_ = str_.encode("utf-8")
str_ = hashlib.sha1(str_).hexdigest()
# REVIEW Switched to sha1 hashlib.sha256(str_).hexdigest()
# REVIEW Take the first limit/2 and last limit/2 characters
# This is to avoid collisions
return str_[:limit // 2] + str_[-limit // 2:] if limit % 2 == 0 else str_[:limit // 2] + str_[-limit // 2 - 1:]
# return str_[-limit:]
return (
str_[: limit // 2] + str_[-limit // 2 :]
if limit % 2 == 0
else str_[: limit // 2] + str_[-limit // 2 - 1 :]
)
+4 -1
View File
@@ -1,7 +1,7 @@
import os
def get_xdg_config_dir():
def get_xdg_config_dir() -> str:
"""
Returns the XDG_CONFIG_HOME environment variable if it exists, otherwise
returns the default config directory. If none of those exist, returns the
@@ -19,3 +19,6 @@ def get_xdg_config_dir():
return alt_dir
except TypeError:
return os.path.expanduser("~")
# Fallback to current directory
return os.path.abspath(".")