mirror of
https://github.com/Dvorinka/swingmusic-extended.git
synced 2026-06-05 04:53:01 +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:
|
else:
|
||||||
req_dir = "/" + req_dir + "/" if not req_dir.startswith("/") else req_dir + "/"
|
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 {
|
return res
|
||||||
"tracks": tracks,
|
|
||||||
"folders": sorted(folders, key=lambda i: i.name),
|
# return {
|
||||||
}
|
# "path": req_dir,
|
||||||
|
# "tracks": tracks,
|
||||||
|
# "folders": sorted(folders, key=lambda i: i.name),
|
||||||
|
# }
|
||||||
|
|
||||||
|
|
||||||
def get_all_drives(is_win: bool = False):
|
def get_all_drives(is_win: bool = False):
|
||||||
|
|||||||
+5
-4
@@ -58,7 +58,7 @@ class HandleArgs:
|
|||||||
|
|
||||||
if not value:
|
if not value:
|
||||||
log.error(f"WARNING: {key} not set in environment")
|
log.error(f"WARNING: {key} not set in environment")
|
||||||
#sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
lines.append(f'{key} = "{value}"\n')
|
lines.append(f'{key} = "{value}"\n')
|
||||||
|
|
||||||
@@ -132,12 +132,13 @@ class HandleArgs:
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
config_path = ARGS[index + 1]
|
config_path = ARGS[index + 1]
|
||||||
|
resolved = os.path.abspath(config_path)
|
||||||
|
|
||||||
if os.path.exists(config_path):
|
if os.path.exists(resolved):
|
||||||
settings.Paths.set_config_dir(config_path)
|
settings.Paths.set_config_dir(resolved)
|
||||||
return
|
return
|
||||||
|
|
||||||
log.warn(f"Config path {config_path} doesn't exist")
|
log.warn(f"Config path {resolved} doesn't exist")
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
except IndexError:
|
except IndexError:
|
||||||
pass
|
pass
|
||||||
|
|||||||
+26
-4
@@ -48,11 +48,20 @@ class GetFilesAndDirs:
|
|||||||
self.path = path
|
self.path = path
|
||||||
self.tracks_only = tracks_only
|
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:
|
try:
|
||||||
entries = os.scandir(self.path)
|
entries = os.scandir(path)
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
return [], []
|
return {
|
||||||
|
"path": path,
|
||||||
|
"tracks": [],
|
||||||
|
"folders": [],
|
||||||
|
}
|
||||||
|
|
||||||
dirs, files = [], []
|
dirs, files = [], []
|
||||||
|
|
||||||
@@ -86,4 +95,17 @@ class GetFilesAndDirs:
|
|||||||
if not self.tracks_only:
|
if not self.tracks_only:
|
||||||
folders = get_folders(dirs)
|
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,14 +10,20 @@ class AddTimestampToFavoritesTable(Migration):
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def migrate():
|
def migrate():
|
||||||
# INFO: add timestamp column with automatic current timestamp
|
# 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
|
# INFO: execute the sql
|
||||||
with SQLiteManager(userdata_db=True) as cur:
|
with SQLiteManager(userdata_db=True) as cur:
|
||||||
|
try:
|
||||||
|
# INFO: Add the timestamp column to the favorites table
|
||||||
cur.execute(sql)
|
cur.execute(sql)
|
||||||
|
|
||||||
# INFO: Update the timestamp column with the current timestamp
|
# INFO: Set all the timestamps to the current time
|
||||||
cur.execute("UPDATE favorites SET timestamp = strftime('%s', 'now')")
|
cur.execute("UPDATE favorites SET timestamp = strftime('%s', 'now')")
|
||||||
|
except Exception as e:
|
||||||
|
# INFO: timestamp column already exists
|
||||||
|
pass
|
||||||
|
finally:
|
||||||
cur.close()
|
cur.close()
|
||||||
|
|
||||||
|
|
||||||
@@ -28,6 +34,7 @@ class MoveHashesToSha1(Migration):
|
|||||||
|
|
||||||
Thanks to [@tcsenpai](https:github.com/tcsenpai) for the contribution.
|
Thanks to [@tcsenpai](https:github.com/tcsenpai) for the contribution.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# INFO: Apparentlly, every single table is affected by this migration.
|
# INFO: Apparentlly, every single table is affected by this migration.
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
"""
|
"""
|
||||||
Requests related to artists
|
Requests related to artists
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import urllib.parse
|
import urllib.parse
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
from requests import ConnectionError, HTTPError, ReadTimeout
|
from requests import ConnectionError, HTTPError, ReadTimeout
|
||||||
|
|
||||||
#from app import settings
|
|
||||||
from app.utils.hashing import create_hash
|
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"
|
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:
|
try:
|
||||||
response = requests.get(url, timeout=10)
|
response = requests.get(url, timeout=10)
|
||||||
response.raise_for_status()
|
response.raise_for_status()
|
||||||
|
|||||||
@@ -275,9 +275,6 @@ class Keys:
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def load(cls):
|
def load(cls):
|
||||||
# TODO Remove this. Just an handy flag to test the app without the API key
|
|
||||||
# IS_BUILD = True
|
|
||||||
|
|
||||||
if IS_BUILD:
|
if IS_BUILD:
|
||||||
cls.SWINGMUSIC_APP_VERSION = configs.SWINGMUSIC_APP_VERSION
|
cls.SWINGMUSIC_APP_VERSION = configs.SWINGMUSIC_APP_VERSION
|
||||||
cls.GIT_LATEST_COMMIT_HASH = configs.GIT_LATEST_COMMIT_HASH
|
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_ = str_.encode("utf-8")
|
||||||
str_ = hashlib.sha1(str_).hexdigest()
|
str_ = hashlib.sha1(str_).hexdigest()
|
||||||
# REVIEW Switched to sha1 hashlib.sha256(str_).hexdigest()
|
|
||||||
|
|
||||||
# REVIEW Take the first limit/2 and last limit/2 characters
|
return (
|
||||||
# This is to avoid collisions
|
str_[: limit // 2] + str_[-limit // 2 :]
|
||||||
return str_[:limit // 2] + str_[-limit // 2:] if limit % 2 == 0 else str_[:limit // 2] + str_[-limit // 2 - 1:]
|
if limit % 2 == 0
|
||||||
|
else str_[: limit // 2] + str_[-limit // 2 - 1 :]
|
||||||
# return str_[-limit:]
|
)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import os
|
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 XDG_CONFIG_HOME environment variable if it exists, otherwise
|
||||||
returns the default config directory. If none of those exist, returns the
|
returns the default config directory. If none of those exist, returns the
|
||||||
@@ -19,3 +19,6 @@ def get_xdg_config_dir():
|
|||||||
return alt_dir
|
return alt_dir
|
||||||
except TypeError:
|
except TypeError:
|
||||||
return os.path.expanduser("~")
|
return os.path.expanduser("~")
|
||||||
|
|
||||||
|
# Fallback to current directory
|
||||||
|
return os.path.abspath(".")
|
||||||
|
|||||||
Regular → Executable
Reference in New Issue
Block a user