import gradio as gr import requests import json import base64 import io from PIL import Image import pandas as pd import plotly.graph_objects as go import plotly.express as px from datetime import datetime, timedelta import hashlib import uuid import time import re from typing import Dict, List, Optional, Tuple import asyncio import aiohttp import numpy as np import os os.environ['GRADIO_SERVER_NAME'] = '0.0.0.0' os.environ['GRADIO_SERVER_PORT'] = '7860' # ============================================================================ # CONFIGURATION & CONSTANTS # ============================================================================ API_BASE_URL = "https://vaibhav07112004-vibe-detection-backend-api.hf.space" ##YOUTUBE_API_KEY = "your-youtube-api-key" # Add your YouTube API key # CSS Styles - Complete Tailwind-inspired styling with additional enhancements CUSTOM_CSS = """ /* Global Styles */ .gradio-container { font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif; background: linear-gradient(135deg, #1a1a2e 0%, #16213e 50%, #0f3460 100%); min-height: 100vh; } /* Enhanced Glass Morphism Effects */ .glass-card { background: rgba(255, 255, 255, 0.1); backdrop-filter: blur(15px); border-radius: 20px; border: 1px solid rgba(255, 255, 255, 0.2); box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.37); transition: all 0.3s ease; } .glass-card:hover { background: rgba(255, 255, 255, 0.15); transform: translateY(-2px); box-shadow: 0 12px 40px 0 rgba(31, 38, 135, 0.5); } /* Purple to Pink Gradients - Enhanced */ .gradient-bg { background: linear-gradient(135deg, #667eea 0%, #764ba2 50%, #f093fb 100%); } .gradient-text { background: linear-gradient(135deg, #667eea 0%, #764ba2 50%, #f093fb 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; } /* Enhanced Button Styles */ .btn-primary { background: linear-gradient(135deg, #667eea 0%, #764ba2 50%, #f093fb 100%); border: none; border-radius: 12px; color: white; padding: 12px 24px; font-weight: 600; transition: all 0.3s ease; cursor: pointer; position: relative; overflow: hidden; } .btn-primary:hover { transform: translateY(-2px); box-shadow: 0 10px 25px rgba(102, 126, 234, 0.4); } .btn-primary:before { content: ''; position: absolute; top: 0; left: -100%; width: 100%; height: 100%; background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent); transition: left 0.5s; } .btn-primary:hover:before { left: 100%; } /* Enhanced Card Styles */ .emotion-card { background: rgba(255, 255, 255, 0.95); border-radius: 16px; padding: 24px; margin: 12px; box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1); transition: all 0.3s ease; position: relative; overflow: hidden; } .emotion-card:hover { transform: translateY(-4px) scale(1.02); box-shadow: 0 8px 30px rgba(0, 0, 0, 0.15); } .emotion-card:before { content: ''; position: absolute; top: 0; left: 0; right: 0; height: 4px; background: linear-gradient(135deg, #667eea 0%, #764ba2 50%, #f093fb 100%); } /* Enhanced Animation Classes */ @keyframes fadeInUp { from { opacity: 0; transform: translateY(30px); } to { opacity: 1; transform: translateY(0); } } .fade-in { animation: fadeInUp 0.6s ease-out; } @keyframes pulseGlow { 0%, 100% { transform: scale(1); box-shadow: 0 0 20px rgba(102, 126, 234, 0.5); } 50% { transform: scale(1.05); box-shadow: 0 0 30px rgba(102, 126, 234, 0.8); } } .pulse { animation: pulseGlow 2s infinite; } @keyframes float { 0%, 100% { transform: translateY(0px); } 50% { transform: translateY(-10px); } } .float { animation: float 3s ease-in-out infinite; } /* Enhanced Loading Spinner */ .spinner { border: 4px solid rgba(255, 255, 255, 0.3); border-top: 4px solid #667eea; border-radius: 50%; width: 40px; height: 40px; animation: spin 1s linear infinite; margin: 20px auto; } @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } /* Progress Bar */ .progress-bar { width: 100%; height: 8px; background: rgba(255, 255, 255, 0.2); border-radius: 4px; overflow: hidden; margin: 10px 0; } .progress-fill { height: 100%; background: linear-gradient(135deg, #667eea 0%, #764ba2 50%, #f093fb 100%); border-radius: 4px; transition: width 0.3s ease; } /* Responsive Design */ @media (max-width: 768px) { .emotion-card { margin: 8px; padding: 16px; } .gradio-container { padding: 10px; } } /* Enhanced Chart Containers */ .chart-container { background: rgba(255, 255, 255, 0.95); border-radius: 16px; padding: 24px; margin: 15px 0; box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1); backdrop-filter: blur(10px); border: 1px solid rgba(255, 255, 255, 0.2); } /* Enhanced User Profile Styles */ .user-avatar { width: 80px; height: 80px; border-radius: 50%; background: linear-gradient(135deg, #667eea 0%, #764ba2 50%, #f093fb 100%); display: flex; align-items: center; justify-content: center; color: white; font-weight: bold; font-size: 28px; box-shadow: 0 4px 20px rgba(102, 126, 234, 0.4); transition: all 0.3s ease; } .user-avatar:hover { transform: scale(1.1); box-shadow: 0 6px 30px rgba(102, 126, 234, 0.6); } /* Enhanced Music Player Styles */ .music-player { background: rgba(255, 255, 255, 0.95); border-radius: 20px; padding: 24px; margin: 15px 0; box-shadow: 0 6px 25px rgba(0, 0, 0, 0.15); backdrop-filter: blur(15px); border: 1px solid rgba(255, 255, 255, 0.3); } /* Enhanced Notification Styles */ .notification { padding: 16px 20px; border-radius: 12px; margin: 10px 0; font-weight: 500; position: relative; overflow: hidden; animation: slideInRight 0.5s ease-out; } @keyframes slideInRight { from { transform: translateX(100%); opacity: 0; } to { transform: translateX(0); opacity: 1; } } .notification-success { background: linear-gradient(135deg, #d4edda 0%, #c3e6cb 100%); color: #155724; border-left: 4px solid #28a745; } .notification-error { background: linear-gradient(135deg, #f8d7da 0%, #f5c6cb 100%); color: #721c24; border-left: 4px solid #dc3545; } .notification-info { background: linear-gradient(135deg, #cce7ff 0%, #b3d7ff 100%); color: #004085; border-left: 4px solid #007bff; } /* Tab Styling */ .tab-nav { background: rgba(255, 255, 255, 0.1); border-radius: 15px; padding: 5px; margin-bottom: 20px; } .tab-nav button { background: transparent; border: none; padding: 12px 20px; border-radius: 10px; color: rgba(255, 255, 255, 0.7); transition: all 0.3s ease; } .tab-nav button.active { background: linear-gradient(135deg, #667eea 0%, #764ba2 50%, #f093fb 100%); color: white; box-shadow: 0 4px 15px rgba(102, 126, 234, 0.4); } /* Story Creation Styles */ .story-editor { background: rgba(255, 255, 255, 0.95); border-radius: 16px; padding: 24px; margin: 15px 0; min-height: 300px; border: 2px dashed rgba(102, 126, 234, 0.3); transition: all 0.3s ease; } .story-editor:focus-within { border-color: #667eea; box-shadow: 0 0 20px rgba(102, 126, 234, 0.2); } /* Social Share Buttons */ .social-share { display: flex; gap: 10px; margin: 15px 0; } .social-btn { padding: 10px 15px; border-radius: 25px; border: none; color: white; font-weight: 500; cursor: pointer; transition: all 0.3s ease; } .social-btn.twitter { background: #1da1f2; } .social-btn.facebook { background: #4267b2; } .social-btn.instagram { background: linear-gradient(45deg, #f09433 0%, #e6683c 25%, #dc2743 50%, #cc2366 75%, #bc1888 100%); } .social-btn:hover { transform: translateY(-2px); box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3); } """ # ============================================================================ # ENHANCED UTILITY SERVICES # ============================================================================ class AnalyticsService: """Complete analytics service for emotion tracking and user behavior""" def __init__(self): self.events = [] self.user_sessions = {} self.emotion_data = [] self.user_preferences = {} self.performance_metrics = {} def track_event(self, event_type: str, user_id: str, data: Dict): """Track user events and interactions""" event = { 'id': str(uuid.uuid4()), 'type': event_type, 'user_id': user_id, 'data': data, 'timestamp': datetime.now().isoformat(), 'session_id': self.get_session_id(user_id), 'user_agent': data.get('user_agent', 'Unknown'), 'ip_address': data.get('ip_address', 'Unknown') } self.events.append(event) self.update_performance_metrics(event_type) return event def track_emotion(self, user_id: str, emotion_data: Dict, image_metadata: Dict = None): """Track emotion detection results with enhanced metadata""" emotion_record = { 'id': str(uuid.uuid4()), 'user_id': user_id, 'emotions': emotion_data, 'timestamp': datetime.now().isoformat(), 'session_id': self.get_session_id(user_id), 'image_metadata': image_metadata or {}, 'processing_time': emotion_data.get('processing_time', 0), 'confidence_score': max(emotion_data.values()) if emotion_data else 0 } self.emotion_data.append(emotion_record) return emotion_record def update_performance_metrics(self, event_type: str): """Update performance metrics""" if event_type not in self.performance_metrics: self.performance_metrics[event_type] = { 'count': 0, 'avg_response_time': 0, 'success_rate': 0 } self.performance_metrics[event_type]['count'] += 1 def get_session_id(self, user_id: str) -> str: """Get or create session ID for user""" if user_id not in self.user_sessions: self.user_sessions[user_id] = { 'session_id': str(uuid.uuid4()), 'start_time': datetime.now().isoformat(), 'last_activity': datetime.now().isoformat() } else: self.user_sessions[user_id]['last_activity'] = datetime.now().isoformat() return self.user_sessions[user_id]['session_id'] def get_analytics_dashboard(self, user_id: str) -> Dict: """Generate comprehensive analytics dashboard data""" user_events = [e for e in self.events if e['user_id'] == user_id] user_emotions = [e for e in self.emotion_data if e['user_id'] == user_id] # Calculate advanced metrics total_sessions = len(set([e['session_id'] for e in user_events])) total_emotions_detected = len(user_emotions) avg_confidence = sum([e['confidence_score'] for e in user_emotions]) / len(user_emotions) if user_emotions else 0 # Emotion distribution with confidence weighting emotion_counts = {} emotion_confidence_totals = {} for emotion_record in user_emotions: for emotion, confidence in emotion_record['emotions'].items(): if emotion not in emotion_counts: emotion_counts[emotion] = 0 emotion_confidence_totals[emotion] = 0 emotion_counts[emotion] += 1 emotion_confidence_totals[emotion] += confidence # Calculate average confidence per emotion emotion_avg_confidence = {} for emotion in emotion_counts: emotion_avg_confidence[emotion] = emotion_confidence_totals[emotion] / emotion_counts[emotion] return { 'total_sessions': total_sessions, 'total_emotions_detected': total_emotions_detected, 'average_confidence': avg_confidence, 'emotion_distribution': emotion_counts, 'emotion_confidence': emotion_avg_confidence, 'recent_events': user_events[-10:], 'mood_trends': self.calculate_mood_trends(user_emotions), 'session_duration': self.calculate_session_duration(user_id), 'most_active_times': self.get_most_active_times(user_events), 'emotion_patterns': self.analyze_emotion_patterns(user_emotions) } def calculate_mood_trends(self, emotion_data: List[Dict]) -> Dict: """Calculate mood trends over time with enhanced analysis""" if not emotion_data: return {} # Group by date and time periods daily_moods = {} hourly_patterns = {} for record in emotion_data: timestamp = datetime.fromisoformat(record['timestamp']) date = timestamp.strftime('%Y-%m-%d') hour = timestamp.hour if date not in daily_moods: daily_moods[date] = [] daily_moods[date].append(record['emotions']) if hour not in hourly_patterns: hourly_patterns[hour] = [] hourly_patterns[hour].append(record['emotions']) # Calculate averages mood_trends = {} for date, moods in daily_moods.items(): avg_mood = {} for mood_list in moods: for emotion, confidence in mood_list.items(): if emotion not in avg_mood: avg_mood[emotion] = [] avg_mood[emotion].append(confidence) for emotion in avg_mood: avg_mood[emotion] = sum(avg_mood[emotion]) / len(avg_mood[emotion]) mood_trends[date] = avg_mood return { 'daily_trends': mood_trends, 'hourly_patterns': hourly_patterns, 'trend_analysis': self.analyze_trends(mood_trends) } def analyze_trends(self, mood_trends: Dict) -> Dict: """Analyze mood trends for insights""" if len(mood_trends) < 2: return {'message': 'Not enough data for trend analysis'} # Calculate trend direction for each emotion dates = sorted(mood_trends.keys()) trend_analysis = {} for emotion in ['happy', 'sad', 'angry', 'neutral']: values = [mood_trends[date].get(emotion, 0) for date in dates] if len(values) >= 2: trend = 'increasing' if values[-1] > values[0] else 'decreasing' change = abs(values[-1] - values[0]) trend_analysis[emotion] = { 'trend': trend, 'change': change, 'stability': 'stable' if change < 0.1 else 'variable' } return trend_analysis def calculate_session_duration(self, user_id: str) -> Dict: """Calculate session duration statistics""" if user_id not in self.user_sessions: return {'average_duration': 0, 'total_time': 0} session_data = self.user_sessions[user_id] start_time = datetime.fromisoformat(session_data['start_time']) last_activity = datetime.fromisoformat(session_data['last_activity']) duration = (last_activity - start_time).total_seconds() return { 'current_session_duration': duration, 'average_duration': duration, # Would be calculated across multiple sessions 'total_time': duration } def get_most_active_times(self, user_events: List[Dict]) -> Dict: """Analyze most active times of day""" hourly_activity = {} for event in user_events: hour = datetime.fromisoformat(event['timestamp']).hour hourly_activity[hour] = hourly_activity.get(hour, 0) + 1 if not hourly_activity: return {} most_active_hour = max(hourly_activity, key=hourly_activity.get) return { 'most_active_hour': most_active_hour, 'hourly_distribution': hourly_activity, 'peak_activity_time': f"{most_active_hour}:00-{most_active_hour+1}:00" } def analyze_emotion_patterns(self, emotion_data: List[Dict]) -> Dict: """Analyze emotion patterns and sequences""" if len(emotion_data) < 2: return {'message': 'Not enough data for pattern analysis'} # Analyze emotion transitions transitions = {} for i in range(len(emotion_data) - 1): current_emotion = max(emotion_data[i]['emotions'], key=emotion_data[i]['emotions'].get) next_emotion = max(emotion_data[i+1]['emotions'], key=emotion_data[i+1]['emotions'].get) transition = f"{current_emotion} -> {next_emotion}" transitions[transition] = transitions.get(transition, 0) + 1 # Find most common transitions if transitions: most_common_transition = max(transitions, key=transitions.get) return { 'transitions': transitions, 'most_common_transition': most_common_transition, 'pattern_strength': max(transitions.values()) / sum(transitions.values()) } return {'message': 'No clear patterns detected'} class APIService: """Enhanced API service for backend integration""" def __init__(self, base_url: str): self.base_url = base_url self.session_token = None self.user_data = None self.request_cache = {} self.retry_count = 3 self.timeout = 30 def make_request(self, method: str, endpoint: str, data: Dict = None, files: Dict = None) -> Dict: """Make HTTP request with error handling and retries""" url = f"{self.base_url}{endpoint}" headers = self.get_headers() for attempt in range(self.retry_count): try: if method.upper() == 'GET': response = requests.get(url, headers=headers, params=data, timeout=self.timeout) elif method.upper() == 'POST': if files: # For file uploads, don't set Content-Type header headers.pop('Content-Type', None) response = requests.post(url, data=data, files=files, headers=headers, timeout=self.timeout) else: response = requests.post(url, json=data, headers=headers, timeout=self.timeout) elif method.upper() == 'PUT': response = requests.put(url, json=data, headers=headers, timeout=self.timeout) elif method.upper() == 'DELETE': response = requests.delete(url, headers=headers, timeout=self.timeout) else: return {"success": False, "error": f"Unsupported method: {method}"} if response.status_code == 200: return {"success": True, "data": response.json()} elif response.status_code == 401: return {"success": False, "error": "Authentication required"} elif response.status_code == 403: return {"success": False, "error": "Access forbidden"} elif response.status_code == 404: return {"success": False, "error": "Endpoint not found"} elif response.status_code == 429: return {"success": False, "error": "Rate limit exceeded"} else: return {"success": False, "error": f"HTTP {response.status_code}: {response.text}"} except requests.exceptions.Timeout: if attempt == self.retry_count - 1: return {"success": False, "error": "Request timeout"} time.sleep(2 ** attempt) # Exponential backoff except requests.exceptions.ConnectionError: if attempt == self.retry_count - 1: return {"success": False, "error": "Connection error"} time.sleep(2 ** attempt) except Exception as e: return {"success": False, "error": str(e)} return {"success": False, "error": "Max retries exceeded"} def authenticate_user(self, email: str, password: str) -> Dict: """Authenticate user with backend""" if not email or not password: return {"success": False, "error": "Email and password required"} # Create FormData for FastAPI compatibility form_data = { 'email': email, 'password': password } result = self.make_request('POST', '/auth/login', data=form_data) if result['success']: user_data = result['data'].get('user', {}) self.session_token = result['data'].get('token') self.user_data = user_data return {"success": True, "user": user_data} else: return result def register_user(self, email: str, password: str, name: str) -> Dict: """Register new user""" if not all([email, password, name]): return {"success": False, "error": "All fields are required"} form_data = { 'email': email, 'password': password, 'name': name } result = self.make_request('POST', '/auth/signup', data=form_data) if result['success']: user_data = result['data'].get('user', {}) self.session_token = result['data'].get('token') self.user_data = user_data return {"success": True, "user": user_data} else: return result def detect_emotion(self, image_file) -> Dict: """Send image for emotion detection""" if not image_file: return {"success": False, "error": "No image provided"} try: # Convert PIL image to file-like object img_buffer = io.BytesIO() image_file.save(img_buffer, format='PNG') img_buffer.seek(0) files = { 'file': ('image.png', img_buffer, 'image/png') } result = self.make_request('POST', '/analyze', files=files) if result['success']: return { "success": True, "emotions": result['data'].get('emotions', {}), "moods": result['data'].get('moods', []), "genres": result['data'].get('genres', []), "tracks": result['data'].get('tracks', []), "source": result['data'].get('source', 'unknown') } else: return result except Exception as e: return {"success": False, "error": f"Image processing error: {str(e)}"} def get_user_profile(self) -> Dict: """Get current user profile""" if not self.session_token: return {"success": False, "error": "Not authenticated"} result = self.make_request('GET', '/auth/me') if result['success']: return {"success": True, "user": result['data']} else: return result def get_health_status(self) -> Dict: """Check backend health status""" result = self.make_request('GET', '/health') return result def get_headers(self) -> Dict: """Get authentication headers""" headers = {'Content-Type': 'application/json'} if self.session_token: headers['Authorization'] = f'Bearer {self.session_token}' return headers class EmailService: """Enhanced email notification service""" def __init__(self): self.email_queue = [] self.sent_emails = [] self.templates = { 'welcome': self.get_welcome_template(), 'weekly_recap': self.get_weekly_recap_template(), 'emotion_report': self.get_emotion_report_template(), 'achievement': self.get_achievement_template(), 'reminder': self.get_reminder_template() } self.email_preferences = {} def send_welcome_email(self, user_email: str, user_name: str) -> bool: """Send welcome email to new user""" email_data = { 'id': str(uuid.uuid4()), 'to': user_email, 'subject': '🎭 Welcome to VibeStory - Your Emotion Journey Begins!', 'template': 'welcome', 'data': { 'name': user_name, 'welcome_tips': [ 'Upload your first image to discover your emotions', 'Explore personalized music recommendations', 'Track your mood patterns over time', 'Create emotion-based stories' ] }, 'timestamp': datetime.now().isoformat(), 'status': 'queued' } self.email_queue.append(email_data) return True def send_weekly_recap(self, user_email: str, recap_data: Dict) -> bool: """Send enhanced weekly emotion recap""" email_data = { 'id': str(uuid.uuid4()), 'to': user_email, 'subject': f'📊 Your Weekly Emotion Recap - {recap_data.get("week_start", "")} to {recap_data.get("week_end", "")}', 'template': 'weekly_recap', 'data': recap_data, 'timestamp': datetime.now().isoformat(), 'status': 'queued' } self.email_queue.append(email_data) return True def send_achievement_notification(self, user_email: str, achievement_data: Dict) -> bool: """Send achievement notification""" email_data = { 'id': str(uuid.uuid4()), 'to': user_email, 'subject': f'🏆 Achievement Unlocked: {achievement_data.get("title", "New Achievement")}', 'template': 'achievement', 'data': achievement_data, 'timestamp': datetime.now().isoformat(), 'status': 'queued' } self.email_queue.append(email_data) return True def get_welcome_template(self) -> str: return """

