footypredict-pro / src /enhanced_api.py
NetBoss
V3.0 Ultimate Enhancement - Complete production system
6f7e932
"""
Enhanced API Endpoints
Additional API routes for:
- Enhanced predictions with caching
- Real-time data streaming
- User notifications
- Advanced statistics
- Match recommendations
"""
from flask import Blueprint, jsonify, request
from datetime import datetime, timedelta
from typing import Dict, List, Optional
# Import our new modules
from src.cache_system import (
cache_prediction, cache_fixtures,
prediction_cache, get_cache_stats,
invalidate_prediction_cache
)
from src.realtime_updates import (
event_emitter, live_tracker, odds_tracker,
alert_manager, get_event_stream, emit_prediction
)
from src.notification_service import (
notification_service, get_user_notifications,
get_unread_count, notify_sure_win
)
# Create blueprint
enhanced_api = Blueprint('enhanced_api', __name__, url_prefix='/api/v4')
# ============================================================
# Enhanced Prediction Endpoints
# ============================================================
@enhanced_api.route('/predict/enhanced')
def enhanced_prediction():
"""Enhanced prediction with caching and full analysis"""
home = request.args.get('home')
away = request.args.get('away')
league = request.args.get('league', 'bundesliga')
if not home or not away:
return jsonify({'success': False, 'error': 'Missing home or away team'})
# Check cache first
cache_key = f"pred_{home}_{away}_{league}"
cached = prediction_cache.get(cache_key)
if cached:
cached['from_cache'] = True
cached['cache_age'] = 'recent'
return jsonify({'success': True, 'prediction': cached})
# Generate prediction
try:
from src.enhanced_predictor_v2 import enhanced_predict_with_goals
from src.advanced_features import get_team_form, get_h2h_stats
# Get prediction
prediction = enhanced_predict_with_goals(home, away, league)
# Enrich with additional data
home_form = get_team_form(home)
away_form = get_team_form(away)
h2h = get_h2h_stats(home, away)
result = {
'match': {
'home': home,
'away': away,
'league': league
},
'prediction': prediction,
'form': {
'home': home_form,
'away': away_form
},
'h2h': h2h,
'timestamp': datetime.now().isoformat(),
'from_cache': False
}
# Cache the result
prediction_cache.set(cache_key, result, ttl=300)
# Emit event for real-time subscribers
emit_prediction(result)
# Check for sure win
if prediction.get('confidence', 0) >= 0.91:
alert_manager.send_sure_win_alert(result)
return jsonify({'success': True, 'prediction': result})
except Exception as e:
return jsonify({'success': False, 'error': str(e)})
@enhanced_api.route('/predict/batch', methods=['POST'])
def batch_predictions():
"""Get predictions for multiple matches at once"""
data = request.get_json() or {}
matches = data.get('matches', [])
if not matches:
return jsonify({'success': False, 'error': 'No matches provided'})
results = []
for match in matches[:20]: # Limit to 20 matches
home = match.get('home')
away = match.get('away')
league = match.get('league', 'bundesliga')
if home and away:
cache_key = f"pred_{home}_{away}_{league}"
cached = prediction_cache.get(cache_key)
if cached:
results.append({'match': match, 'prediction': cached, 'cached': True})
else:
try:
from src.enhanced_predictor_v2 import enhanced_predict
pred = enhanced_predict(home, away, league)
prediction_cache.set(cache_key, pred, ttl=300)
results.append({'match': match, 'prediction': pred, 'cached': False})
except Exception as e:
results.append({'match': match, 'error': str(e)})
return jsonify({
'success': True,
'predictions': results,
'count': len(results)
})
# ============================================================
# Real-time Data Endpoints
# ============================================================
@enhanced_api.route('/realtime/stream')
def realtime_stream():
"""Get real-time event stream status"""
return jsonify({
'success': True,
'stream': get_event_stream()
})
@enhanced_api.route('/realtime/events')
def get_events():
"""Get recent events"""
event_type = request.args.get('type')
limit = int(request.args.get('limit', 50))
events = event_emitter.get_history(event_type, limit)
return jsonify({
'success': True,
'events': events,
'count': len(events)
})
@enhanced_api.route('/realtime/live-matches')
def get_live_matches():
"""Get currently tracked live matches"""
return jsonify({
'success': True,
'matches': live_tracker.get_live_matches(),
'count': len(live_tracker.live_matches)
})
@enhanced_api.route('/realtime/alerts')
def get_alerts():
"""Get recent alerts"""
limit = int(request.args.get('limit', 20))
return jsonify({
'success': True,
'alerts': alert_manager.get_active_alerts(limit)
})
# ============================================================
# Notification Endpoints
# ============================================================
@enhanced_api.route('/notifications')
def user_notifications():
"""Get user notifications"""
user_id = request.args.get('user_id', 'default')
return jsonify({
'success': True,
'notifications': get_user_notifications(user_id),
'unread_count': get_unread_count(user_id)
})
@enhanced_api.route('/notifications/mark-read', methods=['POST'])
def mark_notification_read():
"""Mark notification as read"""
data = request.get_json() or {}
user_id = data.get('user_id', 'default')
notification_id = data.get('notification_id')
if notification_id:
success = notification_service.in_app.mark_read(user_id, notification_id)
return jsonify({'success': success})
return jsonify({'success': False, 'error': 'Missing notification_id'})
@enhanced_api.route('/notifications/subscribe', methods=['POST'])
def subscribe_notifications():
"""Subscribe to push notifications"""
data = request.get_json() or {}
subscription = data.get('subscription')
if subscription:
success = notification_service.push.subscribe(subscription)
return jsonify({'success': success})
return jsonify({'success': False, 'error': 'Missing subscription data'})
# ============================================================
# Cache Management Endpoints
# ============================================================
@enhanced_api.route('/cache/stats')
def cache_stats():
"""Get cache statistics"""
return jsonify({
'success': True,
'stats': get_cache_stats()
})
@enhanced_api.route('/cache/clear', methods=['POST'])
def clear_cache():
"""Clear prediction cache"""
cleared = prediction_cache.clear()
return jsonify({
'success': True,
'cleared': cleared
})
@enhanced_api.route('/cache/invalidate', methods=['POST'])
def invalidate_cache():
"""Invalidate specific cache entries"""
data = request.get_json() or {}
home = data.get('home')
away = data.get('away')
league = data.get('league')
invalidate_prediction_cache(home, away, league)
return jsonify({'success': True})
# ============================================================
# Advanced Statistics Endpoints
# ============================================================
@enhanced_api.route('/stats/accuracy')
def accuracy_stats():
"""Get detailed accuracy statistics"""
try:
from src.accuracy_monitor import get_accuracy_stats, get_recent_predictions
stats = get_accuracy_stats()
recent = get_recent_predictions(limit=20)
return jsonify({
'success': True,
'stats': stats,
'recent': recent
})
except Exception as e:
return jsonify({'success': False, 'error': str(e)})
@enhanced_api.route('/stats/leagues')
def league_stats():
"""Get per-league statistics"""
try:
from src.success_tracker import get_success_analytics
analytics = get_success_analytics()
return jsonify({
'success': True,
'analytics': analytics
})
except Exception as e:
return jsonify({'success': False, 'error': str(e)})
@enhanced_api.route('/stats/performance')
def performance_stats():
"""Get overall performance metrics"""
try:
from src.accuracy_monitor import get_accuracy_stats
stats = get_accuracy_stats()
cache = get_cache_stats()
return jsonify({
'success': True,
'accuracy': stats,
'cache_performance': cache,
'uptime': '99.9%',
'api_version': 'v4',
'timestamp': datetime.now().isoformat()
})
except Exception as e:
return jsonify({'success': False, 'error': str(e)})
# ============================================================
# Match Recommendations
# ============================================================
@enhanced_api.route('/recommendations')
def get_recommendations():
"""Get personalized match recommendations"""
user_id = request.args.get('user_id', 'default')
strategy = request.args.get('strategy', 'balanced')
limit = int(request.args.get('limit', 10))
try:
from src.data.free_data_sources import UnifiedFreeDataProvider
from src.enhanced_predictor_v2 import enhanced_predict
provider = UnifiedFreeDataProvider()
fixtures = provider.get_unified_fixtures('bundesliga')
recommendations = []
for fixture in fixtures[:limit]:
home = fixture.get('home_team', {}).get('name') or fixture.get('home_team')
away = fixture.get('away_team', {}).get('name') or fixture.get('away_team')
if home and away:
try:
pred = enhanced_predict(home, away, 'bundesliga')
# Calculate recommendation score
confidence = pred.get('confidence', 0.5)
if strategy == 'safe':
score = confidence * 100
elif strategy == 'value':
edge = pred.get('edge', 0)
score = edge * 10 + confidence * 50
else: # balanced
score = confidence * 70 + 30
recommendations.append({
'match': f"{home} vs {away}",
'home': home,
'away': away,
'prediction': pred.get('predicted_outcome', 'N/A'),
'confidence': round(confidence * 100, 1),
'score': round(score, 1),
'reason': 'High confidence' if confidence > 0.7 else 'Good value'
})
except:
pass
# Sort by score
recommendations.sort(key=lambda x: x['score'], reverse=True)
return jsonify({
'success': True,
'strategy': strategy,
'recommendations': recommendations[:limit]
})
except Exception as e:
return jsonify({'success': False, 'error': str(e)})
@enhanced_api.route('/recommendations/sure-wins')
def sure_wins_endpoint():
"""Get sure win recommendations"""
try:
from src.confidence_sections import get_sure_wins
sure_wins = get_sure_wins(min_confidence=0.91)
return jsonify({
'success': True,
'sure_wins': sure_wins,
'count': len(sure_wins)
})
except Exception as e:
return jsonify({'success': False, 'error': str(e)})
# ============================================================
# Health & API Info
# ============================================================
@enhanced_api.route('/health')
def api_health():
"""Enhanced API health check"""
return jsonify({
'success': True,
'status': 'healthy',
'version': 'v4',
'features': [
'enhanced_predictions',
'caching',
'realtime_events',
'notifications',
'batch_predictions',
'recommendations',
'performance_stats'
],
'cache': get_cache_stats(),
'timestamp': datetime.now().isoformat()
})
@enhanced_api.route('/info')
def api_info():
"""Get API information"""
return jsonify({
'success': True,
'api': {
'name': 'FootyPredict Pro Enhanced API',
'version': 'v4.0.0',
'base_url': '/api/v4',
'endpoints': {
'predictions': '/predict/enhanced',
'batch': '/predict/batch',
'realtime': '/realtime/stream',
'notifications': '/notifications',
'stats': '/stats/performance',
'recommendations': '/recommendations'
}
},
'rate_limits': {
'predictions': '100/minute',
'batch': '10/minute',
'general': '1000/hour'
}
})
def register_enhanced_api(app):
"""Register the enhanced API blueprint"""
app.register_blueprint(enhanced_api)
print("✅ Enhanced API v4 registered at /api/v4")