awacke1 commited on
Commit
ef89835
·
verified ·
1 Parent(s): 34fcd26

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +78 -86
app.py CHANGED
@@ -18,22 +18,22 @@ import edge_tts
18
  from audio_recorder_streamlit import audio_recorder
19
  import nest_asyncio
20
 
21
- # Apply patch to allow nested asyncio.run() calls
22
  nest_asyncio.apply()
23
 
24
- # Initial App Configuration (static)
25
  icons = '🤖🧠🔬📝'
26
  START_ROOM = "Sector 🌌"
27
 
28
- # Set page config once at the top
29
  st.set_page_config(
30
- page_title="🤖🧠MMO Chat Brain📝🔬", # Initial static title
31
  page_icon=icons,
32
  layout="wide",
33
  initial_sidebar_state="auto"
34
  )
35
 
36
- # Fun usernames with emojis and their paired voices
37
  FUN_USERNAMES = {
38
  "CosmicJester 🌌": "en-US-AriaNeural",
39
  "PixelPanda 🐼": "en-US-JennyNeural",
@@ -57,7 +57,7 @@ FUN_USERNAMES = {
57
  "ChronoChimp 🐒": "en-US-JennyNeural"
58
  }
59
 
60
- # Directories and files
61
  CHAT_DIR = "chat_logs"
62
  VOTE_DIR = "vote_logs"
63
  STATE_FILE = "user_state.txt"
@@ -73,34 +73,51 @@ QUOTE_VOTES_FILE = os.path.join(VOTE_DIR, "quote_votes.md")
73
  MEDIA_VOTES_FILE = os.path.join(VOTE_DIR, "media_votes.md")
74
  HISTORY_FILE = os.path.join(HISTORY_DIR, "chat_history.md")
75
 
76
- # Unicode digits and fonts
77
  UNICODE_DIGITS = {i: f"{i}\uFE0F⃣" for i in range(10)}
 
 
78
  UNICODE_FONTS = [
79
  ("Normal", lambda x: x),
80
  ("Bold", lambda x: "".join(chr(ord(c) + 0x1D400 - 0x41) if 'A' <= c <= 'Z' else chr(ord(c) + 0x1D41A - 0x61) if 'a' <= c <= 'z' else c for c in x)),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
81
  ]
82
 
83
  server_running = False
84
  server_task = None
85
 
86
- # Helper Functions
87
  def format_timestamp_prefix():
88
- """📅 - Time Stamp Champ - Marks the clock, no flop!"""
89
  return datetime.now().strftime("%Y%m%d_%H%M%S")
90
 
 
91
  def get_node_name():
92
- """🌐 - Naming Node with Code - Spins a name, oh so bold!"""
93
- action = "🌐 - Naming Node with Code - Spins a name, oh so bold!"
94
- username = st.session_state.get('username', 'System 🌟')
95
- log_action(username, action)
96
  parser = argparse.ArgumentParser(description='Start a chat node with a specific name')
97
  parser.add_argument('--node-name', type=str, default=None)
98
  parser.add_argument('--port', type=int, default=8501)
99
  args = parser.parse_args()
 
 
100
  return args.node_name or f"node-{uuid.uuid4().hex[:8]}", args.port
101
 
 
102
  def log_action(username, action):
103
- """📜 - Log Jog Blog - Tracks the deed, no greed!"""
104
  if 'action_log' not in st.session_state:
105
  st.session_state.action_log = {}
106
  user_log = st.session_state.action_log.setdefault(username, {})
@@ -112,36 +129,32 @@ def log_action(username, action):
112
  f.write(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] {username}: {action}\n")
113
  user_log[action] = current_time
114
 
 
115
  async def save_chat_entry(username, message):
116
- """📝 - Chat Snap Trap - Logs your yap, no cap! ✍️🧠"""
117
- action = "📝 - Chat Snap Trap - Logs your yap, no cap! ✍️🧠"
118
- await asyncio.to_thread(log_action, username, action)
119
  timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
120
  entry = f"[{timestamp}] {username}: {message}"
121
  await asyncio.to_thread(lambda: open(CHAT_FILE, 'a').write(f"{entry}\n"))
122
- # Generate and save audio for the message
123
  voice = FUN_USERNAMES.get(username, "en-US-AriaNeural")
124
  audio_file = await async_edge_tts_generate(message, voice)
125
  if audio_file:
126
  with open(HISTORY_FILE, 'a') as f:
127
  f.write(f"[{timestamp}] {username}: Audio generated - {audio_file}\n")
128
 
 
129
  async def load_chat():
130
- """📖 - Chat Fetch Quest - Grabs the log, no jest!"""
131
- action = "📖 - Chat Fetch Quest - Grabs the log, no jest!"
132
  username = st.session_state.get('username', 'System 🌟')
133
- await asyncio.to_thread(log_action, username, action)
134
  if not os.path.exists(CHAT_FILE):
135
  await asyncio.to_thread(lambda: open(CHAT_FILE, 'w').write(f"# {START_ROOM} Chat\n\nWelcome to the cosmic hub - start chatting! 🎤\n"))
136
  with open(CHAT_FILE, 'r') as f:
137
  content = await asyncio.to_thread(f.read)
138
  return content
139
 
 
140
  async def get_user_list(chat_content):
141
- """👥 - Crew Clue Brew - Spots who’s who in the crew!"""
142
- action = "👥 - Crew Clue Brew - Spots who’s who in the crew!"
143
  username = st.session_state.get('username', 'System 🌟')
144
- await asyncio.to_thread(log_action, username, action)
145
  users = set()
146
  for line in chat_content.split('\n'):
147
  if line.strip() and ': ' in line:
@@ -149,26 +162,23 @@ async def get_user_list(chat_content):
149
  users.add(user)
150
  return sorted(list(users))
151
 
 
152
  async def has_joined_before(client_id, chat_content):
153
- """🚪 - Join Check Trek - Sees who’s back, no wreck!"""
154
- action = "🚪 - Join Check Trek - Sees who’s back, no wreck!"
155
  username = st.session_state.get('username', 'System 🌟')
156
- await asyncio.to_thread(log_action, username, action)
157
  return any(f"Client-{client_id} has joined" in line for line in chat_content.split('\n'))
158
 
 
159
  async def get_message_suggestions(chat_content, prefix):
160
- """🔍 - Suggest Jest Chest - Finds old quips, the best!"""
161
- action = "🔍 - Suggest Jest Chest - Finds old quips, the best!"
162
  username = st.session_state.get('username', 'System 🌟')
163
- await asyncio.to_thread(log_action, username, action)
164
  lines = chat_content.split('\n')
165
  messages = [line.split(': ', 1)[1] for line in lines if ': ' in line and line.strip()]
166
  return [msg for msg in messages if msg.lower().startswith(prefix.lower())][:5]
167
 
 
168
  async def save_vote(file, item, user_hash, username, comment=""):
169
- """👍 - Vote Note Float - Cheers rise, we gloat!"""
170
- action = "👍 - Vote Note Float - Cheers rise, we gloat!"
171
- await asyncio.to_thread(log_action, username, action)
172
  timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
173
  entry = f"[{timestamp}] {user_hash} voted for {item}"
174
  await asyncio.to_thread(lambda: open(file, 'a').write(f"{entry}\n"))
@@ -178,11 +188,10 @@ async def save_vote(file, item, user_hash, username, comment=""):
178
  chat_message += f" - {comment}"
179
  await save_chat_entry(username, chat_message)
180
 
 
181
  async def load_votes(file):
182
- """🏆 - Tally Rally Call - Counts the cheers, no stall!"""
183
- action = "🏆 - Tally Rally Call - Counts the cheers, no stall!"
184
  username = st.session_state.get('username', 'System 🌟')
185
- await asyncio.to_thread(log_action, username, action)
186
  if not os.path.exists(file):
187
  await asyncio.to_thread(lambda: open(file, 'w').write("# Vote Tally\n\nNo votes yet - get clicking! 🖱️\n"))
188
  with open(file, 'r') as f:
@@ -199,28 +208,26 @@ async def load_votes(file):
199
  user_votes.add(vote_key)
200
  return votes
201
 
 
202
  async def generate_user_hash():
203
- """🔑 - Hash Dash Bash - Crafts a code, so brash!"""
204
- action = "🔑 - Hash Dash Bash - Crafts a code, so brash!"
205
  username = st.session_state.get('username', 'System 🌟')
206
- await asyncio.to_thread(log_action, username, action)
207
  if 'user_hash' not in st.session_state:
208
  st.session_state.user_hash = hashlib.md5(str(random.getrandbits(128)).encode()).hexdigest()[:8]
209
  return st.session_state.user_hash
210
 
 
211
  async def async_edge_tts_generate(text, voice, rate=0, pitch=0, file_format="mp3"):
212
- """🎶 - Tune Moon Boom - Drops a beat, so groom!"""
213
- action = "🎶 - Tune Moon Boom - Drops a beat, so groom!"
214
  username = st.session_state.get('username', 'System 🌟')
215
- await asyncio.to_thread(log_action, username, action)
216
  timestamp = format_timestamp_prefix()
217
  filename = os.path.join(AUDIO_DIR, f"audio_{timestamp}_{random.randint(1000, 9999)}.mp3")
218
  communicate = edge_tts.Communicate(text, voice, rate=f"{rate:+d}%", pitch=f"{pitch:+d}Hz")
219
  await communicate.save(filename)
220
  return filename if os.path.exists(filename) else None
221
 
 
222
  def play_and_download_audio(file_path):
223
- """🔊 - Sound Pound Ground - Plays it loud, all around!"""
224
  if file_path and os.path.exists(file_path):
225
  st.audio(file_path)
226
  with open(file_path, "rb") as f:
@@ -228,11 +235,10 @@ def play_and_download_audio(file_path):
228
  dl_link = f'<a href="data:audio/mpeg;base64,{b64}" download="{os.path.basename(file_path)}">🎵 Download {os.path.basename(file_path)}</a>'
229
  st.markdown(dl_link, unsafe_allow_html=True)
230
 
 
231
  async def save_pasted_image(image_data):
232
- """📸 - Snap Cap Trap - Saves your pic, no flap!"""
233
- action = "📸 - Snap Cap Trap - Saves your pic, no flap!"
234
  username = st.session_state.get('username', 'System 🌟')
235
- await asyncio.to_thread(log_action, username, action)
236
  timestamp = format_timestamp_prefix()
237
  filename = f"paste_{timestamp}.png"
238
  filepath = os.path.join('./', filename)
@@ -243,29 +249,26 @@ async def save_pasted_image(image_data):
243
  await asyncio.to_thread(img.save, filepath, "PNG")
244
  return filename
245
 
 
246
  async def get_video_html(video_path, width="100%"):
247
- """🎥 - Reel Deal Steal - Plays your flick, so real!"""
248
- action = "🎥 - Reel Deal Steal - Plays your flick, so real!"
249
  username = st.session_state.get('username', 'System 🌟')
250
- await asyncio.to_thread(log_action, username, action)
251
  video_url = f"data:video/mp4;base64,{base64.b64encode(await asyncio.to_thread(open, video_path, 'rb').read()).decode()}"
252
  return f'<video width="{width}" controls autoplay muted loop><source src="{video_url}" type="video/mp4">Your browser does not support the video tag.</video>'
253
 
 
254
  async def get_audio_html(audio_path, width="100%"):
255
- """🎶 - Tune Moon Boom - Drops a beat, so groom!"""
256
- action = "🎶 - Tune Moon Boom - Drops a beat, so groom!"
257
  username = st.session_state.get('username', 'System 🌟')
258
- await asyncio.to_thread(log_action, username, action)
259
  audio_url = f"data:audio/mpeg;base64,{base64.b64encode(await asyncio.to_thread(open, audio_path, 'rb').read()).decode()}"
260
  return f'<audio controls style="width: {width};"><source src="{audio_url}" type="audio/mpeg">Your browser does not support the audio element.</audio>'
261
 
262
  active_connections = {}
263
 
 
264
  async def websocket_handler(websocket, path):
265
- """🌐 - Web Sock Jock - Links the chat, no block!"""
266
- action = "🌐 - Web Sock Jock - Links the chat, no block!"
267
  username = st.session_state.get('username', 'System 🌟')
268
- await asyncio.to_thread(log_action, username, action)
269
  try:
270
  client_id = str(uuid.uuid4())
271
  room_id = "chat"
@@ -286,11 +289,10 @@ async def websocket_handler(websocket, path):
286
  if room_id in active_connections and client_id in active_connections[room_id]:
287
  del active_connections[room_id][client_id]
288
 
 
289
  async def broadcast_message(message, room_id):
290
- """📢 - Shout Out Bout - Blasts the word, no doubt!"""
291
- action = "📢 - Shout Out Bout - Blasts the word, no doubt!"
292
  username = st.session_state.get('username', 'System 🌟')
293
- await asyncio.to_thread(log_action, username, action)
294
  if room_id in active_connections:
295
  disconnected = []
296
  for client_id, ws in active_connections[room_id].items():
@@ -301,33 +303,28 @@ async def broadcast_message(message, room_id):
301
  for client_id in disconnected:
302
  del active_connections[room_id][client_id]
303
 
 
304
  async def run_websocket_server():
305
- """🖥️ - Server Ferver Verve - Spins the web, with nerve!"""
306
- action = "🖥️ - Server Ferver Verve - Spins the web, with nerve!"
307
  username = st.session_state.get('username', 'System 🌟')
308
- await asyncio.to_thread(log_action, username, action)
309
  global server_running, server_task
310
  if not server_running:
311
  server = await websockets.serve(websocket_handler, '0.0.0.0', 8765)
312
  server_running = True
313
  await server.wait_closed()
314
 
 
315
  async def process_voice_input(audio_bytes):
316
- """🎤 - Voice Choice Rejoice - Speaks your mind, oh boy!"""
317
- action = "🎤 - Voice Choice Rejoice - Speaks your mind, oh boy!"
318
  username = st.session_state.get('username', 'System 🌟')
319
- await asyncio.to_thread(log_action, username, action)
320
  if audio_bytes:
321
- # Simple placeholder for speech-to-text (requires additional library like `speech_recognition`)
322
- # For now, we'll simulate text input from audio
323
  text = "Voice input simulation" # Replace with actual speech-to-text logic
324
  await save_chat_entry(username, text)
325
 
 
326
  async def create_streamlit_interface():
327
- """🎨 - UI Brew Crew - Builds the view, so new!"""
328
- action = "🎨 - UI Brew Crew - Builds the view, so new!"
329
  username = st.session_state.get('username', 'System 🌟')
330
- await asyncio.to_thread(log_action, username, action)
331
 
332
  if 'username' not in st.session_state:
333
  chat_content = await load_chat()
@@ -410,9 +407,7 @@ async def create_streamlit_interface():
410
  quote_response = st.text_area("Add your response", key="quote_response")
411
  if st.button("Send Quote 🚀", key="send_quote"):
412
  async def process_quote():
413
- """📢 - Quote Float Boat - Echoes chat, we gloat!"""
414
- action = "📢 - Quote Float Boat - Echoes chat, we gloat!"
415
- await asyncio.to_thread(log_action, st.session_state.username, action)
416
  markdown_response = f"### Quote Response\n- **Original**: {st.session_state.quote_line}\n- **{st.session_state.username} Replies**: {quote_response}"
417
  if st.session_state.pasted_image_data:
418
  filename = await save_pasted_image(st.session_state.pasted_image_data)
@@ -425,7 +420,7 @@ async def create_streamlit_interface():
425
  st.session_state.message_text = ''
426
  st.rerun()
427
 
428
- # Username Change Dropdown
429
  new_username = st.selectbox("Change Name", [""] + list(FUN_USERNAMES.keys()), index=0)
430
  if new_username and new_username != st.session_state.username:
431
  await save_chat_entry("System 🌟", f"{st.session_state.username} changed name to {new_username}")
@@ -530,16 +525,13 @@ async def create_streamlit_interface():
530
  history_content = f.read()
531
  st.sidebar.markdown(history_content)
532
 
533
- async def main():
534
- """🎮 - Game Fame Claim - Starts the fun, no shame!"""
535
- action = "🎮 - Game Fame Claim - Starts the fun, no shame!"
536
- username = st.session_state.get('username', 'System 🌟')
537
- await asyncio.to_thread(log_action, username, action)
538
- global NODE_NAME, server_task
539
- NODE_NAME, port = await get_node_name()
540
- if server_task is None:
541
- server_task = asyncio.create_task(run_websocket_server())
542
- await create_streamlit_interface()
543
-
544
- if __name__ == "__main__":
545
- asyncio.run(main())
 
18
  from audio_recorder_streamlit import audio_recorder
19
  import nest_asyncio
20
 
21
+ # Patch for nested async - sneaky fix! 🐍✨
22
  nest_asyncio.apply()
23
 
24
+ # Static config - constants rule! 📏👑
25
  icons = '🤖🧠🔬📝'
26
  START_ROOM = "Sector 🌌"
27
 
28
+ # Page setup - dressing up the window! 🖼️🎀
29
  st.set_page_config(
30
+ page_title="🤖🧠MMO Chat Brain📝🔬",
31
  page_icon=icons,
32
  layout="wide",
33
  initial_sidebar_state="auto"
34
  )
35
 
36
+ # Funky usernames - who’s who in the zoo! 🎭🐾
37
  FUN_USERNAMES = {
38
  "CosmicJester 🌌": "en-US-AriaNeural",
39
  "PixelPanda 🐼": "en-US-JennyNeural",
 
57
  "ChronoChimp 🐒": "en-US-JennyNeural"
58
  }
59
 
60
+ # Folders galore - organizing chaos! 📂🌀
61
  CHAT_DIR = "chat_logs"
62
  VOTE_DIR = "vote_logs"
63
  STATE_FILE = "user_state.txt"
 
73
  MEDIA_VOTES_FILE = os.path.join(VOTE_DIR, "media_votes.md")
74
  HISTORY_FILE = os.path.join(HISTORY_DIR, "chat_history.md")
75
 
76
+ # Fancy digits - numbers got style! 🔢💃
77
  UNICODE_DIGITS = {i: f"{i}\uFE0F⃣" for i in range(10)}
78
+
79
+ # Massive font collection - typography bonanza! 🖋️🎨
80
  UNICODE_FONTS = [
81
  ("Normal", lambda x: x),
82
  ("Bold", lambda x: "".join(chr(ord(c) + 0x1D400 - 0x41) if 'A' <= c <= 'Z' else chr(ord(c) + 0x1D41A - 0x61) if 'a' <= c <= 'z' else c for c in x)),
83
+ ("Italic", lambda x: "".join(chr(ord(c) + 0x1D434 - 0x41) if 'A' <= c <= 'Z' else chr(ord(c) + 0x1D44E - 0x61) if 'a' <= c <= 'z' else c for c in x)),
84
+ ("Bold Italic", lambda x: "".join(chr(ord(c) + 0x1D468 - 0x41) if 'A' <= c <= 'Z' else chr(ord(c) + 0x1D482 - 0x61) if 'a' <= c <= 'z' else c for c in x)),
85
+ ("Script", lambda x: "".join(chr(ord(c) + 0x1D49C - 0x41) if 'A' <= c <= 'Z' else chr(ord(c) + 0x1D4B6 - 0x61) if 'a' <= c <= 'z' else c for c in x)),
86
+ ("Bold Script", lambda x: "".join(chr(ord(c) + 0x1D4D0 - 0x41) if 'A' <= c <= 'Z' else chr(ord(c) + 0x1D4EA - 0x61) if 'a' <= c <= 'z' else c for c in x)),
87
+ ("Fraktur", lambda x: "".join(chr(ord(c) + 0x1D504 - 0x41) if 'A' <= c <= 'Z' else chr(ord(c) + 0x1D51E - 0x61) if 'a' <= c <= 'z' else c for c in x)),
88
+ ("Bold Fraktur", lambda x: "".join(chr(ord(c) + 0x1D56C - 0x41) if 'A' <= c <= 'Z' else chr(ord(c) + 0x1D586 - 0x61) if 'a' <= c <= 'z' else c for c in x)),
89
+ ("Double Struck", lambda x: "".join(chr(ord(c) + 0x1D538 - 0x41) if 'A' <= c <= 'Z' else chr(ord(c) + 0x1D552 - 0x61) if 'a' <= c <= 'z' else c for c in x)),
90
+ ("Sans Serif", lambda x: "".join(chr(ord(c) + 0x1D5A0 - 0x41) if 'A' <= c <= 'Z' else chr(ord(c) + 0x1D5BA - 0x61) if 'a' <= c <= 'z' else c for c in x)),
91
+ ("Sans Serif Bold", lambda x: "".join(chr(ord(c) + 0x1D5D4 - 0x41) if 'A' <= c <= 'Z' else chr(ord(c) + 0x1D5EE - 0x61) if 'a' <= c <= 'z' else c for c in x)),
92
+ ("Sans Serif Italic", lambda x: "".join(chr(ord(c) + 0x1D608 - 0x41) if 'A' <= c <= 'Z' else chr(ord(c) + 0x1D622 - 0x61) if 'a' <= c <= 'z' else c for c in x)),
93
+ ("Sans Serif Bold Italic", lambda x: "".join(chr(ord(c) + 0x1D63C - 0x41) if 'A' <= c <= 'Z' else chr(ord(c) + 0x1D656 - 0x61) if 'a' <= c <= 'z' else c for c in x)),
94
+ ("Monospace", lambda x: "".join(chr(ord(c) + 0x1D670 - 0x41) if 'A' <= c <= 'Z' else chr(ord(c) + 0x1D68A - 0x61) if 'a' <= c <= 'z' else c for c in x)),
95
+ ("Circled", lambda x: "".join(chr(ord(c) - 0x41 + 0x24B6) if 'A' <= c <= 'Z' else chr(ord(c) - 0x61 + 0x24D0) if 'a' <= c <= 'z' else c for c in x)),
96
+ ("Squared", lambda x: "".join(chr(ord(c) - 0x41 + 0x1F130) if 'A' <= c <= 'Z' else c for c in x)),
97
+ ("Negative Circled", lambda x: "".join(chr(ord(c) - 0x41 + 0x1F150) if 'A' <= c <= 'Z' else c for c in x)),
98
+ ("Negative Squared", lambda x: "".join(chr(ord(c) - 0x41 + 0x1F170) if 'A' <= c <= 'Z' else c for c in x)),
99
+ ("Regional Indicator", lambda x: "".join(chr(ord(c) - 0x41 + 0x1F1E6) if 'A' <= c <= 'Z' else c for c in x)),
100
  ]
101
 
102
  server_running = False
103
  server_task = None
104
 
105
+ # Timestamp wizardry - clock ticks with flair! ⏰🎩
106
  def format_timestamp_prefix():
 
107
  return datetime.now().strftime("%Y%m%d_%H%M%S")
108
 
109
+ # Node naming - christening the beast! 🌐🍼
110
  def get_node_name():
 
 
 
 
111
  parser = argparse.ArgumentParser(description='Start a chat node with a specific name')
112
  parser.add_argument('--node-name', type=str, default=None)
113
  parser.add_argument('--port', type=int, default=8501)
114
  args = parser.parse_args()
115
+ username = st.session_state.get('username', 'System 🌟')
116
+ log_action(username, "🌐🍼 - Node naming - christening the beast!")
117
  return args.node_name or f"node-{uuid.uuid4().hex[:8]}", args.port
118
 
119
+ # Action logger - spying on deeds! 🕵️📜
120
  def log_action(username, action):
 
121
  if 'action_log' not in st.session_state:
122
  st.session_state.action_log = {}
123
  user_log = st.session_state.action_log.setdefault(username, {})
 
129
  f.write(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] {username}: {action}\n")
130
  user_log[action] = current_time
131
 
132
+ # Chat saver - words locked tight! 💬🔒
133
  async def save_chat_entry(username, message):
134
+ await asyncio.to_thread(log_action, username, "💬🔒 - Chat saver - words locked tight!")
 
 
135
  timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
136
  entry = f"[{timestamp}] {username}: {message}"
137
  await asyncio.to_thread(lambda: open(CHAT_FILE, 'a').write(f"{entry}\n"))
 
138
  voice = FUN_USERNAMES.get(username, "en-US-AriaNeural")
139
  audio_file = await async_edge_tts_generate(message, voice)
140
  if audio_file:
141
  with open(HISTORY_FILE, 'a') as f:
142
  f.write(f"[{timestamp}] {username}: Audio generated - {audio_file}\n")
143
 
144
+ # Chat loader - history unleashed! 📜🚀
145
  async def load_chat():
 
 
146
  username = st.session_state.get('username', 'System 🌟')
147
+ await asyncio.to_thread(log_action, username, "📜🚀 - Chat loader - history unleashed!")
148
  if not os.path.exists(CHAT_FILE):
149
  await asyncio.to_thread(lambda: open(CHAT_FILE, 'w').write(f"# {START_ROOM} Chat\n\nWelcome to the cosmic hub - start chatting! 🎤\n"))
150
  with open(CHAT_FILE, 'r') as f:
151
  content = await asyncio.to_thread(f.read)
152
  return content
153
 
154
+ # User lister - who’s in the gang! 👥🎉
155
  async def get_user_list(chat_content):
 
 
156
  username = st.session_state.get('username', 'System 🌟')
157
+ await asyncio.to_thread(log_action, username, "👥🎉 - User lister - who’s in the gang!")
158
  users = set()
159
  for line in chat_content.split('\n'):
160
  if line.strip() and ': ' in line:
 
162
  users.add(user)
163
  return sorted(list(users))
164
 
165
+ # Join checker - been here before? 🚪🔍
166
  async def has_joined_before(client_id, chat_content):
 
 
167
  username = st.session_state.get('username', 'System 🌟')
168
+ await asyncio.to_thread(log_action, username, "🚪🔍 - Join checker - been here before?")
169
  return any(f"Client-{client_id} has joined" in line for line in chat_content.split('\n'))
170
 
171
+ # Suggestion maker - old quips resurface! 💡📝
172
  async def get_message_suggestions(chat_content, prefix):
 
 
173
  username = st.session_state.get('username', 'System 🌟')
174
+ await asyncio.to_thread(log_action, username, "💡📝 - Suggestion maker - old quips resurface!")
175
  lines = chat_content.split('\n')
176
  messages = [line.split(': ', 1)[1] for line in lines if ': ' in line and line.strip()]
177
  return [msg for msg in messages if msg.lower().startswith(prefix.lower())][:5]
178
 
179
+ # Vote saver - cheers recorded! 👍📊
180
  async def save_vote(file, item, user_hash, username, comment=""):
181
+ await asyncio.to_thread(log_action, username, "👍📊 - Vote saver - cheers recorded!")
 
 
182
  timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
183
  entry = f"[{timestamp}] {user_hash} voted for {item}"
184
  await asyncio.to_thread(lambda: open(file, 'a').write(f"{entry}\n"))
 
188
  chat_message += f" - {comment}"
189
  await save_chat_entry(username, chat_message)
190
 
191
+ # Vote counter - tallying the love! 🏆📈
192
  async def load_votes(file):
 
 
193
  username = st.session_state.get('username', 'System 🌟')
194
+ await asyncio.to_thread(log_action, username, "🏆📈 - Vote counter - tallying the love!")
195
  if not os.path.exists(file):
196
  await asyncio.to_thread(lambda: open(file, 'w').write("# Vote Tally\n\nNo votes yet - get clicking! 🖱️\n"))
197
  with open(file, 'r') as f:
 
208
  user_votes.add(vote_key)
209
  return votes
210
 
211
+ # Hash generator - secret codes ahoy! 🔑🕵️
212
  async def generate_user_hash():
 
 
213
  username = st.session_state.get('username', 'System 🌟')
214
+ await asyncio.to_thread(log_action, username, "🔑🕵️ - Hash generator - secret codes ahoy!")
215
  if 'user_hash' not in st.session_state:
216
  st.session_state.user_hash = hashlib.md5(str(random.getrandbits(128)).encode()).hexdigest()[:8]
217
  return st.session_state.user_hash
218
 
219
+ # Audio maker - voices come alive! 🎶🌟
220
  async def async_edge_tts_generate(text, voice, rate=0, pitch=0, file_format="mp3"):
 
 
221
  username = st.session_state.get('username', 'System 🌟')
222
+ await asyncio.to_thread(log_action, username, "🎶🌟 - Audio maker - voices come alive!")
223
  timestamp = format_timestamp_prefix()
224
  filename = os.path.join(AUDIO_DIR, f"audio_{timestamp}_{random.randint(1000, 9999)}.mp3")
225
  communicate = edge_tts.Communicate(text, voice, rate=f"{rate:+d}%", pitch=f"{pitch:+d}Hz")
226
  await communicate.save(filename)
227
  return filename if os.path.exists(filename) else None
228
 
229
+ # Audio player - tunes blast off! 🔊🚀
230
  def play_and_download_audio(file_path):
 
231
  if file_path and os.path.exists(file_path):
232
  st.audio(file_path)
233
  with open(file_path, "rb") as f:
 
235
  dl_link = f'<a href="data:audio/mpeg;base64,{b64}" download="{os.path.basename(file_path)}">🎵 Download {os.path.basename(file_path)}</a>'
236
  st.markdown(dl_link, unsafe_allow_html=True)
237
 
238
+ # Image saver - pics preserved! 📸💾
239
  async def save_pasted_image(image_data):
 
 
240
  username = st.session_state.get('username', 'System 🌟')
241
+ await asyncio.to_thread(log_action, username, "📸💾 - Image saver - pics preserved!")
242
  timestamp = format_timestamp_prefix()
243
  filename = f"paste_{timestamp}.png"
244
  filepath = os.path.join('./', filename)
 
249
  await asyncio.to_thread(img.save, filepath, "PNG")
250
  return filename
251
 
252
+ # Video renderer - movies roll! 🎥🎬
253
  async def get_video_html(video_path, width="100%"):
 
 
254
  username = st.session_state.get('username', 'System 🌟')
255
+ await asyncio.to_thread(log_action, username, "🎥🎬 - Video renderer - movies roll!")
256
  video_url = f"data:video/mp4;base64,{base64.b64encode(await asyncio.to_thread(open, video_path, 'rb').read()).decode()}"
257
  return f'<video width="{width}" controls autoplay muted loop><source src="{video_url}" type="video/mp4">Your browser does not support the video tag.</video>'
258
 
259
+ # Audio renderer - sounds soar! 🎶✈️
260
  async def get_audio_html(audio_path, width="100%"):
 
 
261
  username = st.session_state.get('username', 'System 🌟')
262
+ await asyncio.to_thread(log_action, username, "🎶✈️ - Audio renderer - sounds soar!")
263
  audio_url = f"data:audio/mpeg;base64,{base64.b64encode(await asyncio.to_thread(open, audio_path, 'rb').read()).decode()}"
264
  return f'<audio controls style="width: {width};"><source src="{audio_url}" type="audio/mpeg">Your browser does not support the audio element.</audio>'
265
 
266
  active_connections = {}
267
 
268
+ # Websocket handler - chat links up! 🌐🔗
269
  async def websocket_handler(websocket, path):
 
 
270
  username = st.session_state.get('username', 'System 🌟')
271
+ await asyncio.to_thread(log_action, username, "🌐🔗 - Websocket handler - chat links up!")
272
  try:
273
  client_id = str(uuid.uuid4())
274
  room_id = "chat"
 
289
  if room_id in active_connections and client_id in active_connections[room_id]:
290
  del active_connections[room_id][client_id]
291
 
292
+ # Message broadcaster - words fly far! 📢✈️
293
  async def broadcast_message(message, room_id):
 
 
294
  username = st.session_state.get('username', 'System 🌟')
295
+ await asyncio.to_thread(log_action, username, "📢✈️ - Message broadcaster - words fly far!")
296
  if room_id in active_connections:
297
  disconnected = []
298
  for client_id, ws in active_connections[room_id].items():
 
303
  for client_id in disconnected:
304
  del active_connections[room_id][client_id]
305
 
306
+ # Server starter - web spins up! 🖥️🌀
307
  async def run_websocket_server():
 
 
308
  username = st.session_state.get('username', 'System 🌟')
309
+ await asyncio.to_thread(log_action, username, "🖥️🌀 - Server starter - web spins up!")
310
  global server_running, server_task
311
  if not server_running:
312
  server = await websockets.serve(websocket_handler, '0.0.0.0', 8765)
313
  server_running = True
314
  await server.wait_closed()
315
 
316
+ # Voice processor - speech to text! 🎤📝
317
  async def process_voice_input(audio_bytes):
 
 
318
  username = st.session_state.get('username', 'System 🌟')
319
+ await asyncio.to_thread(log_action, username, "🎤📝 - Voice processor - speech to text!")
320
  if audio_bytes:
 
 
321
  text = "Voice input simulation" # Replace with actual speech-to-text logic
322
  await save_chat_entry(username, text)
323
 
324
+ # Interface builder - UI takes shape! 🎨🖌️
325
  async def create_streamlit_interface():
 
 
326
  username = st.session_state.get('username', 'System 🌟')
327
+ await asyncio.to_thread(log_action, username, "🎨🖌️ - Interface builder - UI takes shape!")
328
 
329
  if 'username' not in st.session_state:
330
  chat_content = await load_chat()
 
407
  quote_response = st.text_area("Add your response", key="quote_response")
408
  if st.button("Send Quote 🚀", key="send_quote"):
409
  async def process_quote():
410
+ await asyncio.to_thread(log_action, st.session_state.username, "📢💬 - Quote processor - echoes resound!")
 
 
411
  markdown_response = f"### Quote Response\n- **Original**: {st.session_state.quote_line}\n- **{st.session_state.username} Replies**: {quote_response}"
412
  if st.session_state.pasted_image_data:
413
  filename = await save_pasted_image(st.session_state.pasted_image_data)
 
420
  st.session_state.message_text = ''
421
  st.rerun()
422
 
423
+ # Username changer
424
  new_username = st.selectbox("Change Name", [""] + list(FUN_USERNAMES.keys()), index=0)
425
  if new_username and new_username != st.session_state.username:
426
  await save_chat_entry("System 🌟", f"{st.session_state.username} changed name to {new_username}")
 
525
  history_content = f.read()
526
  st.sidebar.markdown(history_content)
527
 
528
+ # Main execution
529
+ NODE_NAME, port = get_node_name()
530
+ server_task = None
531
+
532
+ # Start the websocket server
533
+ if server_task is None:
534
+ server_task = asyncio.create_task(run_websocket_server())
535
+
536
+ # Run the interface
537
+ asyncio.run(create_streamlit_interface())