🎭 Welcome to VibeStory!

Hi {name},

Welcome to VibeStory - your personal AI-powered emotion detection and music recommendation platform!

🚀 Getting Started:

Start your emotional journey today and discover the power of understanding your feelings through AI!

Start Your Journey
""" def get_weekly_recap_template(self) -> str: return """

📊 Your Weekly Emotion Recap

Here's your emotional journey from {week_start} to {week_end}:

📈 This Week's Highlights:

Total Emotions Detected: {total_detections}

Dominant Emotion: {dominant_emotion}

{emotion_summary}

🎵 Music Recommendations:

{music_recommendations}

💡 Insights & Recommendations:

{insights}
""" def get_emotion_report_template(self) -> str: return """

🎭 Emotion Analysis Report

Your latest emotion analysis results:

{emotion_data}

Keep tracking your emotions to build a comprehensive understanding of your emotional patterns!

""" def get_achievement_template(self) -> str: return """

🏆 Achievement Unlocked!

{title}

{description}

{icon}

Congratulations on reaching this milestone in your emotional journey!

""" def get_reminder_template(self) -> str: return """

🔔 VibeStory Reminder

Hi {name},

{message}

Continue Your Journey
""" def process_email_queue(self) -> List[Dict]: """Process queued emails (simulation)""" processed = [] for email in self.email_queue: email['status'] = 'sent' email['sent_at'] = datetime.now().isoformat() processed.append(email) self.sent_emails.append(email) self.email_queue.clear() return processed def get_email_statistics(self, user_email: str) -> Dict: """Get email statistics for user""" user_emails = [e for e in self.sent_emails if e['to'] == user_email] return { 'total_sent': len(user_emails), 'by_template': {}, 'recent_emails': user_emails[-5:], 'engagement_rate': 0.85 # Simulated } class WeeklyRecapService: """Enhanced weekly recap generation service""" def __init__(self, analytics_service: AnalyticsService): self.analytics = analytics_service self.achievement_system = AchievementSystem() def generate_weekly_recap(self, user_id: str) -> Dict: """Generate comprehensive weekly recap with achievements""" end_date = datetime.now() start_date = end_date - timedelta(days=7) # Get user's emotion data for the week user_emotions = [ e for e in self.analytics.emotion_data if e['user_id'] == user_id and start_date <= datetime.fromisoformat(e['timestamp']) <= end_date ] if not user_emotions: return { "message": "No emotion data available for this week", "suggestion": "Upload some images to start tracking your emotions!" } # Calculate comprehensive statistics emotion_summary = self.calculate_emotion_summary(user_emotions) mood_patterns = self.analyze_mood_patterns(user_emotions) recommendations = self.generate_recommendations(emotion_summary) achievements = self.achievement_system.check_achievements(user_id, user_emotions) insights = self.generate_insights(emotion_summary, mood_patterns) # Calculate improvement metrics previous_week_emotions = self.get_previous_week_data(user_id, start_date) improvement_metrics = self.calculate_improvement_metrics(user_emotions, previous_week_emotions) return { 'week_start': start_date.strftime('%Y-%m-%d'), 'week_end': end_date.strftime('%Y-%m-%d'), 'total_detections': len(user_emotions), 'emotion_summary': emotion_summary, 'mood_patterns': mood_patterns, 'recommendations': recommendations, 'insights': insights, 'achievements': achievements, 'improvement_metrics': improvement_metrics, 'engagement_score': self.calculate_engagement_score(user_emotions), 'next_week_goals': self.suggest_next_week_goals(emotion_summary) } def calculate_emotion_summary(self, emotion_data: List[Dict]) -> Dict: """Calculate comprehensive emotion summary statistics""" emotion_totals = {} confidence_totals = {} daily_emotions = {} for record in emotion_data: # Daily grouping date = record['timestamp'][:10] if date not in daily_emotions: daily_emotions[date] = [] daily_emotions[date].append(record['emotions']) # Overall totals for emotion, confidence in record['emotions'].items(): if emotion not in emotion_totals: emotion_totals[emotion] = [] confidence_totals[emotion] = [] emotion_totals[emotion].append(confidence) confidence_totals[emotion].append(confidence) # Calculate averages and statistics emotion_averages = {} emotion_stability = {} for emotion, confidences in emotion_totals.items(): emotion_averages[emotion] = sum(confidences) / len(confidences) emotion_stability[emotion] = np.std(confidences) if len(confidences) > 1 else 0 # Find dominant emotion and calculate diversity dominant_emotion = max(emotion_averages, key=emotion_averages.get) if emotion_averages else None emotion_diversity = len([e for e in emotion_averages.values() if e > 0.1]) # Emotions with >10% presence return { 'averages': emotion_averages, 'stability': emotion_stability, 'dominant_emotion': dominant_emotion, 'emotion_distribution': emotion_totals, 'daily_breakdown': daily_emotions, 'emotion_diversity': emotion_diversity, 'consistency_score': 1 - (sum(emotion_stability.values()) / len(emotion_stability)) if emotion_stability else 0 } def analyze_mood_patterns(self, emotion_data: List[Dict]) -> Dict: """Analyze detailed mood patterns throughout the week""" daily_moods = {} hourly_patterns = {} mood_transitions = [] for i, record in enumerate(emotion_data): timestamp = datetime.fromisoformat(record['timestamp']) date = timestamp.strftime('%Y-%m-%d') hour = timestamp.hour # Daily patterns if date not in daily_moods: daily_moods[date] = [] daily_moods[date].append(record['emotions']) # Hourly patterns if hour not in hourly_patterns: hourly_patterns[hour] = [] hourly_patterns[hour].append(record['emotions']) # Mood transitions if i > 0: prev_dominant = max(emotion_data[i-1]['emotions'], key=emotion_data[i-1]['emotions'].get) curr_dominant = max(record['emotions'], key=record['emotions'].get) if prev_dominant != curr_dominant: mood_transitions.append({ 'from': prev_dominant, 'to': curr_dominant, 'timestamp': record['timestamp'] }) # Analyze patterns most_stable_day = self.find_most_stable_day(daily_moods) most_active_hour = self.find_most_active_hour(hourly_patterns) return { 'daily_patterns': daily_moods, 'hourly_patterns': hourly_patterns, 'mood_transitions': mood_transitions, 'most_stable_day': most_stable_day, 'most_active_hour': most_active_hour, 'pattern_insights': self.generate_pattern_insights(daily_moods, hourly_patterns) } def generate_recommendations(self, emotion_summary: Dict) -> List[Dict]: """Generate personalized recommendations based on emotions""" recommendations = [] dominant_emotion = emotion_summary.get('dominant_emotion') emotion_diversity = emotion_summary.get('emotion_diversity', 0) consistency_score = emotion_summary.get('consistency_score', 0) # Emotion-specific recommendations emotion_recommendations = { 'happy': [ { 'type': 'activity', 'title': 'Share Your Joy', 'description': 'Your happiness is contagious! Consider sharing positive moments with friends and family.', 'action': 'Share a happy moment on social media or call a friend' }, { 'type': 'music', 'title': 'Upbeat Playlist', 'description': 'Keep the positive energy flowing with upbeat music.', 'action': 'Create an energetic playlist' } ], 'sad': [ { 'type': 'wellness', 'title': 'Self-Care Time', 'description': 'It\'s important to acknowledge and process sad feelings.', 'action': 'Try meditation, journaling, or gentle exercise' }, { 'type': 'music', 'title': 'Comforting Music', 'description': 'Soothing music can help process emotions and provide comfort.', 'action': 'Listen to calming or acoustic music' } ], 'angry': [ { 'type': 'wellness', 'title': 'Channel Your Energy', 'description': 'Anger can be transformed into productive energy.', 'action': 'Try physical exercise or creative expression' }, { 'type': 'mindfulness', 'title': 'Breathing Exercises', 'description': 'Deep breathing can help regulate intense emotions.', 'action': 'Practice 4-7-8 breathing technique' } ], 'neutral': [ { 'type': 'exploration', 'title': 'Explore New Experiences', 'description': 'Neutral emotions are a great time to try new things.', 'action': 'Try a new hobby or listen to different music genres' } ] } if dominant_emotion in emotion_recommendations: recommendations.extend(emotion_recommendations[dominant_emotion]) # Diversity-based recommendations if emotion_diversity < 3: recommendations.append({ 'type': 'growth', 'title': 'Emotional Range Expansion', 'description': 'Consider activities that might evoke different emotions to increase emotional awareness.', 'action': 'Try new experiences, watch different types of movies, or explore various music genres' }) # Consistency-based recommendations if consistency_score < 0.5: recommendations.append({ 'type': 'stability', 'title': 'Emotional Stability', 'description': 'Your emotions show some variability. This is normal, but consider stress management techniques.', 'action': 'Establish daily routines, practice mindfulness, or consider talking to someone' }) return recommendations def generate_insights(self, emotion_summary: Dict, mood_patterns: Dict) -> List[str]: """Generate personalized insights""" insights = [] # Emotion diversity insights diversity = emotion_summary.get('emotion_diversity', 0) if diversity >= 5: insights.append("🌈 You experienced a rich range of emotions this week, showing great emotional awareness and depth.") elif diversity >= 3: insights.append("😊 You had a good emotional range this week, experiencing several different feelings.") else: insights.append("🎯 Your emotions were quite focused this week. Consider exploring activities that might broaden your emotional experiences.") # Stability insights consistency = emotion_summary.get('consistency_score', 0) if consistency > 0.7: insights.append("⚖️ Your emotions were quite stable this week, showing good emotional regulation.") elif consistency > 0.4: insights.append("📊 Your emotional patterns showed moderate stability with some natural variation.") else: insights.append("🌊 Your emotions varied quite a bit this week. This can be normal during times of change or stress.") # Pattern insights transitions = mood_patterns.get('mood_transitions', []) if len(transitions) > 5: insights.append("🔄 You experienced several mood transitions this week, indicating dynamic emotional processing.") # Time-based insights most_active_hour = mood_patterns.get('most_active_hour') if most_active_hour is not None: if 6 <= most_active_hour <= 12: insights.append("🌅 You tend to be most emotionally active in the morning hours.") elif 12 <= most_active_hour <= 18: insights.append("☀️ Your peak emotional activity occurs during afternoon hours.") else: insights.append("🌙 You're most emotionally active during evening hours.") return insights def get_previous_week_data(self, user_id: str, current_week_start: datetime) -> List[Dict]: """Get previous week's emotion data for comparison""" prev_week_end = current_week_start - timedelta(days=1) prev_week_start = prev_week_end - timedelta(days=7) return [ e for e in self.analytics.emotion_data if e['user_id'] == user_id and prev_week_start <= datetime.fromisoformat(e['timestamp']) <= prev_week_end ] def calculate_improvement_metrics(self, current_week: List[Dict], previous_week: List[Dict]) -> Dict: """Calculate improvement metrics compared to previous week""" if not previous_week: return {'message': 'No previous week data for comparison'} # Calculate average happiness and overall positivity def calculate_positivity(emotion_data): if not emotion_data: return 0 positive_emotions = ['happy', 'surprised', 'neutral'] total_positivity = 0 count = 0 for record in emotion_data: for emotion, confidence in record['emotions'].items(): if emotion in positive_emotions: total_positivity += confidence count += 1 return total_positivity / count if count > 0 else 0 current_positivity = calculate_positivity(current_week) previous_positivity = calculate_positivity(previous_week) positivity_change = current_positivity - previous_positivity return { 'positivity_score': current_positivity, 'positivity_change': positivity_change, 'improvement_direction': 'improving' if positivity_change > 0.05 else 'stable' if abs(positivity_change) <= 0.05 else 'declining', 'activity_level': len(current_week) - len(previous_week), 'consistency_improvement': self.calculate_consistency_improvement(current_week, previous_week) } def calculate_engagement_score(self, emotion_data: List[Dict]) -> float: """Calculate user engagement score based on activity""" if not emotion_data: return 0.0 # Factors: frequency, consistency, time spread frequency_score = min(len(emotion_data) / 10, 1.0) # Max score at 10+ detections # Time spread (how many different days) dates = set([record['timestamp'][:10] for record in emotion_data]) spread_score = min(len(dates) / 7, 1.0) # Max score for all 7 days # Average confidence (quality of detections) avg_confidence = sum([max(record['emotions'].values()) for record in emotion_data]) / len(emotion_data) confidence_score = avg_confidence return (frequency_score + spread_score + confidence_score) / 3 def suggest_next_week_goals(self, emotion_summary: Dict) -> List[Dict]: """Suggest goals for the next week""" goals = [] dominant_emotion = emotion_summary.get('dominant_emotion') diversity = emotion_summary.get('emotion_diversity', 0) # Always suggest consistency goal goals.append({ 'type': 'consistency', 'title': 'Daily Check-ins', 'description': 'Upload at least one image per day to track your emotional journey', 'target': 7, 'current': 0 }) # Emotion-specific goals if dominant_emotion == 'sad': goals.append({ 'type': 'wellness', 'title': 'Self-Care Activities', 'description': 'Engage in 3 self-care activities this week', 'target': 3, 'current': 0 }) elif dominant_emotion == 'happy': goals.append({ 'type': 'sharing', 'title': 'Spread Joy', 'description': 'Share your positive moments with others', 'target': 2, 'current': 0 }) # Diversity goal if diversity < 4: goals.append({ 'type': 'exploration', 'title': 'Emotional Exploration', 'description': 'Try activities that evoke different emotions', 'target': 5, 'current': diversity }) return goals def find_most_stable_day(self, daily_moods: Dict) -> str: """Find the day with most stable emotions""" if not daily_moods: return None stability_scores = {} for date, moods in daily_moods.items(): if len(moods) > 1: # Calculate variance in dominant emotions dominant_emotions = [max(mood, key=mood.get) for mood in moods] stability = len(set(dominant_emotions)) / len(dominant_emotions) stability_scores[date] = 1 - stability # Higher score = more stable else: stability_scores[date] = 1.0 # Single mood = perfectly stable return max(stability_scores, key=stability_scores.get) if stability_scores else None def find_most_active_hour(self, hourly_patterns: Dict) -> int: """Find the hour with most emotional activity""" if not hourly_patterns: return None activity_scores = {hour: len(moods) for hour, moods in hourly_patterns.items()} return max(activity_scores, key=activity_scores.get) if activity_scores else None def generate_pattern_insights(self, daily_patterns: Dict, hourly_patterns: Dict) -> List[str]: """Generate insights about patterns""" insights = [] # Daily pattern insights if len(daily_patterns) >= 5: insights.append("You maintained consistent emotional tracking throughout most of the week.") elif len(daily_patterns) >= 3: insights.append("You tracked emotions on several days this week.") # Hourly pattern insights if hourly_patterns: peak_hours = sorted(hourly_patterns.keys(), key=lambda h: len(hourly_patterns[h]), reverse=True)[:3] if peak_hours: insights.append(f"Your most active emotional periods were around {peak_hours[0]}:00.") return insights def calculate_consistency_improvement(self, current_week: List[Dict], previous_week: List[Dict]) -> float: """Calculate improvement in emotional consistency""" def calculate_consistency(emotion_data): if len(emotion_data) < 2: return 0 # Calculate variance in dominant emotions dominant_emotions = [] for record in emotion_data: dominant = max(record['emotions'], key=record['emotions'].get) dominant_emotions.append(dominant) # Consistency = how often the same emotion appears from collections import Counter emotion_counts = Counter(dominant_emotions) max_count = max(emotion_counts.values()) return max_count / len(dominant_emotions) current_consistency = calculate_consistency(current_week) previous_consistency = calculate_consistency(previous_week) return current_consistency - previous_consistency class AchievementSystem: """Achievement and milestone tracking system""" def __init__(self): self.achievements = { 'first_emotion': { 'title': 'First Steps', 'description': 'Detected your first emotion', 'icon': '🎯', 'type': 'milestone', 'requirement': 1 }, 'emotion_explorer': { 'title': 'Emotion Explorer', 'description': 'Detected 5 different emotions', 'icon': '🌈', 'type': 'diversity', 'requirement': 5 }, 'consistent_tracker': { 'title': 'Consistent Tracker', 'description': 'Tracked emotions for 7 consecutive days', 'icon': '📅', 'type': 'consistency', 'requirement': 7 }, 'emotion_master': { 'title': 'Emotion Master', 'description': 'Completed 50 emotion detections', 'icon': '🏆', 'type': 'volume', 'requirement': 50 }, 'mood_analyst': { 'title': 'Mood Analyst', 'description': 'Maintained emotional awareness for 30 days', 'icon': '📊', 'type': 'longevity', 'requirement': 30 }, 'happiness_champion': { 'title': 'Happiness Champion', 'description': 'Detected happiness as dominant emotion 10 times', 'icon': '😊', 'type': 'emotion_specific', 'requirement': 10, 'emotion': 'happy' } } self.user_achievements = {} def check_achievements(self, user_id: str, emotion_data: List[Dict]) -> List[Dict]: """Check and award achievements based on emotion data""" if user_id not in self.user_achievements: self.user_achievements[user_id] = [] new_achievements = [] user_earned = [ach['id'] for ach in self.user_achievements[user_id]] for achievement_id, achievement in self.achievements.items(): if achievement_id in user_earned: continue if self.check_achievement_requirement(achievement, emotion_data, user_id): new_achievement = { 'id': achievement_id, 'title': achievement['title'], 'description': achievement['description'], 'icon': achievement['icon'], 'earned_at': datetime.now().isoformat(), 'type': achievement['type'] } self.user_achievements[user_id].append(new_achievement) new_achievements.append(new_achievement) return new_achievements def check_achievement_requirement(self, achievement: Dict, emotion_data: List[Dict], user_id: str) -> bool: """Check if achievement requirement is met""" achievement_type = achievement['type'] requirement = achievement['requirement'] if achievement_type == 'milestone': return len(emotion_data) >= requirement elif achievement_type == 'diversity': unique_emotions = set() for record in emotion_data: dominant = max(record['emotions'], key=record['emotions'].get) unique_emotions.add(dominant) return len(unique_emotions) >= requirement elif achievement_type == 'consistency': if len(emotion_data) < requirement: return False # Check for consecutive days dates = [datetime.fromisoformat(record['timestamp']).date() for record in emotion_data] dates = sorted(set(dates)) consecutive_days = 1 max_consecutive = 1 for i in range(1, len(dates)): if (dates[i] - dates[i-1]).days == 1: consecutive_days += 1 max_consecutive = max(max_consecutive, consecutive_days) else: consecutive_days = 1 return max_consecutive >= requirement elif achievement_type == 'volume': return len(emotion_data) >= requirement elif achievement_type == 'longevity': if not emotion_data: return False first_date = min([datetime.fromisoformat(record['timestamp']).date() for record in emotion_data]) last_date = max([datetime.fromisoformat(record['timestamp']).date() for record in emotion_data]) return (last_date - first_date).days >= requirement elif achievement_type == 'emotion_specific': target_emotion = achievement.get('emotion') count = 0 for record in emotion_data: dominant = max(record['emotions'], key=record['emotions'].get) if dominant == target_emotion: count += 1 return count >= requirement return False def get_user_achievements(self, user_id: str) -> List[Dict]: """Get all achievements for a user""" return self.user_achievements.get(user_id, []) def get_achievement_progress(self, user_id: str, emotion_data: List[Dict]) -> Dict: """Get progress towards unearned achievements""" if user_id not in self.user_achievements: self.user_achievements[user_id] = [] user_earned = [ach['id'] for ach in self.user_achievements[user_id]] progress = {} for achievement_id, achievement in self.achievements.items(): if achievement_id in user_earned: continue current_progress = self.calculate_achievement_progress(achievement, emotion_data) progress[achievement_id] = { 'title': achievement['title'], 'description': achievement['description'], 'icon': achievement['icon'], 'current': current_progress, 'required': achievement['requirement'], 'percentage': min((current_progress / achievement['requirement']) * 100, 100) } return progress def calculate_achievement_progress(self, achievement: Dict, emotion_data: List[Dict]) -> int: """Calculate current progress towards an achievement""" achievement_type = achievement['type'] if achievement_type == 'milestone' or achievement_type == 'volume': return len(emotion_data) elif achievement_type == 'diversity': unique_emotions = set() for record in emotion_data: dominant = max(record['emotions'], key=record['emotions'].get) unique_emotions.add(dominant) return len(unique_emotions) elif achievement_type == 'consistency': dates = [datetime.fromisoformat(record['timestamp']).date() for record in emotion_data] dates = sorted(set(dates)) consecutive_days = 1 max_consecutive = 1 for i in range(1, len(dates)): if (dates[i] - dates[i-1]).days == 1: consecutive_days += 1 max_consecutive = max(max_consecutive, consecutive_days) else: consecutive_days = 1 return max_consecutive elif achievement_type == 'longevity': if not emotion_data: return 0 first_date = min([datetime.fromisoformat(record['timestamp']).date() for record in emotion_data]) last_date = max([datetime.fromisoformat(record['timestamp']).date() for record in emotion_data]) return (last_date - first_date).days elif achievement_type == 'emotion_specific': target_emotion = achievement.get('emotion') count = 0 for record in emotion_data: dominant = max(record['emotions'], key=record['emotions'].get) if dominant == target_emotion: count += 1 return count return 0 class YouTubeService: """YouTube music integration service (uses backend data)""" def __init__(self): self.playlists = {} self.user_preferences = {} self.listening_history = {} def create_mood_playlist(self, user_id: str, mood: str, tracks: List[Dict]) -> Dict: """Create a mood-based playlist from backend recommendations""" playlist_id = str(uuid.uuid4()) playlist = { 'id': playlist_id, 'name': f"{mood.title()} Vibes", 'mood': mood, 'tracks': tracks[:20], # Limit to 20 tracks 'created_at': datetime.now().isoformat(), 'user_id': user_id, 'play_count': 0, 'last_played': None } if user_id not in self.playlists: self.playlists[user_id] = [] self.playlists[user_id].append(playlist) return playlist def get_user_playlists(self, user_id: str) -> List[Dict]: """Get all playlists for a user""" return self.playlists.get(user_id, []) def play_track(self, user_id: str, track: Dict) -> Dict: """Simulate playing a track and update history""" if user_id not in self.listening_history: self.listening_history[user_id] = [] play_record = { 'track': track, 'played_at': datetime.now().isoformat(), 'duration': track.get('duration', 180) # Default 3 minutes } self.listening_history[user_id].append(play_record) return play_record def get_listening_history(self, user_id: str) -> List[Dict]: """Get user's listening history""" return self.listening_history.get(user_id, []) class UtilsService: """Utility functions for the application""" @staticmethod def format_date(date_string: str, format_type: str = 'friendly') -> str: """Format date string in various formats""" try: dt = datetime.fromisoformat(date_string.replace('Z', '+00:00')) if format_type == 'friendly': return dt.strftime('%B %d, %Y at %I:%M %p') elif format_type == 'short': return dt.strftime('%m/%d/%Y') elif format_type == 'time': return dt.strftime('%I:%M %p') else: return dt.strftime('%Y-%m-%d %H:%M:%S') except: return date_string @staticmethod def calculate_time_ago(date_string: str) -> str: """Calculate human-readable time ago""" try: dt = datetime.fromisoformat(date_string.replace('Z', '+00:00')) now = datetime.now() diff = now - dt if diff.days > 0: return f"{diff.days} day{'s' if diff.days != 1 else ''} ago" elif diff.seconds > 3600: hours = diff.seconds // 3600 return f"{hours} hour{'s' if hours != 1 else ''} ago" elif diff.seconds > 60: minutes = diff.seconds // 60 return f"{minutes} minute{'s' if minutes != 1 else ''} ago" else: return "Just now" except: return "Unknown" @staticmethod def validate_email(email: str) -> bool: """Validate email format""" pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$' return re.match(pattern, email) is not None @staticmethod def validate_password(password: str) -> Dict: """Validate password strength""" errors = [] if len(password) < 8: errors.append("Password must be at least 8 characters long") if not re.search(r'[A-Z]', password): errors.append("Password must contain at least one uppercase letter") if not re.search(r'[a-z]', password): errors.append("Password must contain at least one lowercase letter") if not re.search(r'\d', password): errors.append("Password must contain at least one number") return { 'valid': len(errors) == 0, 'errors': errors, 'strength': 'strong' if len(errors) == 0 else 'weak' } @staticmethod def sanitize_input(text: str) -> str: """Sanitize user input""" # Remove HTML tags and dangerous characters text = re.sub(r'<[^>]*>', '', text) text = re.sub(r'[<>&"\'`]', '', text) return text.strip() @staticmethod def generate_color_from_emotion(emotion: str) -> str: """Generate color based on emotion""" emotion_colors = { 'happy': '#FFD700', 'sad': '#4169E1', 'angry': '#DC143C', 'fear': '#8B008B', 'surprise': '#FF8C00', 'disgust': '#228B22', 'neutral': '#708090', 'contempt': '#800080' } return emotion_colors.get(emotion.lower(), '#708090') @staticmethod def calculate_emotion_intensity(emotions: Dict) -> str: """Calculate overall emotion intensity""" if not emotions: return 'low' max_confidence = max(emotions.values()) if max_confidence > 0.8: return 'high' elif max_confidence > 0.5: return 'medium' else: return 'low' # ============================================================================ # INITIALIZE SERVICES # ============================================================================ # Initialize all services analytics_service = AnalyticsService() api_service = APIService(API_BASE_URL) email_service = EmailService() weekly_recap_service = WeeklyRecapService(analytics_service) youtube_service = YouTubeService() utils_service = UtilsService() # Global state management current_user = None current_session = None # ============================================================================ # CORE FUNCTIONS # ============================================================================ def authenticate_user(email: str, password: str) -> Tuple[bool, str, Dict]: """Authenticate user with enhanced error handling""" global current_user, current_session try: # Validate inputs if not email or not password: return False, "Email and password are required", {} if not utils_service.validate_email(email): return False, "Please enter a valid email address", {} # Track authentication attempt analytics_service.track_event('login_attempt', email, {'timestamp': datetime.now().isoformat()}) # Call backend API result = api_service.authenticate_user(email, password) if result['success']: current_user = result['user'] current_session = str(uuid.uuid4()) # Track successful login analytics_service.track_event('login_success', email, { 'session_id': current_session, 'timestamp': datetime.now().isoformat() }) # Send welcome back notification email_service.send_welcome_email(email, current_user.get('name', 'User')) return True, "Login successful! Welcome back!", current_user else: # Track failed login analytics_service.track_event('login_failure', email, { 'error': result['error'], 'timestamp': datetime.now().isoformat() }) return False, result.get('error', 'Login failed'), {} except Exception as e: analytics_service.track_event('login_error', email, { 'error': str(e), 'timestamp': datetime.now().isoformat() }) return False, f"Login error: {str(e)}", {} def register_user(email: str, password: str, name: str, confirm_password: str) -> Tuple[bool, str, Dict]: """Register new user with comprehensive validation""" global current_user, current_session try: # Validate inputs if not all([email, password, name, confirm_password]): return False, "All fields are required", {} if not utils_service.validate_email(email): return False, "Please enter a valid email address", {} if password != confirm_password: return False, "Passwords do not match", {} # Validate password strength password_validation = utils_service.validate_password(password) if not password_validation['valid']: return False, "; ".join(password_validation['errors']), {} # Sanitize inputs name = utils_service.sanitize_input(name) email = email.lower().strip() # Track registration attempt analytics_service.track_event('signup_attempt', email, {'timestamp': datetime.now().isoformat()}) # Call backend API result = api_service.register_user(email, password, name) if result['success']: current_user = result['user'] current_session = str(uuid.uuid4()) # Track successful registration analytics_service.track_event('signup_success', email, { 'session_id': current_session, 'timestamp': datetime.now().isoformat() }) # Send welcome email email_service.send_welcome_email(email, name) return True, f"Welcome to VibeStory, {name}! Your account has been created successfully.", current_user else: # Track failed registration analytics_service.track_event('signup_failure', email, { 'error': result['error'], 'timestamp': datetime.now().isoformat() }) return False, result.get('error', 'Registration failed'), {} except Exception as e: analytics_service.track_event('signup_error', email, { 'error': str(e), 'timestamp': datetime.now().isoformat() }) return False, f"Registration error: {str(e)}", {} def detect_emotion_from_image(image) -> Tuple[bool, str, Dict]: """Detect emotion from uploaded image with comprehensive processing""" global current_user try: if not image: return False, "Please upload an image", {} if not current_user: return False, "Please log in to analyze emotions", {} user_id = current_user.get('id', 'anonymous') # Track emotion detection attempt analytics_service.track_event('emotion_detection_start', user_id, { 'timestamp': datetime.now().isoformat() }) # Process image start_time = time.time() # Call backend API for emotion detection result = api_service.detect_emotion(image) processing_time = time.time() - start_time if result['success']: # Extract emotion data emotions = result.get('emotions', {}) moods = result.get('moods', []) genres = result.get('genres', []) tracks = result.get('tracks', []) source = result.get('source', 'unknown') # Calculate metadata image_metadata = { 'size': getattr(image, 'size', (0, 0)), 'format': getattr(image, 'format', 'unknown'), 'mode': getattr(image, 'mode', 'unknown') } # Enhanced emotion data with processing info enhanced_emotions = { **emotions, 'processing_time': processing_time, 'confidence_score': max(emotions.values()) if emotions else 0, 'detection_source': source } # Track emotion detection in analytics emotion_record = analytics_service.track_emotion( user_id, enhanced_emotions, image_metadata ) # Create mood-based playlist if tracks: dominant_emotion = max(emotions, key=emotions.get) if emotions else 'neutral' playlist = youtube_service.create_mood_playlist(user_id, dominant_emotion, tracks) # Track successful detection analytics_service.track_event('emotion_detection_success', user_id, { 'dominant_emotion': max(emotions, key=emotions.get) if emotions else 'unknown', 'confidence': max(emotions.values()) if emotions else 0, 'processing_time': processing_time, 'timestamp': datetime.now().isoformat() }) # Check for achievements user_emotions = [e for e in analytics_service.emotion_data if e['user_id'] == user_id] new_achievements = weekly_recap_service.achievement_system.check_achievements(user_id, user_emotions) # Send achievement notifications for achievement in new_achievements: email_service.send_achievement_notification(current_user['email'], achievement) return True, "Emotion detected successfully!", { 'emotions': emotions, 'moods': moods, 'genres': genres, 'tracks': tracks, 'source': source, 'processing_time': processing_time, 'achievements': new_achievements, 'playlist_created': len(tracks) > 0, 'emotion_record_id': emotion_record['id'] } else: # Track failed detection analytics_service.track_event('emotion_detection_failure', user_id, { 'error': result['error'], 'processing_time': processing_time, 'timestamp': datetime.now().isoformat() }) return False, result.get('error', 'Emotion detection failed'), {} except Exception as e: if current_user: analytics_service.track_event('emotion_detection_error', current_user.get('id', 'anonymous'), { 'error': str(e), 'timestamp': datetime.now().isoformat() }) return False, f"Analysis error: {str(e)}", {} def generate_analytics_dashboard(user_id: str = None) -> Dict: """Generate comprehensive analytics dashboard""" try: if not user_id and current_user: user_id = current_user.get('id') if not user_id: return {'error': 'User not authenticated'} # Get analytics data dashboard_data = analytics_service.get_analytics_dashboard(user_id) # Get achievement progress user_emotions = [e for e in analytics_service.emotion_data if e['user_id'] == user_id] achievement_progress = weekly_recap_service.achievement_system.get_achievement_progress(user_id, user_emotions) earned_achievements = weekly_recap_service.achievement_system.get_user_achievements(user_id) # Get playlists user_playlists = youtube_service.get_user_playlists(user_id) # Get listening history listening_history = youtube_service.get_listening_history(user_id) # Enhanced dashboard with all data enhanced_dashboard = { **dashboard_data, 'achievement_progress': achievement_progress, 'earned_achievements': earned_achievements, 'playlists': user_playlists, 'listening_history': listening_history[-10:], # Last 10 tracks 'user_stats': { 'total_playlists': len(user_playlists), 'total_listening_time': sum([track.get('duration', 0) for track in listening_history]), 'favorite_genre': 'Pop', # Would be calculated from listening history 'streak_days': dashboard_data.get('session_duration', {}).get('current_session_duration', 0) // 86400 } } return enhanced_dashboard except Exception as e: return {'error': f'Dashboard generation failed: {str(e)}'} def generate_weekly_recap_report(user_id: str = None) -> Dict: """Generate comprehensive weekly recap""" try: if not user_id and current_user: user_id = current_user.get('id') if not user_id: return {'error': 'User not authenticated'} # Generate recap recap_data = weekly_recap_service.generate_weekly_recap(user_id) # Send email recap if user has email if current_user and 'email' in current_user: email_service.send_weekly_recap(current_user['email'], recap_data) return recap_data except Exception as e: return {'error': f'Weekly recap generation failed: {str(e)}'} def create_story_from_emotion(emotion_data: Dict, story_prompt: str = "") -> Dict: """Create an emotion-based story""" try: if not emotion_data: return {'error': 'No emotion data provided'} dominant_emotion = max(emotion_data, key=emotion_data.get) confidence = emotion_data[dominant_emotion] # Story templates based on emotions story_templates = { 'happy': [ "The sun was shining brightly as {character} discovered something wonderful...", "With a smile that could light up the world, {character} began their adventure...", "Joy filled the air as {character} realized their dream was coming true..." ], 'sad': [ "The rain matched {character}'s mood as they walked through the empty streets...", "With tears in their eyes, {character} remembered better times...", "The melancholy evening reminded {character} of what they had lost..." ], 'angry': [ "Fury burned in {character}'s eyes as they faced the injustice...", "The storm inside {character} was about to break free...", "With clenched fists, {character} decided enough was enough..." ], 'surprised': [ "Never in their wildest dreams did {character} expect this...", "The unexpected turn of events left {character} speechless...", "As the door opened, {character} gasped in amazement..." ], 'neutral': [ "It was an ordinary day when {character} noticed something different...", "In the quiet moments, {character} found clarity...", "Sometimes the most profound changes begin with simple observations..." ] } # Select template templates = story_templates.get(dominant_emotion, story_templates['neutral']) selected_template = templates[0] # Could be randomized # Generate story character_name = story_prompt.strip() if story_prompt else "Alex" story_beginning = selected_template.format(character=character_name) story_data = { 'id': str(uuid.uuid4()), 'title': f"A {dominant_emotion.title()} Story", 'beginning': story_beginning, 'emotion_inspiration': dominant_emotion, 'confidence': confidence, 'character': character_name, 'created_at': datetime.now().isoformat(), 'author': current_user.get('name', 'Anonymous') if current_user else 'Anonymous' } # Track story creation if current_user: analytics_service.track_event('story_created', current_user.get('id'), { 'emotion': dominant_emotion, 'confidence': confidence, 'timestamp': datetime.now().isoformat() }) return {'success': True, 'story': story_data} except Exception as e: return {'error': f'Story creation failed: {str(e)}'} def get_backend_health() -> Dict: """Check backend health status""" try: result = api_service.get_health_status() if result['success']: health_data = result['data'] return { 'status': 'healthy', 'backend_connected': True, 'details': health_data } else: return { 'status': 'unhealthy', 'backend_connected': False, 'error': result.get('error', 'Unknown error') } except Exception as e: return { 'status': 'error', 'backend_connected': False, 'error': str(e) } # ============================================================================ # GRADIO INTERFACE FUNCTIONS # ============================================================================ def create_login_interface(): """Create enhanced login interface with WORKING backend integration""" return f"""
🎭 VibeStory

