api / routers /analytics.py
jamelloverz-sketch
PopCorn API v3.5 - Media metadata, people, images, open CORS
c18e004
Raw
History Blame Contribute Delete
3.95 kB
"""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
@router.get("/stats")
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,
}}
@router.get("/stats/genres")
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}
@router.get("/stats/activity")
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]}