swingmusic/app/db/sqlite/playlists.py
mungai-njoroge e3a61c109b implement pinning playlists
+ update migrations to add pinned attr to plalist
+ misc
2023-08-22 15:36:43 +03:00

214 lines
6.3 KiB
Python

import json
from collections import OrderedDict
from app.db.sqlite.tracks import SQLiteTrackMethods
from app.db.sqlite.utils import SQLiteManager, tuple_to_playlist, tuples_to_playlists
from app.models import Artist
from app.utils.dates import create_new_date
from app.utils.threading import background
class SQLitePlaylistMethods:
"""
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
def insert_one_playlist(playlist: dict):
# banner_pos,
# has_gif,
sql = """INSERT INTO playlists(
image,
last_updated,
name,
settings,
trackhashes
) VALUES(:image, :last_updated, :name, :settings, :trackhashes)
"""
playlist = OrderedDict(sorted(playlist.items()))
with SQLiteManager(userdata_db=True) as cur:
cur.execute(sql, playlist)
pid = cur.lastrowid
cur.close()
p_tuple = (pid, *playlist.values())
return tuple_to_playlist(p_tuple)
@staticmethod
def get_playlist_by_name(name: str):
sql = "SELECT * FROM playlists WHERE name = ?"
with SQLiteManager(userdata_db=True) as cur:
cur.execute(sql, (name,))
data = cur.fetchone()
cur.close()
if data is not None:
return tuple_to_playlist(data)
return None
@staticmethod
def count_playlist_by_name(name: str):
sql = "SELECT COUNT(*) FROM playlists WHERE name = ?"
with SQLiteManager(userdata_db=True) as cur:
cur.execute(sql, (name,))
data = cur.fetchone()
cur.close()
return int(data[0])
@staticmethod
def get_all_playlists():
with SQLiteManager(userdata_db=True) as cur:
cur.execute("SELECT * FROM playlists")
playlists = cur.fetchall()
cur.close()
if playlists is not None:
return tuples_to_playlists(playlists)
return []
@staticmethod
def get_playlist_by_id(playlist_id: int):
sql = "SELECT * FROM playlists WHERE id = ?"
with SQLiteManager(userdata_db=True) as cur:
cur.execute(sql, (playlist_id,))
data = cur.fetchone()
cur.close()
if data is not None:
return tuple_to_playlist(data)
return None
# FIXME: Extract the "add_track_to_playlist" method to use it for both the artisthash and trackhash lists.
@classmethod
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.
Takes the playlist ID, a field name, an item to add to the field.
"""
sql = f"SELECT {field} FROM playlists WHERE id = ?"
with SQLiteManager(userdata_db=True) as cur:
cur.execute(sql, (playlist_id,))
data = cur.fetchone()
if data is not None:
db_items: list[str] = json.loads(data[0])
# Remove duplicates, without changing the order.
for item in items:
if item in db_items:
items.remove(item)
db_items.extend(items)
sql = f"UPDATE playlists SET {field} = ? WHERE id = ?"
cur.execute(sql, (json.dumps(db_items), playlist_id))
return len(items)
cls.update_last_updated(playlist_id)
@classmethod
def add_tracks_to_playlist(cls, playlist_id: int, trackhashes: list[str]):
"""
Adds trackhashes to a playlist
"""
return cls.add_item_to_json_list(playlist_id, "trackhashes", trackhashes)
@classmethod
def update_playlist(cls, playlist_id: int, playlist: dict):
sql = """UPDATE playlists SET
image = ?,
last_updated = ?,
name = ?,
settings = ?
WHERE id = ?
"""
del playlist["id"]
del playlist["trackhashes"]
playlist["settings"] = json.dumps(playlist["settings"])
playlist = OrderedDict(sorted(playlist.items()))
params = (*playlist.values(), playlist_id)
with SQLiteManager(userdata_db=True) as cur:
cur.execute(sql, params)
cls.update_last_updated(playlist_id)
@classmethod
def update_settings(cls, playlist_id: int, settings: dict):
sql = """UPDATE playlists SET settings = ? WHERE id = ?"""
with SQLiteManager(userdata_db=True) as cur:
cur.execute(sql, (json.dumps(settings), playlist_id))
cls.update_last_updated(playlist_id)
@staticmethod
def delete_playlist(pid: str):
sql = "DELETE FROM playlists WHERE id = ?"
with SQLiteManager(userdata_db=True) as cur:
cur.execute(sql, (pid,))
@staticmethod
def remove_banner(playlistid: int):
sql = """UPDATE playlists SET image = NULL WHERE id = ?"""
with SQLiteManager(userdata_db=True) as cur:
cur.execute(sql, (playlistid,))
@classmethod
def remove_tracks_from_playlist(cls, playlistid: int, tracks: list[dict[str, int]]):
"""
Removes tracks from a playlist by trackhash and position.
"""
sql = """UPDATE playlists SET trackhashes = ? WHERE id = ?"""
with SQLiteManager(userdata_db=True) as cur:
cur.execute("SELECT trackhashes FROM playlists WHERE id = ?", (playlistid,))
data = cur.fetchone()
if data is None:
return
trackhashes: list[str] = json.loads(data[0])
for track in tracks:
# {
# trackhash: str;
# index: int;
# }
index = trackhashes.index(track["trackhash"])
if index == track["index"]:
trackhashes.remove(track["trackhash"])
cur.execute(sql, (json.dumps(trackhashes), playlistid))
cls.update_last_updated(playlistid)