import os import base64 import uuid import json import threading import time from datetime import datetime from flask import Flask, render_template, request, jsonify, send_file, send_from_directory from flask_socketio import SocketIO, emit from flask_cors import CORS import eventlet eventlet.monkey_patch() app = Flask(__name__) app.config['SECRET_KEY'] = 'camera-website-secret-key-2024' app.config['UPLOAD_FOLDER'] = 'uploads/gallery' app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024 app.config['ALLOWED_EXTENSIONS'] = {'png', 'jpg', 'jpeg', 'gif'} CORS(app) socketio = SocketIO(app, cors_allowed_origins="*", async_mode='eventlet') os.makedirs(app.config['UPLOAD_FOLDER'], exist_ok=True) active_sessions = {} last_capture_time = {} def allowed_file(filename): return '.' in filename and filename.rsplit('.', 1)[1].lower() in app.config['ALLOWED_EXTENSIONS'] def save_base64_image(base64_string, session_id): try: if ',' in base64_string: base64_string = base64_string.split(',')[1] image_data = base64.b64decode(base64_string) timestamp = datetime.now().strftime('%Y%m%d_%H%M%S_%f') filename = f"capture_{timestamp}_{session_id[:8]}.jpg" filepath = os.path.join(app.config['UPLOAD_FOLDER'], filename) with open(filepath, 'wb') as f: f.write(image_data) file_size = os.path.getsize(filepath) created_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S') image_info = { 'filename': filename, 'path': f'/uploads/{filename}', 'created': created_time, 'size': file_size, 'session_id': session_id, 'timestamp': timestamp } socketio.emit('new_image', image_info, namespace='/gallery') print(f"Image saved: {filename}") return True, filename except Exception as e: print(f"Error saving image: {str(e)}") return False, str(e) @app.route('/') def index(): return render_template('index.html') @app.route('/gallery') def gallery(): return render_template('gallery.html') @app.route('/api/start_session', methods=['POST']) def start_session(): session_id = str(uuid.uuid4()) active_sessions[session_id] = { 'started': datetime.now().strftime('%Y-%m-%d %H:%M:%S'), 'last_capture': None, 'capture_count': 0, 'ip': request.remote_addr } return jsonify({ 'status': 'success', 'session_id': session_id, 'message': 'Camera session started' }) @app.route('/api/capture', methods=['POST']) def capture_image(): try: data = request.get_json() if not data or 'image' not in data: return jsonify({'status': 'error', 'message': 'No image data provided'}), 400 session_id = data.get('session_id', 'anonymous') image_data = data['image'] success, result = save_base64_image(image_data, session_id) if success: if session_id in active_sessions: active_sessions[session_id]['last_capture'] = datetime.now().strftime('%Y-%m-%d %H:%M:%S') active_sessions[session_id]['capture_count'] += 1 return jsonify({ 'status': 'success', 'message': 'Image captured successfully', 'filename': result }) else: return jsonify({'status': 'error', 'message': f'Failed to save image: {result}'}), 500 except Exception as e: return jsonify({'status': 'error', 'message': str(e)}), 500 @app.route('/api/end_session/', methods=['POST']) def end_session(session_id): if session_id in active_sessions: del active_sessions[session_id] return jsonify({'status': 'success', 'message': 'Session ended'}) return jsonify({'status': 'error', 'message': 'Session not found'}), 404 @app.route('/api/get_images', methods=['GET']) def get_images(): try: images = [] for filename in os.listdir(app.config['UPLOAD_FOLDER']): if allowed_file(filename): filepath = os.path.join(app.config['UPLOAD_FOLDER'], filename) if os.path.isfile(filepath): stat = os.stat(filepath) images.append({ 'filename': filename, 'path': f'/uploads/{filename}', 'created': datetime.fromtimestamp(stat.st_ctime).strftime('%Y-%m-%d %H:%M:%S'), 'size': stat.st_size, 'full_path': filepath }) images.sort(key=lambda x: x['created'], reverse=True) return jsonify({'status': 'success', 'images': images, 'total': len(images)}) except Exception as e: return jsonify({'status': 'error', 'message': str(e)}), 500 @app.route('/api/get_sessions', methods=['GET']) def get_sessions(): try: sessions = [] for session_id, session_data in active_sessions.items(): sessions.append({ 'session_id': session_id[:8], 'started': session_data['started'], 'last_capture': session_data['last_capture'], 'capture_count': session_data['capture_count'], 'ip': session_data.get('ip', 'Unknown') }) return jsonify({'status': 'success', 'sessions': sessions, 'total': len(sessions)}) except Exception as e: return jsonify({'status': 'error', 'message': str(e)}), 500 @app.route('/api/get_stats', methods=['GET']) def get_stats(): try: total_images = len([f for f in os.listdir(app.config['UPLOAD_FOLDER']) if allowed_file(f)]) total_size = sum(os.path.getsize(os.path.join(app.config['UPLOAD_FOLDER'], f)) for f in os.listdir(app.config['UPLOAD_FOLDER']) if allowed_file(f)) active_sessions_count = len(active_sessions) return jsonify({ 'status': 'success', 'stats': { 'total_images': total_images, 'total_size': total_size, 'total_size_mb': round(total_size / (1024 * 1024), 2), 'active_sessions': active_sessions_count } }) except Exception as e: return jsonify({'status': 'error', 'message': str(e)}), 500 @app.route('/uploads/') def uploaded_file(filename): return send_from_directory(app.config['UPLOAD_FOLDER'], filename) @app.route('/api/download/') def download_file(filename): filepath = os.path.join(app.config['UPLOAD_FOLDER'], filename) if os.path.exists(filepath): return send_file(filepath, as_attachment=True, download_name=filename) return jsonify({'status': 'error', 'message': 'File not found'}), 404 @app.route('/api/delete/', methods=['DELETE']) def delete_file(filename): try: filepath = os.path.join(app.config['UPLOAD_FOLDER'], filename) if os.path.exists(filepath): os.remove(filepath) socketio.emit('image_deleted', {'filename': filename}, namespace='/gallery') return jsonify({'status': 'success', 'message': 'File deleted'}) return jsonify({'status': 'error', 'message': 'File not found'}), 404 except Exception as e: return jsonify({'status': 'error', 'message': str(e)}), 500 @app.route('/api/clear_all', methods=['DELETE']) def clear_all(): try: deleted_count = 0 for filename in os.listdir(app.config['UPLOAD_FOLDER']): filepath = os.path.join(app.config['UPLOAD_FOLDER'], filename) if os.path.isfile(filepath): os.remove(filepath) deleted_count += 1 socketio.emit('all_cleared', {}, namespace='/gallery') return jsonify({ 'status': 'success', 'message': f'Deleted {deleted_count} images' }) except Exception as e: return jsonify({'status': 'error', 'message': str(e)}), 500 @socketio.on('connect', namespace='/gallery') def handle_gallery_connect(): print('Gallery client connected') emit('connected', {'data': 'Connected to gallery updates'}) @socketio.on('disconnect', namespace='/gallery') def handle_gallery_disconnect(): print('Gallery client disconnected') if __name__ == '__main__': print("=" * 50) print("Camera Website Server Starting...") print("Access URLs:") print(" User Page: http://localhost:5000") print(" Admin Gallery: http://localhost:5000/gallery") print("=" * 50) socketio.run(app, debug=True, host='0.0.0.0', port=7860, allow_unsafe_werkzeug=True)