mirror of
https://github.com/tcsenpai/swingmusic.git
synced 2025-06-07 03:35:35 +00:00
implement pinning playlists
+ update migrations to add pinned attr to plalist + misc
This commit is contained in:
parent
c3c9cb059f
commit
e3a61c109b
@ -97,7 +97,12 @@ def insert_playlist(name: str, image: str = None):
|
|||||||
"name": name,
|
"name": name,
|
||||||
"trackhashes": json.dumps([]),
|
"trackhashes": json.dumps([]),
|
||||||
"settings": json.dumps(
|
"settings": json.dumps(
|
||||||
{"has_gif": False, "banner_pos": 50, "square_img": True if image else False}
|
{
|
||||||
|
"has_gif": False,
|
||||||
|
"banner_pos": 50,
|
||||||
|
"square_img": True if image else False,
|
||||||
|
"pinned": False,
|
||||||
|
}
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -170,12 +175,12 @@ def add_item_to_playlist(playlist_id: str):
|
|||||||
itemtype = None
|
itemtype = None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
itemhash = data["itemhash"]
|
itemhash: str = data["itemhash"]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
itemhash = None
|
itemhash = None
|
||||||
|
|
||||||
if itemtype == "track":
|
if itemtype == "tracks":
|
||||||
trackhashes = [itemhash]
|
trackhashes = itemhash.split(",")
|
||||||
elif itemtype == "folder":
|
elif itemtype == "folder":
|
||||||
trackhashes = get_path_trackhashes(itemhash)
|
trackhashes = get_path_trackhashes(itemhash)
|
||||||
elif itemtype == "album":
|
elif itemtype == "album":
|
||||||
@ -190,8 +195,6 @@ def add_item_to_playlist(playlist_id: str):
|
|||||||
if insert_count == 0:
|
if insert_count == 0:
|
||||||
return {"error": "Item already exists in playlist"}, 409
|
return {"error": "Item already exists in playlist"}, 409
|
||||||
|
|
||||||
PL.update_last_updated(int(playlist_id))
|
|
||||||
|
|
||||||
return {"msg": "Done"}, 200
|
return {"msg": "Done"}, 200
|
||||||
|
|
||||||
|
|
||||||
@ -220,13 +223,6 @@ def get_playlist(playlistid: str):
|
|||||||
if not playlist.has_image:
|
if not playlist.has_image:
|
||||||
playlist.images = get_first_4_images(tracks)
|
playlist.images = get_first_4_images(tracks)
|
||||||
|
|
||||||
if len(playlist.images) > 2:
|
|
||||||
# swap 3rd image with first (3rd image is the visible image in UI)
|
|
||||||
playlist.images[2], playlist.images[0] = (
|
|
||||||
playlist.images[0],
|
|
||||||
playlist.images[2],
|
|
||||||
)
|
|
||||||
|
|
||||||
playlist.clear_lists()
|
playlist.clear_lists()
|
||||||
|
|
||||||
return {"info": playlist, "tracks": tracks if not no_tracks else []}
|
return {"info": playlist, "tracks": tracks if not no_tracks else []}
|
||||||
@ -288,6 +284,28 @@ def update_playlist_info(playlistid: str):
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@api.route("/playlist/<playlistid>/pin_unpin", methods=["GET"])
|
||||||
|
def pin_unpin_playlist(playlistid: str):
|
||||||
|
"""
|
||||||
|
Pins or unpins a playlist.
|
||||||
|
"""
|
||||||
|
playlist = PL.get_playlist_by_id(int(playlistid))
|
||||||
|
|
||||||
|
if playlist is None:
|
||||||
|
return {"error": "Playlist not found"}, 404
|
||||||
|
|
||||||
|
settings = playlist.settings
|
||||||
|
|
||||||
|
try:
|
||||||
|
settings["pinned"] = not settings["pinned"]
|
||||||
|
except KeyError:
|
||||||
|
settings["pinned"] = True
|
||||||
|
|
||||||
|
PL.update_settings(int(playlistid), settings)
|
||||||
|
|
||||||
|
return {"msg": "Done"}, 200
|
||||||
|
|
||||||
|
|
||||||
@api.route("/playlist/<playlistid>/remove-img", methods=["GET"])
|
@api.route("/playlist/<playlistid>/remove-img", methods=["GET"])
|
||||||
def remove_playlist_image(playlistid: str):
|
def remove_playlist_image(playlistid: str):
|
||||||
"""
|
"""
|
||||||
@ -308,7 +326,6 @@ def remove_playlist_image(playlistid: str):
|
|||||||
|
|
||||||
playlist.images = get_first_4_images(trackhashes=playlist.trackhashes)
|
playlist.images = get_first_4_images(trackhashes=playlist.trackhashes)
|
||||||
playlist.last_updated = date_string_to_time_passed(playlist.last_updated)
|
playlist.last_updated = date_string_to_time_passed(playlist.last_updated)
|
||||||
PL.update_last_updated(pid)
|
|
||||||
|
|
||||||
return {"playlist": playlist}, 200
|
return {"playlist": playlist}, 200
|
||||||
|
|
||||||
@ -334,24 +351,6 @@ def remove_playlist():
|
|||||||
return {"msg": "Done"}, 200
|
return {"msg": "Done"}, 200
|
||||||
|
|
||||||
|
|
||||||
@api.route("/playlist/<pid>/set-image-pos", methods=["POST"])
|
|
||||||
def update_image_position(pid: int):
|
|
||||||
data = request.get_json()
|
|
||||||
message = {"msg": "No data provided"}
|
|
||||||
|
|
||||||
if data is None:
|
|
||||||
return message, 400
|
|
||||||
|
|
||||||
try:
|
|
||||||
pos = data["pos"]
|
|
||||||
except KeyError:
|
|
||||||
return message, 400
|
|
||||||
|
|
||||||
PL.update_banner_pos(pid, pos)
|
|
||||||
|
|
||||||
return {"msg": "Image position saved"}, 200
|
|
||||||
|
|
||||||
|
|
||||||
@api.route("/playlist/<pid>/remove-tracks", methods=["POST"])
|
@api.route("/playlist/<pid>/remove-tracks", methods=["POST"])
|
||||||
def remove_tracks_from_playlist(pid: int):
|
def remove_tracks_from_playlist(pid: int):
|
||||||
data = request.get_json()
|
data = request.get_json()
|
||||||
@ -366,7 +365,6 @@ def remove_tracks_from_playlist(pid: int):
|
|||||||
|
|
||||||
tracks = data["tracks"]
|
tracks = data["tracks"]
|
||||||
PL.remove_tracks_from_playlist(pid, tracks)
|
PL.remove_tracks_from_playlist(pid, tracks)
|
||||||
PL.update_last_updated(pid)
|
|
||||||
|
|
||||||
return {"msg": "Done"}, 200
|
return {"msg": "Done"}, 200
|
||||||
|
|
||||||
@ -404,30 +402,29 @@ def save_item_as_playlist():
|
|||||||
if itemtype is None or playlist_name is None or itemhash is None:
|
if itemtype is None or playlist_name is None or itemhash is None:
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
if itemtype == "track":
|
if itemtype == "tracks":
|
||||||
trackhashes = [itemhash]
|
trackhashes = itemhash.split(",")
|
||||||
elif itemtype == "folder":
|
elif itemtype == "folder":
|
||||||
trackhashes = get_path_trackhashes(itemhash)
|
trackhashes = get_path_trackhashes(itemhash)
|
||||||
elif itemtype == "album":
|
elif itemtype == "album":
|
||||||
trackhashes = get_album_trackhashes(itemhash)
|
trackhashes = get_album_trackhashes(itemhash)
|
||||||
elif itemtype == "artist":
|
elif itemtype == "artist":
|
||||||
trackhashes = get_artist_trackhashes(itemhash)
|
trackhashes = get_artist_trackhashes(itemhash)
|
||||||
elif itemtype == "queue":
|
|
||||||
trackhashes = itemhash.split(",")
|
|
||||||
else:
|
else:
|
||||||
trackhashes = []
|
trackhashes = []
|
||||||
|
|
||||||
if len(trackhashes) == 0:
|
if len(trackhashes) == 0:
|
||||||
return {"error": "No tracks founds"}, 404
|
return {"error": "No tracks founds"}, 404
|
||||||
|
|
||||||
image = itemhash + ".webp" if itemtype != "folder" and itemtype != "queue" else None
|
image = itemhash + ".webp" if itemtype != "folder" and itemtype != "tracks" else None
|
||||||
|
|
||||||
playlist = insert_playlist(playlist_name, image)
|
playlist = insert_playlist(playlist_name, image)
|
||||||
|
|
||||||
if playlist is None:
|
if playlist is None:
|
||||||
return {"error": "Playlist could not be created"}, 500
|
return {"error": "Playlist could not be created"}, 500
|
||||||
|
|
||||||
if itemtype != "folder" and itemtype != "queue":
|
# save image
|
||||||
|
if itemtype != "folder" and itemtype != "tracks":
|
||||||
filename = itemhash + ".webp"
|
filename = itemhash + ".webp"
|
||||||
|
|
||||||
base_path = (
|
base_path = (
|
||||||
@ -444,6 +441,5 @@ def save_item_as_playlist():
|
|||||||
)
|
)
|
||||||
|
|
||||||
PL.add_tracks_to_playlist(playlist.id, trackhashes)
|
PL.add_tracks_to_playlist(playlist.id, trackhashes)
|
||||||
PL.update_last_updated(playlist.id)
|
|
||||||
|
|
||||||
return {"playlist": playlist}, 201
|
return {"playlist": playlist}, 201
|
||||||
|
@ -13,6 +13,14 @@ class SQLitePlaylistMethods:
|
|||||||
This class contains methods for interacting with the playlists table.
|
This class contains methods for interacting with the playlists table.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def update_last_updated(playlist_id: int):
|
||||||
|
"""Updates the last updated date of a playlist."""
|
||||||
|
sql = """UPDATE playlists SET last_updated = ? WHERE id = ?"""
|
||||||
|
|
||||||
|
with SQLiteManager(userdata_db=True) as cur:
|
||||||
|
cur.execute(sql, (create_new_date(), playlist_id))
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def insert_one_playlist(playlist: dict):
|
def insert_one_playlist(playlist: dict):
|
||||||
# banner_pos,
|
# banner_pos,
|
||||||
@ -92,8 +100,8 @@ class SQLitePlaylistMethods:
|
|||||||
|
|
||||||
# FIXME: Extract the "add_track_to_playlist" method to use it for both the artisthash and trackhash lists.
|
# FIXME: Extract the "add_track_to_playlist" method to use it for both the artisthash and trackhash lists.
|
||||||
|
|
||||||
@staticmethod
|
@classmethod
|
||||||
def add_item_to_json_list(playlist_id: int, field: str, items: set[str]):
|
def add_item_to_json_list(cls, playlist_id: int, field: str, items: set[str]):
|
||||||
"""
|
"""
|
||||||
Adds a string item to a json dumped list using a playlist id and field name.
|
Adds a string item to a json dumped list using a playlist id and field name.
|
||||||
Takes the playlist ID, a field name, an item to add to the field.
|
Takes the playlist ID, a field name, an item to add to the field.
|
||||||
@ -118,6 +126,8 @@ class SQLitePlaylistMethods:
|
|||||||
cur.execute(sql, (json.dumps(db_items), playlist_id))
|
cur.execute(sql, (json.dumps(db_items), playlist_id))
|
||||||
return len(items)
|
return len(items)
|
||||||
|
|
||||||
|
cls.update_last_updated(playlist_id)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def add_tracks_to_playlist(cls, playlist_id: int, trackhashes: list[str]):
|
def add_tracks_to_playlist(cls, playlist_id: int, trackhashes: list[str]):
|
||||||
"""
|
"""
|
||||||
@ -125,8 +135,8 @@ class SQLitePlaylistMethods:
|
|||||||
"""
|
"""
|
||||||
return cls.add_item_to_json_list(playlist_id, "trackhashes", trackhashes)
|
return cls.add_item_to_json_list(playlist_id, "trackhashes", trackhashes)
|
||||||
|
|
||||||
@staticmethod
|
@classmethod
|
||||||
def update_playlist(playlist_id: int, playlist: dict):
|
def update_playlist(cls, playlist_id: int, playlist: dict):
|
||||||
sql = """UPDATE playlists SET
|
sql = """UPDATE playlists SET
|
||||||
image = ?,
|
image = ?,
|
||||||
last_updated = ?,
|
last_updated = ?,
|
||||||
@ -145,13 +155,16 @@ class SQLitePlaylistMethods:
|
|||||||
with SQLiteManager(userdata_db=True) as cur:
|
with SQLiteManager(userdata_db=True) as cur:
|
||||||
cur.execute(sql, params)
|
cur.execute(sql, params)
|
||||||
|
|
||||||
@staticmethod
|
cls.update_last_updated(playlist_id)
|
||||||
def update_last_updated(playlist_id: int):
|
|
||||||
"""Updates the last updated date of a playlist."""
|
@classmethod
|
||||||
sql = """UPDATE playlists SET last_updated = ? WHERE id = ?"""
|
def update_settings(cls, playlist_id: int, settings: dict):
|
||||||
|
sql = """UPDATE playlists SET settings = ? WHERE id = ?"""
|
||||||
|
|
||||||
with SQLiteManager(userdata_db=True) as cur:
|
with SQLiteManager(userdata_db=True) as cur:
|
||||||
cur.execute(sql, (create_new_date(), playlist_id))
|
cur.execute(sql, (json.dumps(settings), playlist_id))
|
||||||
|
|
||||||
|
cls.update_last_updated(playlist_id)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def delete_playlist(pid: str):
|
def delete_playlist(pid: str):
|
||||||
@ -160,21 +173,6 @@ class SQLitePlaylistMethods:
|
|||||||
with SQLiteManager(userdata_db=True) as cur:
|
with SQLiteManager(userdata_db=True) as cur:
|
||||||
cur.execute(sql, (pid,))
|
cur.execute(sql, (pid,))
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def update_banner_pos(playlistid: int, pos: int):
|
|
||||||
playlist = SQLitePlaylistMethods.get_playlist_by_id(playlistid)
|
|
||||||
|
|
||||||
if playlist is None:
|
|
||||||
return
|
|
||||||
|
|
||||||
playlist.settings["banner_pos"] = pos
|
|
||||||
settings_str = json.dumps(playlist.settings)
|
|
||||||
|
|
||||||
sql = """UPDATE playlists SET settings = ? WHERE id = ?"""
|
|
||||||
|
|
||||||
with SQLiteManager(userdata_db=True) as cur:
|
|
||||||
cur.execute(sql, (settings_str, playlistid))
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def remove_banner(playlistid: int):
|
def remove_banner(playlistid: int):
|
||||||
sql = """UPDATE playlists SET image = NULL WHERE id = ?"""
|
sql = """UPDATE playlists SET image = NULL WHERE id = ?"""
|
||||||
@ -182,8 +180,8 @@ class SQLitePlaylistMethods:
|
|||||||
with SQLiteManager(userdata_db=True) as cur:
|
with SQLiteManager(userdata_db=True) as cur:
|
||||||
cur.execute(sql, (playlistid,))
|
cur.execute(sql, (playlistid,))
|
||||||
|
|
||||||
@staticmethod
|
@classmethod
|
||||||
def remove_tracks_from_playlist(playlistid: int, tracks: list[dict[str, int]]):
|
def remove_tracks_from_playlist(cls, playlistid: int, tracks: list[dict[str, int]]):
|
||||||
"""
|
"""
|
||||||
Removes tracks from a playlist by trackhash and position.
|
Removes tracks from a playlist by trackhash and position.
|
||||||
"""
|
"""
|
||||||
@ -211,3 +209,5 @@ class SQLitePlaylistMethods:
|
|||||||
trackhashes.remove(track["trackhash"])
|
trackhashes.remove(track["trackhash"])
|
||||||
|
|
||||||
cur.execute(sql, (json.dumps(trackhashes), playlistid))
|
cur.execute(sql, (json.dumps(trackhashes), playlistid))
|
||||||
|
|
||||||
|
cls.update_last_updated(playlistid)
|
||||||
|
@ -40,8 +40,8 @@ def extract_thumb(filepath: str, webp_path: str, overwrite=False) -> bool:
|
|||||||
img.resize((tsize, tsize), Image.ANTIALIAS).save(lg_img_path, "webp")
|
img.resize((tsize, tsize), Image.ANTIALIAS).save(lg_img_path, "webp")
|
||||||
img.resize((sm_tsize, sm_tsize), Image.ANTIALIAS).save(sm_img_path, "webp")
|
img.resize((sm_tsize, sm_tsize), Image.ANTIALIAS).save(sm_img_path, "webp")
|
||||||
|
|
||||||
if not overwrite and os.path.exists(lg_img_path):
|
if not overwrite and os.path.exists(sm_img_path):
|
||||||
img_size = os.path.getsize(lg_img_path)
|
img_size = os.path.getsize(sm_img_path)
|
||||||
|
|
||||||
if img_size > 0:
|
if img_size > 0:
|
||||||
return True
|
return True
|
||||||
|
@ -69,8 +69,6 @@ class AddSettingsToPlaylistTable(Migration):
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def migrate():
|
def migrate():
|
||||||
# existing_playlists = []
|
|
||||||
|
|
||||||
select_playlists_sql = "SELECT * FROM playlists"
|
select_playlists_sql = "SELECT * FROM playlists"
|
||||||
|
|
||||||
with SQLiteManager(userdata_db=True) as cur:
|
with SQLiteManager(userdata_db=True) as cur:
|
||||||
@ -117,6 +115,7 @@ class AddSettingsToPlaylistTable(Migration):
|
|||||||
"has_gif": False,
|
"has_gif": False,
|
||||||
"banner_pos": playlist[1],
|
"banner_pos": playlist[1],
|
||||||
"square_img": False,
|
"square_img": False,
|
||||||
|
"pinned": False,
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
@ -22,13 +22,15 @@ class Playlist:
|
|||||||
duration: int = 0
|
duration: int = 0
|
||||||
has_image: bool = False
|
has_image: bool = False
|
||||||
images: list[str] = dataclasses.field(default_factory=list)
|
images: list[str] = dataclasses.field(default_factory=list)
|
||||||
|
pinned: bool = False
|
||||||
|
|
||||||
def __post_init__(self):
|
def __post_init__(self):
|
||||||
self.trackhashes = json.loads(str(self.trackhashes))
|
self.trackhashes = json.loads(str(self.trackhashes))
|
||||||
self.count = len(self.trackhashes)
|
self.count = len(self.trackhashes)
|
||||||
|
|
||||||
if isinstance(self.settings, str):
|
if isinstance(self.settings, str):
|
||||||
self.settings = json.loads(self.settings)
|
self.settings = dict(json.loads(self.settings))
|
||||||
|
self.pinned = self.settings.get("pinned", False)
|
||||||
|
|
||||||
self.has_image = (
|
self.has_image = (
|
||||||
Path(settings.Paths.get_playlist_img_path()) / str(self.image)
|
Path(settings.Paths.get_playlist_img_path()) / str(self.image)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user