""" Recommendations and releases routes for Ohm Stream Downloader API. """ import hashlib from datetime import datetime from typing import Optional from fastapi import APIRouter, Request, Query, HTTPException, Depends from fastapi.templating import Jinja2Templates from app.recommendation_engine import RecommendationEngine from app.models.auth import User from app.routers.router_auth import get_optional_user, get_current_user_from_token router = APIRouter(prefix="/api", tags=["recommendations"]) templates = Jinja2Templates(directory="templates") # Add custom filters to Jinja2 def hash_filter(s): return hashlib.md5(s.encode()).hexdigest()[:10] templates.env.filters["hash"] = hash_filter @router.get("/recommendations") async def get_recommendations( request: Request, limit: int = 15, html: bool = Query(False), current_user: Optional[User] = Depends(get_optional_user), ): """Get personalized anime recommendations based on download history""" is_htmx = request.headers.get("HX-Request") if current_user is None and (html or is_htmx): return templates.TemplateResponse( "components/login_prompt.html", {"request": request} ) if current_user is None: raise HTTPException(status_code=401, detail="Authentication required") engine = RecommendationEngine(download_dir="downloads") try: recommendations = await engine.get_personalized_recommendations(limit=limit) if html or is_htmx: return templates.TemplateResponse( "components/recommendations_list.html", {"request": request, "recommendations": recommendations} ) return {"recommendations": recommendations, "count": len(recommendations)} except Exception as e: import logging logging.getLogger(__name__).error(f"Recommendations error: {e}", exc_info=True) raise HTTPException(status_code=500, detail=str(e)) finally: await engine.close() @router.get("/releases/latest") async def get_latest_releases( request: Request, limit: int = 20, html: bool = Query(False), ): """Get latest anime releases""" from app.recommendations import get_latest_releases_with_info try: releases = await get_latest_releases_with_info(limit=limit) if html or request.headers.get("HX-Request"): return templates.TemplateResponse( "components/releases_list.html", {"request": request, "releases": releases} ) return { "releases": releases, "count": len(releases), "updated": datetime.now().isoformat(), } except Exception as e: import logging logging.getLogger(__name__).error(f"Latest releases error: {e}", exc_info=True) raise HTTPException(status_code=500, detail=str(e)) @router.get("/releases/seasonal") async def get_seasonal_anime( year: Optional[int] = None, season: Optional[str] = None, ): """Get current/previously seasonal anime""" from app.recommendations import AnimeReleasesFetcher fetcher = AnimeReleasesFetcher() try: anime = await fetcher.get_seasonal_anime(year, season) return { "anime": anime, "count": len(anime), "year": year or datetime.now().year, "season": season or "current", } except Exception as e: raise HTTPException(status_code=500, detail=str(e)) finally: await fetcher.close() @router.get("/releases/scheduled") async def get_scheduled_anime(day: Optional[str] = None): """Get anime scheduled for a specific day""" from app.recommendations import AnimeReleasesFetcher fetcher = AnimeReleasesFetcher() try: anime = await fetcher.get_scheduled_anime(day) return {"anime": anime, "count": len(anime), "day": day or "today"} except Exception as e: raise HTTPException(status_code=500, detail=str(e)) finally: await fetcher.close() @router.get("/releases/top") async def get_top_anime( type: str = "tv", limit: int = 15, ): """Get top rated anime""" from app.recommendations import AnimeReleasesFetcher fetcher = AnimeReleasesFetcher() try: anime = await fetcher.get_top_anime(type=type, limit=limit) return {"anime": anime, "count": len(anime)} except Exception as e: raise HTTPException(status_code=500, detail=str(e)) finally: await fetcher.close() @router.get("/stats/downloads") async def get_download_statistics( current_user: User = Depends(get_current_user_from_token), ): """Get download statistics and preferences""" engine = RecommendationEngine(download_dir="downloads") try: stats = await engine.get_download_stats() return stats except Exception as e: raise HTTPException(status_code=500, detail=str(e)) finally: await engine.close()