techfolio / app.py
harshdhane's picture
Update app.py
a91022c verified
Raw
History Blame Contribute Delete
9.72 kB
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}")
@app.route('/')
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
@app.route('/visitor_count')
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"
@app.route('/api/visitor_stats')
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
@app.route('/projects/<filename>')
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
@app.route('/certificates/<filename>')
def serve_certificates(filename):
"""Serve certificate images"""
try:
return send_from_directory('certificates', filename)
except FileNotFoundError:
return send_from_directory('.', 'placeholder.jpg'), 404
@app.route('/logos/<filename>')
def serve_logos(filename):
"""Serve company/organization logos"""
try:
return send_from_directory('logos', filename)
except FileNotFoundError:
return send_from_directory('.', 'placeholder.jpg'), 404
@app.route('/others/<filename>')
def serve_others(filename):
"""Serve other static files"""
try:
return send_from_directory('others', filename)
except FileNotFoundError:
return send_from_directory('.', 'placeholder.jpg'), 404
@app.route('/assets/<path:filename>')
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)
@app.route('/contact', methods=['POST'])
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
@app.route('/health')
def health_check():
"""Health check endpoint"""
return jsonify({
'status': 'healthy',
'timestamp': datetime.now().isoformat(),
'version': '1.0.0'
})
# Service worker for PWA
@app.route('/sw.js')
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
@app.errorhandler(404)
def not_found_error(error):
"""Handle 404 errors"""
return jsonify({'error': 'Page not found'}), 404
@app.errorhandler(500)
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)