import streamlit as st import asyncio import websockets import uuid import argparse from datetime import datetime import os import random import time # Fun usernames with emojis - the VIP list of quirky characters! ππ FUN_USERNAMES = [ "CosmicJester π", "PixelPanda πΌ", "QuantumQuack π¦", "StellarSquirrel πΏοΈ", "GizmoGuru βοΈ", "NebulaNinja π ", "ByteBuster πΎ", "GalacticGopher π", "RocketRaccoon π", "EchoElf π§", "PhantomFox π¦", "WittyWizard π§", "LunarLlama π", "SolarSloth βοΈ", "AstroAlpaca π¦", "CyberCoyote πΊ", "MysticMoose π¦", "GlitchGnome π§", "VortexViper π", "ChronoChimp π" ] # Directory for chat logs - the secret vault where tales are stashed! ποΈπ CHAT_DIR = "chat_logs" os.makedirs(CHAT_DIR, exist_ok=True) # Persistent chat file - the grand tome of all chatter! πβ¨ CHAT_FILE = os.path.join(CHAT_DIR, "global_chat.md") # Node name - the appβs codename generator, sneaky and slick! π΅οΈββοΈπΎ def get_node_name(): """π² Spins the wheel of fate to name our node - a random alias or user pick! π·οΈ""" parser = argparse.ArgumentParser(description='Start a chat node with a specific name') parser.add_argument('--node-name', type=str, default=None, help='Name for this chat node') parser.add_argument('--port', type=int, default=8501, help='Port to run the Streamlit interface on') # Default Streamlit port args = parser.parse_args() return args.node_name or f"node-{uuid.uuid4().hex[:8]}", args.port # Chat saver - the scribe etching epic messages into the eternal scroll! ποΈπ def save_chat_entry(username, message): """ποΈ Carves a chat line into the grand Markdown tome - history in the making! ποΈ""" timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") entry = f"[{timestamp}] {username}: {message}" try: with open(CHAT_FILE, 'a') as f: f.write(f"{entry}\n") return True except Exception as e: print(f"Oops! Failed to save chat: {e}") return False # Chat loader - the archaeologist unearthing the chat saga! βοΈπ def load_chat(): """π Digs up the chat treasure from the filesystem - tales of old and new! π°""" if not os.path.exists(CHAT_FILE): with open(CHAT_FILE, 'w') as f: f.write("# Global Chat\n\nNo messages yet - start chatting! π€\n") try: with open(CHAT_FILE, 'r') as f: content = f.read() lines = content.strip().split('\n') numbered_content = "\n".join(f"{i+1}. {line}" for i, line in enumerate(lines) if line.strip()) return numbered_content except Exception as e: print(f"Chat load hiccup: {e}") return "# Error loading chat\nSomething went wonky! π΅" # User list grabber - the social butterfly spotting all the chatters! π¦π₯ def get_user_list(chat_content): """π Peeks at the chat to spot all the cool cats talking - whoβs in the club? πΈ""" users = set() for line in chat_content.split('\n'): if line.strip() and ': ' in line: user = line.split(': ')[1].split(' ')[0] users.add(user) return sorted(list(users)) active_connections = {} # WebSocket handler - the bouncer at the chat rave, keeping it hopping! ππͺ async def websocket_handler(websocket, path): """π§ Guards the chat gate, letting messages fly and booting crashers! π¨""" try: client_id = str(uuid.uuid4()) room_id = "chat" active_connections.setdefault(room_id, {})[client_id] = websocket print(f"Client {client_id} joined the chat party!") async for message in websocket: try: parts = message.split('|', 1) if len(parts) == 2: username, content = parts save_chat_entry(username, content) await broadcast_message(f"{username}|{content}", room_id) except Exception as e: print(f"Message mishap: {e}") await websocket.send(f"ERROR|Oops, bad message format! π¬") except websockets.ConnectionClosed: print(f"Client {client_id} bailed from the chat!") finally: if room_id in active_connections and client_id in active_connections[room_id]: del active_connections[room_id][client_id] if not active_connections[room_id]: del active_connections[room_id] # Broadcaster - the megaphone blasting chat vibes to all! π£πΆ async def broadcast_message(message, room_id): """π’ Shouts the latest chat beat to every dancer in the room - hear it loud! π΅""" if room_id in active_connections: disconnected = [] for client_id, ws in active_connections[room_id].items(): try: await ws.send(message) except websockets.ConnectionClosed: disconnected.append(client_id) for client_id in disconnected: del active_connections[room_id][client_id] # WebSocket starter - the DJ spinning up the chat tunes! π§π₯ async def start_websocket_server(host='0.0.0.0', port=8765): """π Cranks up the WebSocket jukebox, ready to rock the chat scene! πΈ""" server = await websockets.serve(websocket_handler, host, port) print(f"WebSocket server jamming on ws://{host}:{port}") return server # Chat interface maker - the stage builder for our chat extravaganza! πποΈ def create_streamlit_interface(initial_username): """ποΈ Sets up the chat stage with live updates and name-switching flair! π""" # Custom CSS for a sleek chat box st.markdown(""" """, unsafe_allow_html=True) # Title and intro st.title(f"Chat Node: {NODE_NAME}") st.markdown("Chat live, switch names, and keep the party going! π") # Session state to persist username if 'username' not in st.session_state: st.session_state.username = initial_username # Chat display chat_content = load_chat() st.markdown(f"