its working
This commit is contained in:
parent
3410f98d7e
commit
30d01b82b0
2 changed files with 119 additions and 41 deletions
90
server.py
90
server.py
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
import asyncio
|
||||
from fastapi import FastAPI, Request, WebSocket, WebSocketDisconnect
|
||||
from fastapi.responses import HTMLResponse
|
||||
import json
|
||||
from redis import asyncio as redis
|
||||
|
||||
|
|
@ -24,6 +25,43 @@ templates = Jinja2Templates(directory="templates")
|
|||
# Redis connection
|
||||
redis_client = redis.Redis(host="localhost", port=6379, decode_responses=True)
|
||||
|
||||
new_button = """
|
||||
|
||||
<div id='after_chat_wrapper'>
|
||||
<div
|
||||
id='after_chat'
|
||||
class='h-12'
|
||||
_="
|
||||
on load
|
||||
wait 10ms
|
||||
on intersection(intersecting) having threshold 0.5
|
||||
if #go_to_bottom exists and intersecting
|
||||
then remove #go_to_bottom
|
||||
|
||||
|
||||
"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div id="after_form" class='mb-24'>
|
||||
<button
|
||||
id="go_to_bottom"
|
||||
class="fixed bottom-0 right-0 px-2 py-1 rounded font-bold m-4 invisible"
|
||||
hx-get="/null"
|
||||
hx-swap="outerHTML"
|
||||
hx-trigger="intersect from:#after_chat"
|
||||
_="
|
||||
on load
|
||||
wait 10ms
|
||||
remove .invisible
|
||||
on click
|
||||
go to bottom of the body
|
||||
"
|
||||
>
|
||||
go to bottom
|
||||
</button>
|
||||
</div>
|
||||
"""
|
||||
# Constants
|
||||
REDIS_MESSAGE_LIST = "chat_messages"
|
||||
WEBSOCKET_CHANNEL = "websocket_channel"
|
||||
|
|
@ -41,6 +79,7 @@ async def listen_to_redis():
|
|||
await pubsub.subscribe(WEBSOCKET_CHANNEL)
|
||||
|
||||
async for message in pubsub.listen():
|
||||
print(message)
|
||||
if message["type"] == "message":
|
||||
data = message["data"]
|
||||
data = json.loads(data)
|
||||
|
|
@ -52,11 +91,16 @@ async def listen_to_redis():
|
|||
color_level = color_levels[level]
|
||||
# Send message to all connected clients
|
||||
for name, websocket in connected_clients.items():
|
||||
if data.get("name") == name:
|
||||
html_data = f'<div id="chat_room" hx-swap-oob="beforeend"><li class="px-4 py-2 h-12 w-64 rounded bg-green-{color_level} ml-8 my-4">{data.get("name")}: {data.get("chat_message")}</li></div>'
|
||||
else:
|
||||
html_data = f'<div id="chat_room" hx-swap-oob="beforeend"><li class="px-4 py-2 h-12 w-64 rounded bg-blue-{color_level} my-4">{data.get("name")}: {data.get("chat_message")}</li></div>'
|
||||
await websocket.send_text(html_data)
|
||||
html_data = ""
|
||||
|
||||
if "chat_message" in data:
|
||||
if data.get("name") == name:
|
||||
html_data += f'<div id="chat_room" hx-swap-oob="beforeend" hx-swap="scroll:bottom"><li class="px-4 py-2 h-12 w-124 rounded bg-green-{color_level} ml-8 my-4">{data.get("name")}: {data.get("chat_message")}</li></div>'
|
||||
else:
|
||||
html_data += f'<div id="chat_room" hx-swap-oob="beforeend" hx-swap="scroll:bottom"><li class="px-4 py-2 h-12 w-124 rounded bg-blue-{color_level} my-4">{data.get("name")}: {data.get("chat_message")}</li></div>'
|
||||
if "notification" in data:
|
||||
html_data += f'<div id="notifications" hx-swap-oob="beforeend"><li class="px-4 py-2 h-12 w-64 rounded bg-blue-{color_level} my-4" _="on click remove me on load wait 3s remove me" hx-trigger="click, load delay:3s" hx-swap="outerHTML">{data.get("notification")}</li></div>'
|
||||
await websocket.send_text(html_data + new_button)
|
||||
|
||||
|
||||
@app.on_event("startup")
|
||||
|
|
@ -106,28 +150,41 @@ async def websocket_endpoint(websocket: WebSocket):
|
|||
|
||||
name = random.choice(chat_names)
|
||||
connected_clients[name] = websocket
|
||||
|
||||
data = {
|
||||
"name": name,
|
||||
"notification": f"{name} joined the chat",
|
||||
}
|
||||
|
||||
data_str = json.dumps(data)
|
||||
|
||||
await redis_client.publish(WEBSOCKET_CHANNEL, data_str)
|
||||
|
||||
# Send previous messages to the new client
|
||||
messages = await redis_client.lrange(REDIS_MESSAGE_LIST, 0, -1)
|
||||
for msg in messages:
|
||||
msg_data = json.loads(msg)
|
||||
color_level = color_levels[0] # Use first color level for old messages
|
||||
if msg_data.get("name") == name:
|
||||
html_data = f'<div id="chat_room" hx-swap-oob="beforeend"><li class="px-4 py-2 h-12 w-64 rounded bg-green-{color_level} ml-8 my-4">{msg_data.get("name")}: {msg_data.get("chat_message")}</li></div>'
|
||||
else:
|
||||
html_data = f'<div id="chat_room" hx-swap-oob="beforeend"><li class="px-4 py-2 h-12 w-64 rounded bg-blue-{color_level} my-4">{msg_data.get("name")}: {msg_data.get("chat_message")}</li></div>'
|
||||
await websocket.send_text(html_data)
|
||||
|
||||
html_data = ""
|
||||
if "chat_message" in msg_data:
|
||||
if msg_data.get("name") == name:
|
||||
html_data += f'<div id="chat_room" hx-swap-oob="beforeend"><li class="px-4 py-2 h-12 w-124 rounded bg-green-{color_level} ml-8 my-4" _="">{msg_data.get("name")}: {msg_data.get("chat_message")}</li></div>'
|
||||
|
||||
else:
|
||||
html_data += f'<div id="chat_room" hx-swap-oob="beforeend"><li class="px-4 py-2 h-12 w-124 rounded bg-blue-{color_level} my-4" _="">{msg_data.get("name")}: {msg_data.get("chat_message")}</li></div>'
|
||||
if "notification" in msg_data:
|
||||
html_data += f'<div id="notifications" hx-swap-oob="beforeend"><li class="px-4 py-2 h-12 w-64 rounded bg-blue-{color_level} my-4">{msg_data.get("notification")}</li></div>'
|
||||
await websocket.send_text(html_data + new_button)
|
||||
|
||||
try:
|
||||
while True:
|
||||
data = await websocket.receive_text()
|
||||
data = json.loads(data)
|
||||
data["name"] = name
|
||||
data_str = json.dumps(data)
|
||||
|
||||
|
||||
# Store message in Redis list
|
||||
await redis_client.rpush(REDIS_MESSAGE_LIST, data_str)
|
||||
|
||||
|
||||
# Publish message to Redis
|
||||
await redis_client.publish(WEBSOCKET_CHANNEL, data_str)
|
||||
except WebSocketDisconnect:
|
||||
|
|
@ -139,6 +196,11 @@ async def root(request: Request):
|
|||
return templates.TemplateResponse("index.html", {"request": request})
|
||||
|
||||
|
||||
@app.get("/null")
|
||||
async def root(request: Request):
|
||||
return HTMLResponse("")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import uvicorn
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue