Files
DanceVideos/app/playlists/playlist_db.py
Gabriel Radureau 65d63ec828 playlist edition
2025-10-13 16:53:15 +02:00

96 lines
4.5 KiB
Python

# playlists/playlist_db.py
import db
import json
from playlists.playlist_model import Playlist, RuleSet
def load_all_playlists():
"""Retourne une liste de Playlist (Pydantic) — tolérant aux rules_json nuls / vides."""
with db.get_conn() as conn:
# s'assurer que les lignes sont accessibles par nom (si get_conn ne l'a pas fait)
try:
conn.row_factory = conn.row_factory # no-op si déjà réglé
except Exception:
pass
rows = conn.execute("SELECT * FROM playlists ORDER BY created_at DESC").fetchall()
playlists = []
for row in rows:
# si row est sqlite3.Row, on peut accéder par nom, sinon c'est un tuple et on mappe par index
if hasattr(row, "__getitem__") and isinstance(row, dict) is False and getattr(row, "keys", None):
# sqlite3.Row behaves like mapping
row_dict = {k: row[k] for k in row.keys()}
elif isinstance(row, dict):
row_dict = row
else:
# fallback: convert tuple -> dict using cursor.description
# but here we assume conn.row_factory set in db.get_conn; keep robust fallback
cols = [d[0] for d in conn.execute("PRAGMA table_info(playlists)").fetchall()]
row_dict = dict(zip(cols, row))
try:
pl = Playlist(
id=row_dict.get("id"),
name=row_dict.get("name") or "",
description=row_dict.get("description") or "",
type=row_dict.get("type") or "manual",
rules=row_dict.get("rules_json")
)
playlists.append(pl)
except Exception as e:
# Ne bloque pas toute la lecture : logue et passe à la suivante
print(f"⚠️ Ignored invalid playlist row (id={row_dict.get('id')}, name={row_dict.get('name')}): {e}")
return playlists
def delete_playlist(playlist_id):
with db.get_conn() as conn:
conn.execute("DELETE FROM playlists WHERE id = ?", (playlist_id,))
conn.commit()
def get_videos_for_playlist(playlist: Playlist):
"""Retourne les vidéos selon le type"""
with db.get_conn() as conn:
if playlist.type == "manual":
q = """
SELECT v.*
FROM videos v
JOIN video_playlists vp ON vp.video_file_name = v.file_name
WHERE vp.playlist_id = ?
ORDER BY vp.position
"""
return conn.execute(q, (playlist.id,)).fetchall()
else:
rules = playlist.rules
clauses = []
params = []
if rules.include_labels:
placeholders = ",".join("?" * len(rules.include_labels))
clauses.append(f"v.file_name IN (SELECT vl.video_file_name FROM video_labels vl JOIN labels l ON l.id=vl.label_id WHERE l.name IN ({placeholders}))")
params += rules.include_labels
if rules.exclude_labels:
placeholders = ",".join("?" * len(rules.exclude_labels))
clauses.append(f"v.file_name NOT IN (SELECT vl.video_file_name FROM video_labels vl JOIN labels l ON l.id=vl.label_id WHERE l.name IN ({placeholders}))")
params += rules.exclude_labels
if rules.include_playlists:
placeholders = ",".join("?" * len(rules.include_playlists))
clauses.append(f"v.file_name IN (SELECT vp.video_file_name FROM video_playlists vp JOIN playlists p ON vp.playlist_id=p.id WHERE p.name IN ({placeholders}))")
params += rules.include_playlists
if rules.exclude_playlists:
placeholders = ",".join("?" * len(rules.exclude_playlists))
clauses.append(f"v.file_name NOT IN (SELECT vp.video_file_name FROM video_playlists vp JOIN playlists p ON vp.playlist_id=p.id WHERE p.name IN ({placeholders}))")
params += rules.exclude_playlists
if rules.date_after:
clauses.append("v.record_datetime >= ?")
params.append(rules.date_after)
if rules.date_before:
clauses.append("v.record_datetime <= ?")
params.append(rules.date_before)
where_clause = f" {' AND ' if rules.logic == 'AND' else ' OR '} ".join(clauses) if clauses else "1=1"
q = f"SELECT v.* FROM videos v WHERE {where_clause} ORDER BY v.record_datetime DESC"
return conn.execute(q, params).fetchall()