Welcome Back

Sign in to continue your emotional journey

📧
🔒
Or continue with

Don't have an account?

""" def create_signup_interface(): """Create enhanced signup interface with WORKING backend integration""" return f"""
🎭 VibeStory

Join VibeStory

Create your account to start your emotional journey

👤
📧
🔒
🔒
Or continue with

Already have an account?

""" # ============================================================================ # MAIN GRADIO APPLICATION # ============================================================================ def create_main_app(): """Create the main Gradio application with all features""" with gr.Blocks( title="🎭 VibeStory - AI Emotion Recognition Platform", theme=gr.themes.Base( primary_hue="purple", secondary_hue="pink", neutral_hue="slate" ), css=CUSTOM_CSS ) as app: # Global state user_state = gr.State(None) session_state = gr.State(None) # Rest of your app code... # Main application header gr.HTML("""

🎭 VibeStory

AI-Powered Emotion Recognition & Music Recommendation Platform

""") # Main tabs with gr.Tabs() as main_tabs: # ============================================================================ # LOGIN TAB # ============================================================================ with gr.Tab("🔐 Login", id="login_tab"): login_interface = gr.HTML(create_login_interface()) # Hidden components for login functionality with gr.Row(visible=False): login_email = gr.Textbox(label="Email") login_password = gr.Textbox(label="Password", type="password") login_btn = gr.Button("Login") login_output = gr.Textbox(label="Login Result") # Login function def handle_login(email, password): success, message, user_data = authenticate_user(email, password) if success: return user_data, message, gr.update(visible=True), gr.update(selected="emotion_tab") else: return None, message, gr.update(visible=False), gr.update() login_btn.click( handle_login, inputs=[login_email, login_password], outputs=[user_state, login_output, main_tabs, main_tabs] ) # ============================================================================ # SIGNUP TAB # ============================================================================ with gr.Tab("📝 Sign Up", id="signup_tab"): signup_interface = gr.HTML(create_signup_interface()) # Hidden components for signup functionality with gr.Row(visible=False): signup_name = gr.Textbox(label="Name") signup_email = gr.Textbox(label="Email") signup_password = gr.Textbox(label="Password", type="password") signup_confirm = gr.Textbox(label="Confirm Password", type="password") signup_btn = gr.Button("Sign Up") signup_output = gr.Textbox(label="Signup Result") # Signup function def handle_signup(name, email, password, confirm_password): success, message, user_data = register_user(email, password, name, confirm_password) if success: return user_data, message, gr.update(visible=True), gr.update(selected="emotion_tab") else: return None, message, gr.update(visible=False), gr.update() signup_btn.click( handle_signup, inputs=[signup_name, signup_email, signup_password, signup_confirm], outputs=[user_state, signup_output, main_tabs, main_tabs] ) # ============================================================================ # EMOTION DETECTION TAB # ============================================================================ with gr.Tab("🎭 Emotion Detection", id="emotion_tab"): gr.HTML("""

