Spaces:
Sleeping
Sleeping
from fastapi import FastAPI, WebSocket, WebSocketDisconnect | |
from fastapi.responses import HTMLResponse | |
from typing import List, Dict | |
import json | |
app = FastAPI() | |
html = """ | |
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>ChatApp</title> | |
<script src="https://cdn.tailwindcss.com"></script> | |
<style> | |
body { | |
background-color: #1a202c; | |
color: white; | |
font-family: Arial, sans-serif; | |
display: flex; | |
justify-content: center; | |
align-items: center; | |
height: 100vh; | |
margin: 0; | |
} | |
.chat-container { | |
max-width: 800px; | |
width: 100%; | |
display: flex; | |
flex-direction: column; | |
background-color: #2d3748; | |
border-radius: 8px; | |
overflow: hidden; | |
} | |
.messages { | |
flex: 1; | |
overflow-y: auto; | |
padding: 20px; | |
background-color: #1a202c; | |
} | |
.message { | |
margin-bottom: 10px; | |
display: flex; | |
align-items: center; | |
} | |
.message .username { | |
font-weight: bold; | |
color: #63b3ed; | |
margin-right: 10px; | |
} | |
.form-container { | |
display: flex; | |
padding: 10px; | |
background-color: #4a5568; | |
} | |
.form-container input, | |
.form-container button { | |
margin-right: 10px; | |
} | |
.form-container input { | |
flex: 1; | |
padding: 10px; | |
border: none; | |
border-radius: 4px; | |
background-color: #718096; | |
color: white; | |
} | |
.form-container button { | |
padding: 10px 20px; | |
background-color: #3182ce; | |
border: none; | |
border-radius: 4px; | |
color: white; | |
cursor: pointer; | |
} | |
</style> | |
</head> | |
<body> | |
<div class="chat-container"> | |
<div class="messages" id="messages"></div> | |
<div class="form-container"> | |
<input type="text" id="username" placeholder="Username" class="p-2 rounded" required> | |
<input type="text" id="recipient" placeholder="Recipient" class="p-2 rounded" required> | |
<input type="text" id="messageText" placeholder="Message" class="p-2 rounded" required> | |
<button onclick="sendMessage()" class="p-2 bg-blue-500 rounded">Send</button> | |
</div> | |
</div> | |
<script> | |
var ws = new WebSocket("wss://hans-r-d-web-sockets.hf.space/ws"); | |
ws.onmessage = function(event) { | |
var messages = document.getElementById('messages'); | |
var messageData = JSON.parse(event.data); | |
var message = document.createElement('div'); | |
message.className = 'message'; | |
var username = document.createElement('span'); | |
username.className = 'username'; | |
username.textContent = messageData.sender; | |
var text = document.createElement('span'); | |
text.textContent = ": " + messageData.text; | |
message.appendChild(username); | |
message.appendChild(text); | |
messages.appendChild(message); | |
messages.scrollTop = messages.scrollHeight; | |
}; | |
function sendMessage() { | |
var username = document.getElementById("username").value; | |
var recipient = document.getElementById("recipient").value; | |
var input = document.getElementById("messageText"); | |
var message = { | |
"sender": username, | |
"recipient": recipient, | |
"text": input.value | |
}; | |
ws.send(JSON.stringify(message)); | |
input.value = ''; | |
} | |
</script> | |
</body> | |
</html> | |
""" | |
async def get(): | |
return HTMLResponse(html) | |
class ConnectionManager: | |
def __init__(self): | |
self.active_connections: Dict[str, WebSocket] = {} | |
async def connect(self, username: str, websocket: WebSocket): | |
await websocket.accept() | |
self.active_connections[username] = websocket | |
def disconnect(self, username: str): | |
self.active_connections.pop(username, None) | |
async def send_personal_message(self, message: str, recipient: str): | |
recipient_ws = self.active_connections.get(recipient) | |
if recipient_ws: | |
await recipient_ws.send_text(message) | |
manager = ConnectionManager() | |
async def websocket_endpoint(websocket: WebSocket): | |
username = None | |
try: | |
while True: | |
data = await websocket.receive_text() | |
message = json.loads(data) | |
username = message["sender"] | |
if username not in manager.active_connections: | |
await manager.connect(username, websocket) | |
await manager.send_personal_message(json.dumps(message), message["recipient"]) | |
except WebSocketDisconnect: | |
if username: | |
manager.disconnect(username) |