Spaces:
Runtime error
Runtime error
| """Analytics API - إحصائيات وتحليلات المستخدم""" | |
| from fastapi import APIRouter, HTTPException, Request | |
| from database import fetch_one, fetch_all | |
| from auth import get_current_user | |
| router = APIRouter() | |
| async def _resolve_user(request: Request) -> dict: | |
| user_data = await get_current_user(request) | |
| user = await fetch_one("SELECT * FROM users WHERE user_id = ?", [str(user_data["id"])]) | |
| if not user: | |
| raise HTTPException(status_code=404, detail="User not found") | |
| return user | |
| async def get_user_stats(request: Request): | |
| """Get comprehensive user statistics""" | |
| user = await _resolve_user(request) | |
| db_id = str(user["id"]) | |
| total_movies = await fetch_one("SELECT COUNT(*) as cnt FROM watch_history WHERE user_id=? AND media_type='movie'", [db_id]) | |
| total_series = await fetch_one("SELECT COUNT(DISTINCT tmdb_id) as cnt FROM watch_history WHERE user_id=? AND media_type='tv'", [db_id]) | |
| total_watch_time = await fetch_one("SELECT COALESCE(SUM(duration_seconds), 0) as total FROM watch_history WHERE user_id=?", [db_id]) | |
| avg_rating = await fetch_one("SELECT COALESCE(AVG(rating), 0) as avg FROM ratings WHERE user_id=?", [db_id]) | |
| total_reviews = await fetch_one("SELECT COUNT(*) as cnt FROM comments WHERE user_id=?", [db_id]) | |
| achievements = await fetch_one("SELECT COUNT(*) as cnt FROM user_achievements WHERE user_id=? AND is_unlocked=1", [db_id]) | |
| streak = await fetch_one("SELECT streak_count FROM daily_streaks WHERE user_id=?", [db_id]) | |
| return {"ok": True, "data": { | |
| "total_movies": total_movies["cnt"] if total_movies else 0, | |
| "total_series": total_series["cnt"] if total_series else 0, | |
| "total_watch_time": total_watch_time["total"] if total_watch_time else 0, | |
| "average_rating": round(float(avg_rating["avg"] if avg_rating else 0), 1), | |
| "total_reviews": total_reviews["cnt"] if total_reviews else 0, | |
| "achievements_unlocked": achievements["cnt"] if achievements else 0, | |
| "current_streak": streak["streak_count"] if streak else 0, | |
| }} | |
| async def get_genre_breakdown(request: Request): | |
| """Get genre distribution from watch history""" | |
| user = await _resolve_user(request) | |
| rows = await fetch_all(""" | |
| SELECT a.genres, COUNT(*) as count FROM watch_history wh | |
| JOIN archives a ON wh.tmdb_id = a.media_id | |
| WHERE wh.user_id=? AND a.genres != '' | |
| GROUP BY a.genres ORDER BY count DESC""", [str(user["id"])]) | |
| genre_counts = {} | |
| for r in rows: | |
| for g in (r["genres"] or "").split(","): | |
| g = g.strip() | |
| if g: | |
| genre_counts[g] = genre_counts.get(g, 0) + r["count"] | |
| total = sum(genre_counts.values()) or 1 | |
| data = [{"genre": k, "count": v, "percentage": round(v / total * 100, 1)} for k, v in sorted(genre_counts.items(), key=lambda x: -x[1])] | |
| return {"ok": True, "data": data} | |
| async def get_activity_history(request: Request): | |
| """Get recent user activity""" | |
| user = await _resolve_user(request) | |
| activities = [] | |
| wh = await fetch_all( | |
| "SELECT tmdb_id, media_type, last_watched_at FROM watch_history WHERE user_id=? ORDER BY last_watched_at DESC LIMIT 10", | |
| [str(user["id"])] | |
| ) | |
| for w in wh: | |
| activities.append({"action": "شاهد", "target": f"#{w['tmdb_id']}", "time": w.get("last_watched_at", ""), "icon": "🎬"}) | |
| ratings = await fetch_all( | |
| "SELECT tmdb_id, rating, updated_at FROM ratings WHERE user_id=? ORDER BY updated_at DESC LIMIT 5", | |
| [str(user["id"])] | |
| ) | |
| for r in ratings: | |
| activities.append({"action": "قيم", "target": f"#{r['tmdb_id']} بـ {r['rating']}/10", "time": r.get("updated_at", ""), "icon": "⭐"}) | |
| activities.sort(key=lambda x: x["time"], reverse=True) | |
| return {"ok": True, "data": activities[:15]} | |