Upload an Image to Detect Your Emotions

Our AI will analyze your facial expressions and recommend music based on your mood

""") with gr.Row(): with gr.Column(scale=1): image_input = gr.Image( label="Upload Your Image", type="pil", height=400 ) detect_btn = gr.Button( "🔍 Analyze Emotions", variant="primary", size="lg" ) # Progress indicator progress_bar = gr.HTML(visible=False) with gr.Column(scale=2): # Results display emotion_results = gr.HTML(label="Emotion Analysis Results") # Music recommendations music_recommendations = gr.HTML(label="Music Recommendations") # Achievement notifications achievements_display = gr.HTML(label="Achievements") # Emotion detection function def analyze_emotion(image): if not image: return "Please upload an image first.", "", "" # Show progress progress_html = """

Analyzing your emotions...

""" success, message, results = detect_emotion_from_image(image) if success: emotions = results.get('emotions', {}) moods = results.get('moods', []) tracks = results.get('tracks', []) achievements = results.get('achievements', []) # Create emotion results HTML emotion_html = create_emotion_results_html(emotions, moods, results.get('source', 'unknown')) # Create music recommendations HTML music_html = create_music_recommendations_html(tracks) # Create achievements HTML achievements_html = create_achievements_html(achievements) return emotion_html, music_html, achievements_html else: error_html = f"""

