update
This commit is contained in:
239
backend/routes/interests_routes.py
Normal file
239
backend/routes/interests_routes.py
Normal file
@@ -0,0 +1,239 @@
|
||||
"""
|
||||
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/<email>', 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/<email>/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/<email>/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/<email>', 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
|
||||
Reference in New Issue
Block a user