playlist edition

This commit is contained in:
Gabriel Radureau
2025-10-13 16:53:15 +02:00
parent 0fa5a30809
commit 65d63ec828
15 changed files with 550 additions and 137 deletions

102
app/db.py
View File

@@ -7,6 +7,7 @@ DB_PATH = Path.home() / "Documents/.DanceVideos/db.sqlite"
def get_conn():
conn = sqlite3.connect(DB_PATH, timeout=30, check_same_thread=False)
conn.row_factory = sqlite3.Row
conn.execute("PRAGMA foreign_keys = ON;")
return conn
@@ -101,52 +102,111 @@ def search_videos(
address_keyword=None,
start_date=None,
end_date=None,
difficulty=None
difficulty=None,
label_logic="OR",
):
"""
Retourne une DataFrame filtrée selon les critères fournis.
label_logic: "OR" (au moins un label) ou "AND" (tous les labels).
"""
label_names = label_names or []
query = """
SELECT DISTINCT v.*
FROM videos v
LEFT JOIN video_labels vl ON vl.video_file_name = v.file_name
LEFT JOIN labels l ON l.id = vl.label_id
WHERE 1=1
"""
params = []
# 🔖 Filtres par label (tous doivent être présents)
base_query = """
SELECT DISTINCT v.*
FROM videos v
WHERE 1=1
"""
# 🔖 Filtres par label
if label_names:
placeholders = ",".join("?" for _ in label_names)
query += f" AND l.name IN ({placeholders})"
params += label_names
if label_logic == "AND":
# Toutes les étiquettes doivent être présentes
placeholders = ",".join("?" * len(label_names))
base_query += f"""
AND 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})
GROUP BY vl.video_file_name
HAVING COUNT(DISTINCT l.name) = {len(label_names)}
)
"""
params.extend(label_names)
else:
# OR : au moins une étiquette correspond
placeholders = ",".join("?" * len(label_names))
base_query += f"""
AND 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.extend(label_names)
# 📆 Jour de la semaine
if day_of_week:
query += " AND v.day_of_week = ?"
base_query += " AND v.day_of_week = ?"
params.append(day_of_week)
# 🗺️ Mot-clé d'adresse (et exclusion unknown)
if address_keyword:
query += " AND v.address NOT LIKE '%unknown%' AND v.address LIKE ?"
base_query += " AND v.address NOT LIKE '%unknown%' AND v.address LIKE ?"
params.append(f"%{address_keyword}%")
# 📅 Filtre par date
# 📅 Plage de dates
if start_date:
query += " AND v.record_datetime >= ?"
base_query += " AND v.record_datetime >= ?"
params.append(start_date)
if end_date:
query += " AND v.record_datetime <= ?"
base_query += " AND v.record_datetime <= ?"
params.append(end_date)
# 💪 Niveau de difficulté
if difficulty and difficulty != "Tous":
query += " AND v.difficulty_level = ?"
base_query += " AND v.difficulty_level = ?"
params.append(difficulty)
query += " ORDER BY v.record_datetime DESC"
# 🔽 Tri
base_query += " ORDER BY v.record_datetime DESC"
with get_conn() as conn:
return pd.read_sql_query(query, conn, params=params)
return pd.read_sql_query(base_query, conn, params=params)
def get_video_playlists(file_name):
with get_conn() as conn:
query = """
SELECT p.name
FROM playlists p
JOIN video_playlists vp ON vp.playlist_id = p.id
WHERE vp.video_file_name = ?
"""
return [row[0] for row in conn.execute(query, (file_name,))]
def get_videos_in_playlist(playlist_id):
with get_conn() as conn:
query = """
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(query, (playlist_id,)).fetchall()
def add_video_to_playlist(playlist_id, file_name):
with get_conn() as conn:
conn.execute("""
INSERT OR IGNORE INTO video_playlists (video_file_name, playlist_id, position)
VALUES (?, ?, COALESCE((SELECT MAX(position)+1 FROM video_playlists WHERE playlist_id=?), 0))
""", (file_name, playlist_id, playlist_id))
conn.commit()
def remove_video_from_playlist(playlist_id, file_name):
with get_conn() as conn:
conn.execute("DELETE FROM video_playlists WHERE playlist_id=? AND video_file_name=?", (playlist_id, file_name))
conn.commit()