Analysis Failed

{message}

""" return error_html, "", "" detect_btn.click( analyze_emotion, inputs=[image_input], outputs=[emotion_results, music_recommendations, achievements_display] ) # ============================================================================ # ANALYTICS DASHBOARD TAB # ============================================================================ with gr.Tab("📊 Analytics Dashboard", id="analytics_tab"): gr.HTML("""

Your Emotion Analytics Dashboard

Track your emotional patterns and insights over time

""") with gr.Row(): refresh_analytics_btn = gr.Button("🔄 Refresh Analytics", variant="secondary") with gr.Row(): with gr.Column(): analytics_overview = gr.HTML(label="Analytics Overview") with gr.Column(): mood_trends_chart = gr.HTML(label="Mood Trends") with gr.Row(): emotion_distribution = gr.HTML(label="Emotion Distribution") achievement_progress = gr.HTML(label="Achievement Progress") # Analytics function def load_analytics_dashboard(): if not current_user: return "Please log in to view analytics", "", "", "" dashboard_data = generate_analytics_dashboard() if 'error' in dashboard_data: error_html = f"""

{dashboard_data['error']}

""" return error_html, "", "", "" # Create overview HTML overview_html = create_analytics_overview_html(dashboard_data) # Create mood trends chart trends_html = create_mood_trends_chart_html(dashboard_data.get('mood_trends', {})) # Create emotion distribution chart distribution_html = create_emotion_distribution_html(dashboard_data.get('emotion_distribution', {})) # Create achievement progress progress_html = create_achievement_progress_html(dashboard_data.get('achievement_progress', {})) return overview_html, trends_html, distribution_html, progress_html refresh_analytics_btn.click( load_analytics_dashboard, outputs=[analytics_overview, mood_trends_chart, emotion_distribution, achievement_progress] ) # ============================================================================ # WEEKLY RECAP TAB # ============================================================================ with gr.Tab("📅 Weekly Recap", id="recap_tab"): gr.HTML("""

