Files
horror/backend/app/wishlist.py
2026-09-09 17:58:52 +02:00

125 lines
3.8 KiB
Python

"""Was jeder für sich sehen möchte.
Alle sehen alle Sammlungen — man merkt so, worauf die anderen Lust haben.
Ändern darf jeder nur die eigene. Der Vorschlag fürs Rad ist eine andere
Sache: davon gibt es einen je Person, und er landet im Glücksrad.
Titel und Poster kommen mit in die Zeile. Ein gemerkter Film soll lesbar
bleiben, auch wenn er nie im Katalog stand oder Netflix ihn abgibt.
"""
import json
import sqlite3
from datetime import datetime, timezone
from .db import connect
from .users import besitzer, gehoert_mir
SCHEMA = """
CREATE TABLE IF NOT EXISTS wishlist (
id INTEGER PRIMARY KEY AUTOINCREMENT,
session_id TEXT NOT NULL,
movie_id INTEGER NOT NULL,
title TEXT NOT NULL,
year INTEGER,
poster_path TEXT,
created_at TEXT NOT NULL,
UNIQUE (session_id, movie_id)
);
"""
def _spalte_user_id(conn, tabelle):
"""Nachrüsten und aus der Sitzung füllen — einmalig je Datenbank."""
spalten = {r[1] for r in conn.execute(f"PRAGMA table_info({tabelle})")}
if "user_id" in spalten:
return
conn.execute(f"ALTER TABLE {tabelle} ADD COLUMN user_id INTEGER")
conn.execute(
f"UPDATE {tabelle} SET user_id = ("
" SELECT user_id FROM user_sessions s WHERE s.session_id = "
f" {tabelle}.session_id)"
)
def init():
with connect() as conn:
conn.executescript(SCHEMA)
_spalte_user_id(conn, "wishlist")
def alle(session_id):
"""Alle Sammlungen, jede mit dem Namen ihres Besitzers."""
with connect() as conn:
rows = conn.execute(
# Genres kommen aus dem Katalog. Ein Film, der nie darin stand,
# hat keine — das Rad behandelt ihn dann als "nicht Horror".
"SELECT w.*, u.name, m.genres FROM wishlist w "
"LEFT JOIN user_sessions s ON s.session_id = w.session_id "
"LEFT JOIN users u ON u.id = s.user_id "
"LEFT JOIN movies m ON m.id = w.movie_id "
"ORDER BY w.created_at DESC"
).fetchall()
ich = besitzer(session_id)
return [
{
**{
k: v
for k, v in dict(r).items()
if k not in ("session_id", "user_id", "genres")
},
"genres": json.loads(r["genres"]) if r["genres"] else [],
"mine": gehoert_mir(r, session_id, ich),
}
for r in rows
]
def merken(session_id, movie):
"""Ein zweites Mal merken ändert nichts."""
try:
with connect() as conn:
conn.execute(
"INSERT INTO wishlist "
"(session_id, user_id, movie_id, title, year, poster_path, "
"created_at) VALUES (?, ?, ?, ?, ?, ?, ?)",
(
session_id,
besitzer(session_id),
movie["id"],
movie["title"],
movie.get("year"),
movie.get("poster_path"),
datetime.now(timezone.utc).isoformat(timespec="seconds"),
),
)
except sqlite3.IntegrityError:
pass
return alle(session_id)
# Mit Namen zählt der Name, ohne Namen die Sitzung
WEM = "(user_id = ? OR (? IS NULL AND user_id IS NULL AND session_id = ?))"
def vergessen(session_id, movie_id):
ich = besitzer(session_id)
with connect() as conn:
return conn.execute(
f"DELETE FROM wishlist WHERE {WEM} AND movie_id = ?",
(ich, ich, session_id, movie_id),
).rowcount
def ids(session_id):
"""movie_ids der gemerkten Filme, für die Detailansicht."""
ich = besitzer(session_id)
with connect() as conn:
return [
r["movie_id"]
for r in conn.execute(
f"SELECT movie_id FROM wishlist WHERE {WEM}",
(ich, ich, session_id),
)
]