"""BAN YARO — Hunde-Filme Routes""" from fastapi import APIRouter, Depends, HTTPException from pydantic import BaseModel from typing import Optional from datetime import datetime from database import db from auth import get_current_user, get_current_user_optional router = APIRouter() # ------------------------------------------------------------------ # Hardcoded Film-Daten # ------------------------------------------------------------------ FILME = [ {"id": "lassie", "titel": "Lassie", "jahr": 1943, "genre": "Familie", "hund_rasse": "Collie", "stirbt_der_hund": False, "beschreibung": "Der Klassiker schlechthin. Lassie findet immer nach Hause.", "bild_emoji": "🐕", "bewertung_avg": 4.2}, {"id": "benji", "titel": "Benji", "jahr": 1974, "genre": "Familie", "hund_rasse": "Mischling", "stirbt_der_hund": False, "beschreibung": "Ein herrenloser Hund rettet Kinder aus den Händen von Entführern.", "bild_emoji": "🐾", "bewertung_avg": 4.0}, {"id": "marley-and-me", "titel": "Marley & Ich", "jahr": 2008, "genre": "Drama/Komödie", "hund_rasse": "Labrador", "stirbt_der_hund": True, "beschreibung": "Der chaotischste, aber liebste Labrador der Welt. Achtung: Taschentücher bereithalten.", "bild_emoji": "😭", "bewertung_avg": 4.5}, {"id": "hachiko", "titel": "Hachi: A Dog's Tale", "jahr": 2009, "genre": "Drama", "hund_rasse": "Akita", "stirbt_der_hund": True, "beschreibung": "Basiert auf der wahren Geschichte des treuen Akita Hachikō. Starke emotionale Wirkung.", "bild_emoji": "💔", "bewertung_avg": 4.8}, {"id": "101-dalmatiner", "titel": "101 Dalmatiner", "jahr": 1961, "genre": "Animation/Familie", "hund_rasse": "Dalmatiner", "stirbt_der_hund": False, "beschreibung": "Dalmatiner-Welpen vs. die böse Cruella de Vil. Animationsklassiker.", "bild_emoji": "🐡", "bewertung_avg": 4.3}, {"id": "beethoven", "titel": "Beethoven", "jahr": 1992, "genre": "Familie/Komödie", "hund_rasse": "Bernhardiner", "stirbt_der_hund": False, "beschreibung": "Riesiger Bernhardiner bringt Chaos ins Familienleben. Mehrere Fortsetzungen.", "bild_emoji": "🎵", "bewertung_avg": 3.8}, {"id": "rex", "titel": "Kommissar Rex", "jahr": 1994, "genre": "Krimi/Serie", "hund_rasse": "Deutscher Schäferhund", "stirbt_der_hund": False, "beschreibung": "Österreichische Krimiserie. Rex löst gemeinsam mit seinem Herrchen Verbrechen.", "bild_emoji": "🔍", "bewertung_avg": 4.1}, {"id": "old-yeller", "titel": "Old Yeller", "jahr": 1957, "genre": "Familie/Drama", "hund_rasse": "Mischling", "stirbt_der_hund": True, "beschreibung": "Amerikanischer Filmklassiker. Berühmtestes Filmende der Hundfilm-Geschichte.", "bild_emoji": "🌾", "bewertung_avg": 4.0}, {"id": "buddy", "titel": "Air Bud", "jahr": 1997, "genre": "Familie/Sport", "hund_rasse": "Golden Retriever", "stirbt_der_hund": False, "beschreibung": "Hund spielt Basketball. Klingt absurd, wurde ein Hit.", "bild_emoji": "🏀", "bewertung_avg": 3.5}, {"id": "john-wick", "titel": "John Wick", "jahr": 2014, "genre": "Action", "hund_rasse": "Beagle", "stirbt_der_hund": True, "beschreibung": "Achtung Spoiler: Der Hund stirbt am Anfang. Das löst die ganze Geschichte aus. Kontroversiell beliebt.", "bild_emoji": "💣", "bewertung_avg": 4.6}, {"id": "isle-of-dogs", "titel": "Isle of Dogs", "jahr": 2018, "genre": "Animation", "hund_rasse": "Verschiedene", "stirbt_der_hund": False, "beschreibung": "Wes Anderson Stopmotion-Meisterwerk. Alle Hunde Japans auf einer Insel verbannt.", "bild_emoji": "🏝️", "bewertung_avg": 4.4}, {"id": "eight-below", "titel": "8 Below", "jahr": 2006, "genre": "Abenteuer/Drama", "hund_rasse": "Schlittenhunde", "stirbt_der_hund": True, "beschreibung": "Basiert auf wahren Ereignissen. Schlittenhunde überleben die Antarktis. Einige nicht.", "bild_emoji": "❄️", "bewertung_avg": 4.3}, ] PROMIS = [ {"name": "Hachikō", "rasse": "Akita Inu", "bekannt_fuer": "9 Jahre lang täglich auf seinen verstorbenen Herrchen am Bahnhof Shibuya gewartet. Statue in Tokio.", "emoji": "🗿"}, {"name": "Rin Tin Tin", "rasse": "Deutscher Schäferhund", "bekannt_fuer": "Filmhund der 1920er-Jahre. Rettete Warner Bros. vor dem Bankrott. Erster Hundestar Hollywoods.", "emoji": "🎬"}, {"name": "Laika", "rasse": "Mischling", "bekannt_fuer": "Erstes Lebewesen im Weltall (Sputnik 2, 1957). Wurde zur sowjetischen Weltraumpionierin.", "emoji": "🚀"}, {"name": "Endal", "rasse": "Labrador", "bekannt_fuer": "Assistenzhund in England. Erster Hund der eine EC-Karte am Geldautomaten benutzte.", "emoji": "💳"}, {"name": "Barry", "rasse": "Bernhardiner", "bekannt_fuer": "Legendärer Rettungshund der Alpen (1800–1812). Soll 40 Menschen das Leben gerettet haben.", "emoji": "🏔️"}, {"name": "Greyfriars Bobby", "rasse": "Skye Terrier", "bekannt_fuer": "14 Jahre lang das Grab seines Herrchens in Edinburgh bewacht. Statue und Pub benannt nach ihm.", "emoji": "⛪"}, ] # ------------------------------------------------------------------ # Schemas # ------------------------------------------------------------------ class FilmVoteRequest(BaseModel): bewertung: int # 1–5 class HundDesMonatsVoteRequest(BaseModel): dog_id: int # ------------------------------------------------------------------ # GET /api/movies/filme — Film-Liste mit optionaler User-Bewertung # ------------------------------------------------------------------ @router.get("/filme") async def get_filme(user=Depends(get_current_user_optional)): user_ratings = {} community_avgs = {} with db() as conn: if user: rows = conn.execute( "SELECT film_id, bewertung FROM movie_votes WHERE user_id=?", (user["id"],), ).fetchall() user_ratings = {r["film_id"]: r["bewertung"] for r in rows} avg_rows = conn.execute( "SELECT film_id, AVG(bewertung) as avg_bew, COUNT(*) as cnt FROM movie_votes GROUP BY film_id" ).fetchall() community_avgs = {r["film_id"]: {"avg": round(r["avg_bew"], 1), "cnt": r["cnt"]} for r in avg_rows} result = [] for film in FILME: f = dict(film) f["user_rating"] = user_ratings.get(film["id"]) if film["id"] in community_avgs: f["bewertung_avg"] = community_avgs[film["id"]]["avg"] f["bewertung_cnt"] = community_avgs[film["id"]]["cnt"] else: f["bewertung_cnt"] = 0 result.append(f) return result # ------------------------------------------------------------------ # POST /api/movies/filme/{film_id}/vote — Bewertung abgeben (Upsert) # ------------------------------------------------------------------ @router.post("/filme/{film_id}/vote") async def vote_film(film_id: str, data: FilmVoteRequest, user=Depends(get_current_user)): if not any(f["id"] == film_id for f in FILME): raise HTTPException(404, "Film nicht gefunden.") if data.bewertung < 1 or data.bewertung > 5: raise HTTPException(400, "Bewertung muss zwischen 1 und 5 liegen.") with db() as conn: conn.execute( """INSERT INTO movie_votes (user_id, film_id, bewertung) VALUES (?, ?, ?) ON CONFLICT(user_id, film_id) DO UPDATE SET bewertung=excluded.bewertung""", (user["id"], film_id, data.bewertung), ) row = conn.execute( "SELECT AVG(bewertung) as avg_bew, COUNT(*) as cnt FROM movie_votes WHERE film_id=?", (film_id,), ).fetchone() return { "film_id": film_id, "bewertung_avg": round(row["avg_bew"], 1) if row["avg_bew"] else data.bewertung, "bewertung_cnt": row["cnt"], "user_rating": data.bewertung, } # ------------------------------------------------------------------ # GET /api/movies/hund-des-monats — Top-Votes des aktuellen Monats # ------------------------------------------------------------------ @router.get("/hund-des-monats") async def get_hund_des_monats(user=Depends(get_current_user_optional)): monat = datetime.now().strftime("%Y-%m") with db() as conn: rows = conn.execute( """SELECT d.id, d.name, d.rasse, d.foto_url, u.name as besitzer_name, COUNT(v.id) as stimmen FROM hund_des_monats_votes v JOIN dogs d ON d.id = v.dog_id JOIN users u ON u.id = d.user_id WHERE v.monat = ? GROUP BY v.dog_id ORDER BY stimmen DESC LIMIT 10""", (monat,), ).fetchall() user_vote = None if user: row = conn.execute( "SELECT dog_id FROM hund_des_monats_votes WHERE user_id=? AND monat=?", (user["id"], monat), ).fetchone() if row: user_vote = row["dog_id"] return { "monat": monat, "top": [dict(r) for r in rows], "user_vote": user_vote, } # ------------------------------------------------------------------ # POST /api/movies/hund-des-monats/vote — Abstimmen (Auth required) # ------------------------------------------------------------------ @router.post("/hund-des-monats/vote") async def vote_hund_des_monats(data: HundDesMonatsVoteRequest, user=Depends(get_current_user)): monat = datetime.now().strftime("%Y-%m") with db() as conn: # Prüfen ob Hund existiert und entweder dem User gehört oder öffentlich ist dog = conn.execute( "SELECT id, user_id, is_public FROM dogs WHERE id=?", (data.dog_id,), ).fetchone() if not dog: raise HTTPException(404, "Hund nicht gefunden.") if dog["user_id"] != user["id"] and not dog["is_public"]: raise HTTPException(403, "Dieser Hund ist nicht öffentlich.") conn.execute( """INSERT INTO hund_des_monats_votes (user_id, dog_id, monat) VALUES (?, ?, ?) ON CONFLICT(user_id, monat) DO UPDATE SET dog_id=excluded.dog_id""", (user["id"], data.dog_id, monat), ) # Aktuelle Stimmenanzahl für den gewählten Hund row = conn.execute( "SELECT COUNT(*) as cnt FROM hund_des_monats_votes WHERE dog_id=? AND monat=?", (data.dog_id, monat), ).fetchone() return {"dog_id": data.dog_id, "monat": monat, "stimmen": row["cnt"]}