Your Weekly Emotion Recap

Comprehensive analysis of your emotional journey this week

""") with gr.Row(): generate_recap_btn = gr.Button("📊 Generate Weekly Recap", variant="primary") email_recap_btn = gr.Button("📧 Email Recap", variant="secondary") weekly_recap_display = gr.HTML(label="Weekly Recap") # Weekly recap function def generate_recap(): if not current_user: return "Please log in to generate weekly recap" recap_data = generate_weekly_recap_report() if 'error' in recap_data: return f"
{recap_data['error']}
" return create_weekly_recap_html(recap_data) def email_recap(): if not current_user: return "Please log in to email recap" recap_data = generate_weekly_recap_report() if 'error' not in recap_data: email_service.send_weekly_recap(current_user['email'], recap_data) return "Weekly recap sent to your email!" return "Failed to generate recap for email" generate_recap_btn.click(generate_recap, outputs=[weekly_recap_display]) email_recap_btn.click(email_recap, outputs=[weekly_recap_display]) # ============================================================================ # STORY CREATION TAB # ============================================================================ with gr.Tab("📖 Story Creation", id="story_tab"): gr.HTML("""

Create Emotion-Based Stories

Transform your emotions into creative stories

""") with gr.Row(): with gr.Column(): story_emotion_input = gr.Dropdown( choices=['happy', 'sad', 'angry', 'surprised', 'neutral', 'fear'], label="Select Emotion for Story", value="happy" ) story_character_input = gr.Textbox( label="Character Name", placeholder="Enter character name (optional)", value="Alex" ) create_story_btn = gr.Button("✨ Create Story", variant="primary") with gr.Column(): story_output = gr.HTML(label="Generated Story") # Story creation function def create_story(emotion, character_name): if not current_user: return "Please log in to create stories" # Create mock emotion data emotion_data = {emotion: 0.8} result = create_story_from_emotion(emotion_data, character_name) if result.get('success'): story = result['story'] return create_story_display_html(story) else: return f"
{result.get('error', 'Story creation failed')}
" create_story_btn.click( create_story, inputs=[story_emotion_input, story_character_input], outputs=[story_output] ) # ============================================================================ # MUSIC PLAYER TAB # ============================================================================ with gr.Tab("🎵 Music Player", id="music_tab"): gr.HTML("""

