mirror of
https://github.com/Dvorinka/swingmusic-extended.git
synced 2026-06-03 20:13:02 +00:00
fix: absolute config path not resolving
+ skip through empty directories in folder browser + handle timestamp table error in migration
This commit is contained in:
+9
-5
@@ -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
@@ -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
@@ -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)
|
||||
|
||||
@@ -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,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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 :]
|
||||
)
|
||||
|
||||
@@ -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(".")
|
||||
|
||||
Reference in New Issue
Block a user