Upload files to "/"

This commit is contained in:
2025-10-02 18:20:08 +00:00
commit dadc8cf171
5 changed files with 207 additions and 0 deletions

93
app.py Normal file
View File

@@ -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)

31
cert.pem Normal file
View File

@@ -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-----

52
key.pem Normal file
View File

@@ -0,0 +1,52 @@
-----BEGIN PRIVATE KEY-----
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
kVJ7PW1aIDSJnFsDWmsotAyutuoDSk4=
-----END PRIVATE KEY-----

4
requirements.txt Normal file
View File

@@ -0,0 +1,4 @@
Flask==2.3.3
Flask-SocketIO==5.3.6
python-socketio==5.9.0
eventlet==0.33.3

27
setup.sh Normal file
View File

@@ -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."