""" User Interest Profile API routes for Munich News Daily. Provides endpoints to view and manage user interest profiles. """ from flask import Blueprint, request, jsonify from services.interest_profiling_service import ( get_user_interests, get_top_interests, build_interests_from_history, decay_user_interests, get_interest_statistics, delete_user_interests ) interests_bp = Blueprint('interests', __name__) @interests_bp.route('/api/interests/', methods=['GET']) def get_interests(email): """ Get user interest profile. Args: email: Email address of the user Returns: JSON response with user interest profile """ try: profile = get_user_interests(email) if not profile: return jsonify({ 'success': False, 'error': 'User profile not found' }), 404 # Remove MongoDB _id field if '_id' in profile: del profile['_id'] return jsonify({ 'success': True, 'profile': profile }), 200 except Exception as e: return jsonify({ 'success': False, 'error': str(e) }), 500 @interests_bp.route('/api/interests//top', methods=['GET']) def get_top_user_interests(email): """ Get user's top interests sorted by score. Query parameters: top_n: Number of top interests to return (default: 10) Args: email: Email address of the user Returns: JSON response with top categories and keywords """ try: top_n = request.args.get('top_n', 10, type=int) top_interests = get_top_interests(email, top_n) return jsonify({ 'success': True, 'email': email, 'top_categories': [ {'category': cat, 'score': score} for cat, score in top_interests['top_categories'] ], 'top_keywords': [ {'keyword': kw, 'score': score} for kw, score in top_interests['top_keywords'] ] }), 200 except Exception as e: return jsonify({ 'success': False, 'error': str(e) }), 500 @interests_bp.route('/api/interests//rebuild', methods=['POST']) def rebuild_interests(email): """ Rebuild user interest profile from click history. Request body (optional): { "days_lookback": 30 // Number of days of history to analyze } Args: email: Email address of the user Returns: JSON response with rebuilt profile """ try: data = request.get_json() or {} days_lookback = data.get('days_lookback', 30) # Validate days_lookback if not isinstance(days_lookback, int) or days_lookback < 1: return jsonify({ 'success': False, 'error': 'days_lookback must be a positive integer' }), 400 profile = build_interests_from_history(email, days_lookback) # Remove MongoDB _id field if '_id' in profile: del profile['_id'] return jsonify({ 'success': True, 'message': f'Profile rebuilt from {days_lookback} days of history', 'profile': profile }), 200 except Exception as e: return jsonify({ 'success': False, 'error': str(e) }), 500 @interests_bp.route('/api/interests/decay', methods=['POST']) def decay_interests(): """ Decay interest scores for inactive users. Request body (optional): { "decay_factor": 0.95, // Multiplier for scores (default: 0.95) "days_threshold": 7 // Only decay profiles older than N days } Returns: JSON response with decay statistics """ try: data = request.get_json() or {} decay_factor = data.get('decay_factor', 0.95) days_threshold = data.get('days_threshold', 7) # Validate parameters if not isinstance(decay_factor, (int, float)) or decay_factor <= 0 or decay_factor > 1: return jsonify({ 'success': False, 'error': 'decay_factor must be between 0 and 1' }), 400 if not isinstance(days_threshold, int) or days_threshold < 1: return jsonify({ 'success': False, 'error': 'days_threshold must be a positive integer' }), 400 result = decay_user_interests(decay_factor, days_threshold) return jsonify({ 'success': True, 'message': f'Decayed interests for profiles older than {days_threshold} days', 'statistics': result }), 200 except Exception as e: return jsonify({ 'success': False, 'error': str(e) }), 500 @interests_bp.route('/api/interests/statistics', methods=['GET']) def get_statistics(): """ Get statistics about user interests across all users. Returns: JSON response with interest statistics """ try: stats = get_interest_statistics() return jsonify({ 'success': True, 'statistics': stats }), 200 except Exception as e: return jsonify({ 'success': False, 'error': str(e) }), 500 @interests_bp.route('/api/interests/', methods=['DELETE']) def delete_interests(email): """ Delete user interest profile (GDPR compliance). Args: email: Email address of the user Returns: JSON response with confirmation """ try: deleted = delete_user_interests(email) if not deleted: return jsonify({ 'success': False, 'error': 'User profile not found' }), 404 return jsonify({ 'success': True, 'message': f'Interest profile deleted for {email}' }), 200 except Exception as e: return jsonify({ 'success': False, 'error': str(e) }), 500