This commit is contained in:
team3
2026-09-17 15:40:28 +02:00
parent a1684cf54f
commit ea54a86db4
30 changed files with 3680 additions and 989 deletions

View File

@@ -1,8 +1,12 @@
"""Die Runde: wer mitmacht, und wer gerade wer ist.
Der Host pflegt die Namensliste. Alle anderen wählen sich einen davon aus.
Kein Passwort — für acht Freunde, die sich ohnehin über Discord hören, wäre
das nur eine Hürde ohne Nutzen.
Wer nicht will, dass ein anderer in seinem Namen bewertet, hinterlegt in
der Verwaltung einen Anmeldefilm. Dann muss man ihn beim Wechsel erst in
der Suche finden und anklicken. Kein Passwort im Klartext, nichts zu
merken außer einem Film — und für einen Filmabend unter Freunden genau die
richtige Hürde. Wer keinen Film hinterlegt, ist weiter offen für alle.
Die Zuordnung hängt an derselben Cookie-Sitzung wie Vorschläge und
Wertungen. Damit steht der Name serverseitig fest und kommt nicht mehr aus
@@ -26,18 +30,37 @@ CREATE TABLE IF NOT EXISTS user_sessions (
user_id INTEGER NOT NULL,
seit TEXT NOT NULL
);
-- Wer den Hostmodus eingeschaltet hat. Der Host führt durch den Abend und
-- wechselt die Namen frei, ohne jedes Mal den Anmeldefilm zu suchen.
CREATE TABLE IF NOT EXISTS host_sessions (
session_id TEXT PRIMARY KEY,
seit TEXT NOT NULL
);
"""
def init():
with connect() as conn:
conn.executescript(SCHEMA)
# Der Anmeldefilm kam später dazu
spalten = {r[1] for r in conn.execute("PRAGMA table_info(users)")}
if "auth_movie_id" not in spalten:
conn.execute("ALTER TABLE users ADD COLUMN auth_movie_id INTEGER")
def _oeffentlich(row):
"""Der hinterlegte Film verlässt den Server nie — sonst stünde das
Passwort im Netzwerk-Tab. Nach draußen geht nur, ob einer gesetzt ist."""
benutzer = dict(row)
benutzer["geschuetzt"] = benutzer.pop("auth_movie_id", None) is not None
return benutzer
def alle():
with connect() as conn:
rows = conn.execute("SELECT * FROM users ORDER BY name COLLATE NOCASE").fetchall()
return [dict(r) for r in rows]
return [_oeffentlich(r) for r in rows]
def anlegen(name):
@@ -59,7 +82,24 @@ def anlegen(name):
def von_name(name):
with connect() as conn:
row = conn.execute("SELECT * FROM users WHERE name = ?", (name,)).fetchone()
return dict(row) if row else None
return _oeffentlich(row) if row else None
def schutz_setzen(user_id, movie_id):
"""Anmeldefilm hinterlegen oder mit None wieder freigeben."""
with connect() as conn:
return conn.execute(
"UPDATE users SET auth_movie_id = ? WHERE id = ?", (movie_id, user_id)
).rowcount
def schutz_von(user_id):
"""Die hinterlegte Film-Kennung, oder None bei offenem Namen."""
with connect() as conn:
row = conn.execute(
"SELECT auth_movie_id FROM users WHERE id = ?", (user_id,)
).fetchone()
return row["auth_movie_id"] if row else None
def entfernen(user_id):
@@ -84,7 +124,7 @@ def waehlen(session_id, user_id):
datetime.now(timezone.utc).isoformat(timespec="seconds"),
),
)
return dict(da)
return _oeffentlich(da)
def abwaehlen(session_id):
@@ -103,7 +143,32 @@ def aktuell(session_id):
"WHERE s.session_id = ?",
(session_id,),
).fetchone()
return dict(row) if row else None
return _oeffentlich(row) if row else None
def ist_host(session_id):
with connect() as conn:
return bool(
conn.execute(
"SELECT 1 FROM host_sessions WHERE session_id = ?", (session_id,)
).fetchone()
)
def host_setzen(session_id, an):
"""Den Hostmodus merkt sich auch der Server — sonst könnte er den
Anmeldefilm nicht überspringen."""
with connect() as conn:
if an:
conn.execute(
"INSERT OR REPLACE INTO host_sessions (session_id, seit) VALUES (?, ?)",
(session_id, datetime.now(timezone.utc).isoformat(timespec="seconds")),
)
else:
conn.execute(
"DELETE FROM host_sessions WHERE session_id = ?", (session_id,)
)
return an
def besitzer(session_id):