Your Personalized Music Player

Listen to emotion-based music recommendations

""") with gr.Row(): refresh_playlists_btn = gr.Button("🔄 Refresh Playlists", variant="secondary") with gr.Row(): user_playlists = gr.HTML(label="Your Playlists") listening_history = gr.HTML(label="Listening History") # Music player functions def load_music_player(): if not current_user: return "Please log in to access music player", "" user_id = current_user.get('id') playlists = youtube_service.get_user_playlists(user_id) history = youtube_service.get_listening_history(user_id) playlists_html = create_playlists_html(playlists) history_html = create_listening_history_html(history) return playlists_html, history_html refresh_playlists_btn.click( load_music_player, outputs=[user_playlists, listening_history] ) # ============================================================================ # PROFILE TAB # ============================================================================ with gr.Tab("👤 Profile", id="profile_tab") as profile_tab: gr.HTML("""

Your Profile & Settings

Manage your account and preferences

""") with gr.Row(): with gr.Column(): profile_info = gr.HTML(label="Profile Information") linked_accounts = gr.HTML(label="Linked Accounts") with gr.Column(): user_stats = gr.HTML(label="User Statistics") logout_btn = gr.Button("🚪 Logout", variant="stop") # Profile functions def load_profile(): if not current_user: return "Please log in to view profile", "", "" profile_html = create_profile_info_html(current_user) accounts_html = create_linked_accounts_html(current_user) stats_html = create_user_stats_html(current_user) return profile_html, accounts_html, stats_html def handle_logout(): global current_user, current_session current_user = None current_session = None return None, "Logged out successfully", gr.update(selected="login_tab") # Load profile on tab selection profile_tab.select( load_profile, outputs=[profile_info, linked_accounts, user_stats] ) logout_btn.click( handle_logout, outputs=[user_state, profile_info, main_tabs] ) # ============================================================================ # BACKEND STATUS TAB # ============================================================================ with gr.Tab("🔧 Backend Status", id="status_tab"): gr.HTML("""

