Spaces:
Runtime error
Runtime error
| from flask import Flask, send_from_directory, jsonify, request | |
| import os | |
| import json | |
| from datetime import datetime | |
| import sqlite3 | |
| app = Flask(__name__) | |
| # Configuration | |
| app.config['SECRET_KEY'] = 'your-secret-key-here' | |
| DATABASE = 'visitor_counter.db' | |
| VISITOR_LOG_FILE = 'visitor_log.json' | |
| def init_db(): | |
| """Initialize the SQLite database and create the visitor_count table if it doesn't exist""" | |
| with sqlite3.connect(DATABASE) as conn: | |
| cursor = conn.cursor() | |
| cursor.execute(''' | |
| CREATE TABLE IF NOT EXISTS visitor_count ( | |
| id INTEGER PRIMARY KEY, | |
| count INTEGER NOT NULL | |
| ) | |
| ''') | |
| # Check if the table is empty, and if so, initialize with count 0 | |
| cursor.execute('SELECT COUNT(*) FROM visitor_count') | |
| if cursor.fetchone()[0] == 0: | |
| cursor.execute('INSERT INTO visitor_count (count) VALUES (0)') | |
| conn.commit() | |
| def get_visitor_count(): | |
| """Get current visitor count from the database""" | |
| try: | |
| with sqlite3.connect(DATABASE) as conn: | |
| cursor = conn.cursor() | |
| cursor.execute('SELECT count FROM visitor_count WHERE id = 1') | |
| result = cursor.fetchone() | |
| return result[0] if result else 0 | |
| except Exception as e: | |
| print(f"Error retrieving visitor count: {e}") | |
| return 0 | |
| def increment_visitor_count(): | |
| """Increment visitor count in the database""" | |
| try: | |
| with sqlite3.connect(DATABASE) as conn: | |
| cursor = conn.cursor() | |
| cursor.execute('UPDATE visitor_count SET count = count + 1 WHERE id = 1') | |
| conn.commit() | |
| cursor.execute('SELECT count FROM visitor_count WHERE id = 1') | |
| return cursor.fetchone()[0] | |
| except Exception as e: | |
| print(f"Error updating visitor count: {e}") | |
| return get_visitor_count() | |
| def log_visitor(request): | |
| """Log visitor information""" | |
| try: | |
| visitor_info = { | |
| 'timestamp': datetime.now().isoformat(), | |
| 'ip': request.environ.get('HTTP_X_FORWARDED_FOR', request.remote_addr), | |
| 'user_agent': request.headers.get('User-Agent', ''), | |
| 'referrer': request.headers.get('Referer', ''), | |
| 'method': request.method, | |
| 'path': request.path | |
| } | |
| # Read existing logs | |
| logs = [] | |
| if os.path.exists(VISITOR_LOG_FILE): | |
| try: | |
| with open(VISITOR_LOG_FILE, 'r') as f: | |
| logs = json.load(f) | |
| except json.JSONDecodeError: | |
| logs = [] | |
| # Add new log entry | |
| logs.append(visitor_info) | |
| # Keep only last 1000 entries | |
| if len(logs) > 1000: | |
| logs = logs[-1000:] | |
| # Save logs | |
| with open(VISITOR_LOG_FILE, 'w') as f: | |
| json.dump(logs, f, indent=2) | |
| except Exception as e: | |
| print(f"Error logging visitor: {e}") | |
| def home(): | |
| """Serve the main portfolio page""" | |
| try: | |
| # Log visitor and increment counter | |
| log_visitor(request) | |
| increment_visitor_count() | |
| # Serve the HTML file | |
| return send_from_directory('.', 'index.html') | |
| except Exception as e: | |
| print(f"Error serving home page: {e}") | |
| return "Error loading page", 500 | |
| def visitor_count(): | |
| """Return current visitor count""" | |
| try: | |
| count = get_visitor_count() | |
| return str(count) | |
| except Exception as e: | |
| print(f"Error getting visitor count: {e}") | |
| return "0" | |
| def visitor_stats(): | |
| """Return visitor statistics (optional API endpoint)""" | |
| try: | |
| count = get_visitor_count() | |
| # Read visitor logs for additional stats | |
| stats = { | |
| 'total_visitors': count, | |
| 'last_updated': datetime.now().isoformat() | |
| } | |
| if os.path.exists(VISITOR_LOG_FILE): | |
| try: | |
| with open(VISITOR_LOG_FILE, 'r') as f: | |
| logs = json.load(f) | |
| # Calculate additional stats | |
| today = datetime.now().date() | |
| today_visitors = sum(1 for log in logs | |
| if datetime.fromisoformat(log['timestamp']).date() == today) | |
| stats['today_visitors'] = today_visitors | |
| stats['recent_visits'] = len(logs) | |
| except json.JSONDecodeError: | |
| pass | |
| return jsonify(stats) | |
| except Exception as e: | |
| print(f"Error getting visitor stats: {e}") | |
| return jsonify({'error': 'Unable to fetch stats'}), 500 | |
| # Static file routes for different directories | |
| def serve_projects(filename): | |
| """Serve project images""" | |
| try: | |
| return send_from_directory('projects', filename) | |
| except FileNotFoundError: | |
| # Return a placeholder image if file not found | |
| return send_from_directory('.', 'placeholder.jpg'), 404 | |
| def serve_certificates(filename): | |
| """Serve certificate images""" | |
| try: | |
| return send_from_directory('certificates', filename) | |
| except FileNotFoundError: | |
| return send_from_directory('.', 'placeholder.jpg'), 404 | |
| def serve_logos(filename): | |
| """Serve company/organization logos""" | |
| try: | |
| return send_from_directory('logos', filename) | |
| except FileNotFoundError: | |
| return send_from_directory('.', 'placeholder.jpg'), 404 | |
| def serve_others(filename): | |
| """Serve other static files""" | |
| try: | |
| return send_from_directory('others', filename) | |
| except FileNotFoundError: | |
| return send_from_directory('.', 'placeholder.jpg'), 404 | |
| def serve_assets(filename): | |
| """Serve general assets""" | |
| try: | |
| return send_from_directory('assets', filename) | |
| except FileNotFoundError: | |
| return "File not found", 404 | |
| # Contact form endpoint (optional) | |
| def contact(): | |
| """Handle contact form submissions""" | |
| try: | |
| data = request.get_json() | |
| # Basic validation | |
| required_fields = ['name', 'email', 'message'] | |
| if not all(field in data for field in required_fields): | |
| return jsonify({'error': 'Missing required fields'}), 400 | |
| # Log the contact submission | |
| contact_info = { | |
| 'timestamp': datetime.now().isoformat(), | |
| 'name': data.get('name'), | |
| 'email': data.get('email'), | |
| 'message': data.get('message'), | |
| 'ip': request.environ.get('HTTP_X_FORWARDED_FOR', request.remote_addr) | |
| } | |
| # Save to file | |
| contact_file = 'contact_submissions.json' | |
| contacts = [] | |
| if os.path.exists(contact_file): | |
| try: | |
| with open(contact_file, 'r') as f: | |
| contacts = json.load(f) | |
| except json.JSONDecodeError: | |
| contacts = [] | |
| contacts.append(contact_info) | |
| with open(contact_file, 'w') as f: | |
| json.dump(contacts, f, indent=2) | |
| return jsonify({'message': 'Thank you for your message! I will get back to you soon.'}), 200 | |
| except Exception as e: | |
| print(f"Error handling contact form: {e}") | |
| return jsonify({'error': 'Unable to process your request'}), 500 | |
| # Health check endpoint | |
| def health_check(): | |
| """Health check endpoint""" | |
| return jsonify({ | |
| 'status': 'healthy', | |
| 'timestamp': datetime.now().isoformat(), | |
| 'version': '1.0.0' | |
| }) | |
| # Service worker for PWA | |
| def service_worker(): | |
| """Serve service worker for PWA functionality""" | |
| sw_content = ''' | |
| const CACHE_NAME = 'portfolio-v1'; | |
| const urlsToCache = [ | |
| '/', | |
| '/static/css/style.css', | |
| '/static/js/script.js', | |
| 'https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=Playfair+Display:wght@400;500;600;700&display=swap', | |
| 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css' | |
| ]; | |
| self.addEventListener('install', function(event) { | |
| event.waitUntil( | |
| caches.open(CACHE_NAME) | |
| .then(function(cache) { | |
| return cache.addAll(urlsToCache); | |
| }) | |
| ); | |
| }); | |
| self.addEventListener('fetch', function(event) { | |
| event.respondWith( | |
| caches.match(event.request) | |
| .then(function(response) { | |
| if (response) { | |
| return response; | |
| } | |
| return fetch(event.request); | |
| } | |
| ) | |
| ); | |
| }); | |
| ''' | |
| response = app.response_class( | |
| response=sw_content, | |
| status=200, | |
| mimetype='application/javascript' | |
| ) | |
| return response | |
| # Error handlers | |
| def not_found_error(error): | |
| """Handle 404 errors""" | |
| return jsonify({'error': 'Page not found'}), 404 | |
| def internal_error(error): | |
| """Handle 500 errors""" | |
| return jsonify({'error': 'Internal server error'}), 500 | |
| if __name__ == '__main__': | |
| # Initialize database | |
| init_db() | |
| # Create necessary directories if they don't exist | |
| directories = ['projects', 'certificates', 'logos', 'others', 'assets'] | |
| for directory in directories: | |
| os.makedirs(directory, exist_ok=True) | |
| # Run the application | |
| app.run(debug=True, host='0.0.0.0', port=7860) |