commit dadc8cf1717968b7af326fcd16b6ab9485d42da9 Author: Colby Lipsett Date: Thu Oct 2 18:20:08 2025 +0000 Upload files to "/" diff --git a/app.py b/app.py new file mode 100644 index 0000000..ed4f1f6 --- /dev/null +++ b/app.py @@ -0,0 +1,93 @@ +from flask import Flask, render_template +from flask_socketio import SocketIO, emit +import ssl +import os + +app = Flask(__name__, static_folder='static', template_folder='templates') +app.config['SECRET_KEY'] = 'your-secret-key-change-this-in-production' +socketio = SocketIO(app, cors_allowed_origins="*") + +# Store connected clients with their usernames +connected_clients = {} # Format: {session_id: {'username': 'name', 'connected_at': timestamp}} + +@app.route('/') +def index(): + return render_template('index.html') + +@socketio.on('connect') +def handle_connect(auth): + from flask import request + print(f'Client connected: {request.sid}') # type: ignore + connected_clients[request.sid] = {'username': None, 'connected_at': None} # type: ignore + +@socketio.on('disconnect') +def handle_disconnect(): + from flask import request + print(f'Client disconnected: {request.sid}') # type: ignore + if request.sid in connected_clients: # type: ignore + del connected_clients[request.sid] # type: ignore + # Notify other clients about disconnection + emit('user_disconnected', {'id': request.sid}, broadcast=True, include_self=False) # type: ignore + +@socketio.on('offer') +def handle_offer(data): + from flask import request + print(f'Received offer from {request.sid}') # type: ignore + # Broadcast offer to all other clients + data['id'] = request.sid # type: ignore + emit('offer', data, broadcast=True, include_self=False) + +@socketio.on('answer') +def handle_answer(data): + from flask import request + print(f'Received answer from {request.sid}') # type: ignore + # Send answer to specific client + emit('answer', data, to=data['id']) + +@socketio.on('ice_candidate') +def handle_ice_candidate(data): + from flask import request + print(f'Received ICE candidate from {request.sid}') # type: ignore + # Broadcast ICE candidate to all other clients or specific client + if 'target_id' in data: + emit('ice_candidate', data, to=data['target_id']) + else: + emit('ice_candidate', data, broadcast=True, include_self=False) + +@socketio.on('join_room') +def handle_join_room(data=None): + from flask import request + username = data.get('username', 'Anonymous') if data else 'Anonymous' + print(f'Client {request.sid} ({username}) joining room') # type: ignore + + # Update client info with username + if request.sid in connected_clients: # type: ignore + connected_clients[request.sid]['username'] = username # type: ignore + connected_clients[request.sid]['connected_at'] = __import__('time').time() # type: ignore + + # Get list of existing users with usernames (excluding the new user) + existing_users = [] + for user_id, user_info in connected_clients.items(): + if user_id != request.sid and user_info['username']: # type: ignore + existing_users.append({ + 'id': user_id, + 'username': user_info['username'] + }) + + # Send existing users list to the new user + if existing_users: + emit('existing_users', {'users': existing_users}) + + # Notify existing clients about new user + emit('user_joined', { + 'id': request.sid, # type: ignore + 'username': username + }, broadcast=True, include_self=False) + +if __name__ == '__main__': + # Set up SSL context + context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) + context.load_cert_chain('cert.pem', 'key.pem') + + print("Starting Flask-SocketIO server on https://localhost:3000") + socketio.run(app, host='localhost', port=3000, ssl_context=context, debug=True) \ No newline at end of file diff --git a/cert.pem b/cert.pem new file mode 100644 index 0000000..fcc4e0a --- /dev/null +++ b/cert.pem @@ -0,0 +1,31 @@ +-----BEGIN CERTIFICATE----- +MIIFazCCA1OgAwIBAgIUDg+0vek+WVKtsJV9UjTTd5H9Yo4wDQYJKoZIhvcNAQEL +BQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM +GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yNDA0MzAwOTM3MDBaFw0yNTA0 +MzAwOTM3MDBaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEw +HwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggIiMA0GCSqGSIb3DQEB +AQUAA4ICDwAwggIKAoICAQDOfyJn/B9y1u49Hq1ws1WqyN37KvXDbrcGqfakY+sL +f0PwRg7DL82gmPmrJryXHNBpTrmos2K3mJt1M5wLFg+UfUVyVLel2S0enBGDcdZJ +zdQPiz0ktc/OPDPwBsHAVEevh7ydIEzYufPDBh8bddbZK38FeNCoZVBUql36Cb7H +aSUhdaW5GwLck/bPEdiOJIWFXGqv7wh9echy1H59lnljdsDnfEyGG8c/Pf4XrTcO +P4NDLZ3Gp18cp3F5TigTxq7orqBnWEB6VvS3oS3PFNqVF2qUqCwoYwGA/k6v3WqT +0Z3Z8EB9CB9gbUgMLEWIpsRSopPAJkQrGiAdRjqkhJMorXKVqGttYXfHoXbUjlSW +B57kW2pZHQ3DIy1j4goWu9QZP504XNBlyo3l6nvllybA6I5jpfGb+fKnuokB7KmL +bsr2xynWBfo/OcAYvPopPtEPcsvwaRTo8V3omH/ogMrLtOzI8NaHG+xuodpBsnMe +DPjCD6CrbHcEdRMdw5oIN1vFad4R1Gi27Je8lbiV8a9KGFFqH1BJ2C/EQ+e2DY8Y +OKP/yLZ2kjYa3DRg9IJGiEOVyx8aeBD3rtxyE3IX8nXGziz9jKMWAvDoaMjtkT2k +SYyfOnfqt6cQcpOSLWiHsoKHAcOG5Fiel5SE13J1WYA13ES/fEQyBckk9gf1awgn +GwIDAQABo1MwUTAdBgNVHQ4EFgQU7bukSQax6UeiYDJV/M5N9hZ1LVkwHwYDVR0j +BBgwFoAU7bukSQax6UeiYDJV/M5N9hZ1LVkwDwYDVR0TAQH/BAUwAwEB/zANBgkq +hkiG9w0BAQsFAAOCAgEArwMiHvYVWQRV4DmnS5UbAu006S2gpw/A7UP5BMuLDAHO +/uqdbiBFNYQTtIwU15XDhJEQJCJAs4nDMv8ax27gAdOPJ9eGKOTM18VwgshzCQbo +IokIspItVzCmUwj4H/HW3d0w1rqb6gxn6RJWgpTCOpdLtrHpDnarS9Ro0obaGtWC +oj7CSmZDK/RtbWR5QyyDq3kgONLsR5/x4iI6lnsjEUXgUseOa2aydC3pJlsqozta +iHki3jeldmoROZtDnR9tZtJl210hovq8PpdjtEom4TjDWUONVVgliM9mu6in7z+Q +0yTwxPRjKFXL+7+LtlaQAVRgGGMyXQCYBs1ScXgiQbOCW6L2BPwUPS0k594AdQ1Q ++kj6/FpTFerUQJyiov18SQX6o/MqW+I8p4EPz640Z3WhLKqQny/HIFQoOwsriyAc +i9v7I2YdJZkzj1lLpaaiEw4r+l77wPdaIImBuntqTgpL7EpdQXgQpbbcA4TAuKYk +s7R5h5c7LTsAaQ50t8Zji9Gh5+E8VCsLNkcOnjrSwiL4bscR6/3dmAg66vt9sr3t +sTDQSJyEHbx1yPu6niQ+iHH8azomRo+fbpJvjW8L9UYD09IhehjKDnWIpFiR0bQ1 +GzQKkNL1+yAV5XCxiod1UrXwOP015qaY3x+cTclR+hFgmUQIwTjph5hQGUqxX4g= +-----END CERTIFICATE----- diff --git a/key.pem b/key.pem new file mode 100644 index 0000000..5a5c3be --- /dev/null +++ b/key.pem @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +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 +kVJ7PW1aIDSJnFsDWmsotAyutuoDSk4= +-----END PRIVATE KEY----- diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..0013581 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,4 @@ +Flask==2.3.3 +Flask-SocketIO==5.3.6 +python-socketio==5.9.0 +eventlet==0.33.3 \ No newline at end of file diff --git a/setup.sh b/setup.sh new file mode 100644 index 0000000..d690649 --- /dev/null +++ b/setup.sh @@ -0,0 +1,27 @@ +#!/bin/bash + +echo "Setting up Python Flask Video Chat Application..." + +# Create virtual environment if it doesn't exist +if [ ! -d "venv" ]; then + echo "Creating virtual environment..." + python3 -m venv venv +fi + +# Activate virtual environment +echo "Activating virtual environment..." +source venv/bin/activate + +# Install dependencies +echo "Installing dependencies..." +pip install -r requirements.txt + +echo "" +echo "Setup complete!" +echo "" +echo "To run the application:" +echo "1. Activate the virtual environment: source venv/bin/activate" +echo "2. Run the Flask app: python app.py" +echo "3. Open https://localhost:2000 in your browser" +echo "" +echo "Note: You may need to accept the self-signed certificate in your browser." \ No newline at end of file