Backend Health & Status

Monitor system health and performance

""") with gr.Row(): check_health_btn = gr.Button("🏥 Check Backend Health", variant="primary") test_connection_btn = gr.Button("🔌 Test Connection", variant="secondary") backend_status_display = gr.HTML(label="Backend Status") # Backend status functions def check_backend_health(): health_data = get_backend_health() return create_health_status_html(health_data) def test_backend_connection(): try: result = api_service.get_health_status() if result['success']: return """

✅ Connection Successful

Backend is responding normally

""" else: return f"""

❌ Connection Failed

{result.get('error', 'Unknown error')}

""" except Exception as e: return f"""

❌ Connection Error

{str(e)}

""" check_health_btn.click(check_backend_health, outputs=[backend_status_display]) test_connection_btn.click(test_backend_connection, outputs=[backend_status_display]) # Footer gr.HTML("""

🎭 VibeStory - AI-Powered Emotion Recognition Platform | Built with ❤️ using Gradio & FastAPI | © 2025 VibeStory

""") return app # ============================================================================ # HTML CREATION HELPER FUNCTIONS # ============================================================================ def create_emotion_results_html(emotions: Dict, moods: List[str], source: str) -> str: """Create HTML for emotion analysis results""" if not emotions: return "
No emotions detected
" dominant_emotion = max(emotions, key=emotions.get) confidence = emotions[dominant_emotion] emotion_color = utils_service.generate_color_from_emotion(dominant_emotion) emotions_html = "" for emotion, conf in sorted(emotions.items(), key=lambda x: x[1], reverse=True): color = utils_service.generate_color_from_emotion(emotion) emotions_html += f"""
{emotion.title()}
{conf:.1%}
""" moods_html = "" for mood in moods[:5]: # Show top 5 moods moods_html += f""" {mood} """ return f"""
😊

Dominant Emotion: {dominant_emotion.title()}

Confidence: {confidence:.1%} | Source: {source}

All Detected Emotions:

{emotions_html}

Associated Moods:

{moods_html}
""" def create_music_recommendations_html(tracks: List[Dict]) -> str: """Create HTML for music recommendations""" if not tracks: return "
No music recommendations available
" tracks_html = "" for i, track in enumerate(tracks[:10]): # Show top 10 tracks tracks_html += f"""

{track.get('title', 'Unknown Title')}

by {track.get('artist', 'Unknown Artist')}

{track.get('source', 'recommendation')}
""" return f"""

🎵 Music Recommendations

Based on your detected emotions, here are some songs you might enjoy:

{tracks_html}

💡 Tip: Click "Play" to add to your listening history, or "Open" to listen on YouTube Music

""" def create_achievements_html(achievements: List[Dict]) -> str: """Create HTML for achievement notifications""" if not achievements: return "" achievements_html = "" for achievement in achievements: achievements_html += f"""
{achievement.get('icon', '🏆')}

{achievement.get('title', 'Achievement Unlocked!')}

{achievement.get('description', '')}

{achievement.get('type', 'milestone')}
""" return f"""

🏆 New Achievements!

{achievements_html}
""" def create_analytics_overview_html(dashboard_data: Dict) -> str: """Create HTML for analytics overview""" total_sessions = dashboard_data.get('total_sessions', 0) total_emotions = dashboard_data.get('total_emotions_detected', 0) avg_confidence = dashboard_data.get('average_confidence', 0) return f"""

📊 Analytics Overview

{total_sessions}
Total Sessions
{total_emotions}
Emotions Detected
{avg_confidence:.1%}
Avg Confidence

Recent Activity

You've been actively tracking your emotions! Keep up the great work in understanding your emotional patterns.

""" def create_weekly_recap_html(recap_data: Dict) -> str: """Create HTML for weekly recap display""" week_start = recap_data.get('week_start', '') week_end = recap_data.get('week_end', '') total_detections = recap_data.get('total_detections', 0) dominant_emotion = recap_data.get('emotion_summary', {}).get('dominant_emotion', 'neutral') insights = recap_data.get('insights', []) recommendations = recap_data.get('recommendations', []) insights_html = "" for insight in insights: insights_html += f"""

{insight}

""" recommendations_html = "" for rec in recommendations: recommendations_html += f"""
{rec.get('title', '')}

{rec.get('description', '')}

{rec.get('type', 'recommendation')}
""" return f"""

📅 Weekly Recap

{week_start} to {week_end}

{total_detections}
Total Detections
{dominant_emotion.title()}
Dominant Emotion

💡 Insights

{insights_html if insights_html else '

No insights available for this week.

'}

🎯 Recommendations

{recommendations_html if recommendations_html else '

No recommendations available.

'}
""" def create_story_display_html(story: Dict) -> str: """Create HTML for story display""" return f"""

{story.get('title', 'Untitled Story')}

Inspired by: {story.get('emotion_inspiration', 'unknown')} | By: {story.get('author', 'Anonymous')}

{story.get('beginning', 'Story content not available.')}

""" def create_profile_info_html(user: Dict) -> str: """Create HTML for profile information""" return f"""
{user.get('name', 'U')[0].upper()}

{user.get('name', 'Unknown User')}

{user.get('email', 'No email')}

{user.get('auth_type', 'email').title()} Account

Account Information

User ID: {user.get('id', 'Unknown')}

Member Since: {utils_service.format_date(user.get('created_at', ''), 'friendly')}

""" def create_health_status_html(health_data: Dict) -> str: """Create HTML for backend health status""" status = health_data.get('status', 'unknown') connected = health_data.get('backend_connected', False) if status == 'healthy' and connected: status_color = "#22c55e" status_icon = "✅" status_text = "Healthy" elif status == 'unhealthy': status_color = "#ef4444" status_icon = "⚠️" status_text = "Unhealthy" else: status_color = "#f59e0b" status_icon = "❓" status_text = "Unknown" details = health_data.get('details', {}) return f"""
{status_icon}

Backend Status: {status_text}

Connection: {'🟢 Connected' if connected else '🔴 Disconnected'}

{f'''

System Details

ML Available: {'✅' if details.get('ml_available') else '❌'}

DeepFace Available: {'✅' if details.get('deepface_available') else '❌'}

Custom Models: {'✅' if details.get('custom_modules_available') else '❌'}

YouTube Music: {'✅' if details.get('youtube_music_available') else '❌'}

Redis Cache: {'✅' if details.get('redis_available') else '❌'}

''' if details else ''} {f'''

Error Details

{health_data.get('error', 'Unknown error')}

''' if not connected else ''}
""" # Additional helper functions for remaining HTML components def create_mood_trends_chart_html(mood_trends: Dict) -> str: """Create HTML for mood trends chart""" return """

📈 Mood Trends

Mood trends visualization would appear here.
(Chart integration with Plotly would be implemented here)

""" def create_emotion_distribution_html(emotion_distribution: Dict) -> str: """Create HTML for emotion distribution""" return """

🎭 Emotion Distribution

Emotion distribution pie chart would appear here.
(Chart integration with Plotly would be implemented here)

""" def create_achievement_progress_html(achievement_progress: Dict) -> str: """Create HTML for achievement progress""" return """

🏆 Achievement Progress

Achievement progress bars would appear here.
Track your milestones and unlock new achievements!

""" def create_playlists_html(playlists: List[Dict]) -> str: """Create HTML for user playlists""" if not playlists: return """

No playlists yet. Analyze some emotions to create mood-based playlists!

""" playlists_html = "" for playlist in playlists: playlists_html += f"""

{playlist.get('name', 'Untitled Playlist')}

{len(playlist.get('tracks', []))} tracks • Created {utils_service.format_date(playlist.get('created_at', ''), 'friendly')}

""" return f"""

🎵 Your Playlists

{playlists_html}
""" def create_listening_history_html(history: List[Dict]) -> str: """Create HTML for listening history""" if not history: return """

No listening history yet. Start playing some tracks!

""" history_html = "" for record in history[-5:]: # Show last 5 tracks track = record.get('track', {}) history_html += f"""
{track.get('title', 'Unknown Track')}
{track.get('artist', 'Unknown Artist')} • {utils_service.calculate_time_ago(record.get('played_at', ''))}
""" return f"""

🎧 Recent Listening

{history_html}
""" def create_linked_accounts_html(user: Dict) -> str: """Create HTML for linked accounts""" return """

🔗 Linked Accounts

Account linking features would appear here.
Connect multiple social accounts for enhanced experience.

""" def create_user_stats_html(user: Dict) -> str: """Create HTML for user statistics""" return """

📊 Your Statistics

Total Emotions Detected: 0

Favorite Emotion: Happy

Streak Days: 0

Stories Created: 0

""" # ============================================================================ # LAUNCH APPLICATION # ============================================================================ if __name__ == "__main__": app = create_main_app() app.launch( server_name="0.0.0.0", server_port=7860, share=False, debug=False, show_error=True, allowed_paths=["/"], root_path="/", app_kwargs={ "docs_url": None, "redoc_url": None } )