""" 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 from fastapi.templating import Jinja2Templates from app.recommendation_engine import RecommendationEngine 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), ): """Get personalized anime recommendations based on download history""" engine = RecommendationEngine(download_dir="downloads") try: recommendations = await engine.get_personalized_recommendations(limit=limit) if html or request.headers.get("HX-Request"): 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(): """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()