Spaces:
Running
Running
| from fastapi import APIRouter, Depends, HTTPException, Query | |
| from typing import Dict, Any | |
| from src.auth.dependencies import get_current_user | |
| from src.db.firebase import get_firebase_db | |
| from src.recommendation.recommender import RecommendationService | |
| from src.utils.logger import setup_logger | |
| logger = setup_logger(__name__) | |
| router = APIRouter(prefix="/recommendations", tags=["Recommendations"]) | |
| recommendation_service = RecommendationService() | |
| GENERAL_VIDEOS = [ | |
| { | |
| "videoId": "aircAruvnKk", | |
| "title": "But what is a neural network?", | |
| "channelTitle": "3Blue1Brown", | |
| "thumbnail": "https://img.youtube.com/vi/aircAruvnKk/hqdefault.jpg", | |
| }, | |
| { | |
| "videoId": "rfscVS0vtbw", | |
| "title": "Learn Python in 4 hours", | |
| "channelTitle": "freeCodeCamp", | |
| "thumbnail": "https://img.youtube.com/vi/rfscVS0vtbw/hqdefault.jpg", | |
| }, | |
| { | |
| "videoId": "8jLOx1hD3_o", | |
| "title": "Harvard CS50 2023", | |
| "channelTitle": "CS50", | |
| "thumbnail": "https://img.youtube.com/vi/8jLOx1hD3_o/hqdefault.jpg", | |
| }, | |
| { | |
| "videoId": "kqtD5dpn9C8", | |
| "title": "Python for Beginners β Full Course", | |
| "channelTitle": "Programming with Mosh", | |
| "thumbnail": "https://img.youtube.com/vi/kqtD5dpn9C8/hqdefault.jpg", | |
| }, | |
| { | |
| "videoId": "Ke90Tje7VS0", | |
| "title": "React JS Crash Course", | |
| "channelTitle": "Traversy Media", | |
| "thumbnail": "https://img.youtube.com/vi/Ke90Tje7VS0/hqdefault.jpg", | |
| }, | |
| { | |
| "videoId": "bMknfKXIFA8", | |
| "title": "Machine Learning Course for Beginners", | |
| "channelTitle": "freeCodeCamp", | |
| "thumbnail": "https://img.youtube.com/vi/bMknfKXIFA8/hqdefault.jpg", | |
| }, | |
| { | |
| "videoId": "ua-CiDNNj30", | |
| "title": "Fullstack Web Dev in 2024", | |
| "channelTitle": "Fireship", | |
| "thumbnail": "https://img.youtube.com/vi/ua-CiDNNj30/hqdefault.jpg", | |
| }, | |
| { | |
| "videoId": "qiQR5rTSshw", | |
| "title": "C++ Tutorial for Beginners", | |
| "channelTitle": "freeCodeCamp", | |
| "thumbnail": "https://img.youtube.com/vi/qiQR5rTSshw/hqdefault.jpg", | |
| }, | |
| { | |
| "videoId": "zOjov-2OZ0E", | |
| "title": "100+ Linux Things You Should Know", | |
| "channelTitle": "Fireship", | |
| "thumbnail": "https://img.youtube.com/vi/zOjov-2OZ0E/hqdefault.jpg", | |
| }, | |
| { | |
| "videoId": "W6NZfCO5SIk", | |
| "title": "JavaScript Tutorial for Beginners", | |
| "channelTitle": "Programming with Mosh", | |
| "thumbnail": "https://img.youtube.com/vi/W6NZfCO5SIk/hqdefault.jpg", | |
| }, | |
| ] | |
| MIN_INTERACTIONS_FOR_PERSONALIZATION = 5 | |
| async def get_recommendations( | |
| current_user=Depends(get_current_user), | |
| db=Depends(get_firebase_db), | |
| limit: int = Query(default=5, ge=1, le=20), | |
| ) -> Dict[str, Any]: | |
| user_id = current_user.id # β your model uses "id" | |
| if not user_id: | |
| raise HTTPException(status_code=401, detail="Invalid user") | |
| logger.info(f"π― Getting recommendations for user: {user_id}") | |
| try: | |
| # β Use notesCount directly from user | |
| notes_count = getattr(current_user, "notesCount", 0) or 0 | |
| is_personalized = notes_count >= MIN_INTERACTIONS_FOR_PERSONALIZATION | |
| if is_personalized: | |
| logger.info(f"β Personalized mode for {user_id} ({notes_count} notes)") | |
| # β οΈ for now you can still return general videos | |
| # until you build real recommender | |
| recommendations = await recommendation_service.get_recommendations_for_user( | |
| db=db, | |
| user_id=user_id, | |
| limit=limit, | |
| ) | |
| else: | |
| logger.info(f"π± General mode for {user_id} ({notes_count}/{MIN_INTERACTIONS_FOR_PERSONALIZATION} notes)") | |
| recommendations = [] | |
| except Exception as e: | |
| logger.error(f"β Failed to get recommendations for {user_id}: {e}") | |
| raise HTTPException( | |
| status_code=500, | |
| detail="Failed to fetch recommendations.", | |
| ) | |
| return { | |
| "status": "success", | |
| "is_personalized": is_personalized, | |
| "interactions_count": notes_count, # β mapped correctly | |
| "interactions_needed": MIN_INTERACTIONS_FOR_PERSONALIZATION, | |
| "count": len(recommendations), | |
| "recommendations": recommendations, | |
| } |