awacke1 commited on
Commit
60430b4
Β·
verified Β·
1 Parent(s): 26b513b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +52 -56
app.py CHANGED
@@ -224,13 +224,15 @@ class AudioProcessor:
224
  return cache_path
225
 
226
  # Chat saver - words locked tight! πŸ’¬πŸ”’
227
- async def save_chat_entry(username, message, is_markdown=False, quote_line=None):
228
  await asyncio.to_thread(log_action, username, "πŸ’¬πŸ”’ - Chat saver - words locked tight!")
229
  central = pytz.timezone('US/Central')
230
  timestamp = datetime.now(central).strftime("%Y-%m-%d %H:%M:%S")
231
  user_history_file = f"{username}_history.md"
232
  voice = st.session_state.voice if username == st.session_state.username else FUN_USERNAMES.get(username, "en-US-AriaNeural")
233
  indent = " " if quote_line else "" # Nesting for replies
 
 
234
  if is_markdown:
235
  entry = f"{indent}[{timestamp}] {username}:\n{indent}```markdown\n{indent}{message}\n{indent}```"
236
  else:
@@ -239,7 +241,8 @@ async def save_chat_entry(username, message, is_markdown=False, quote_line=None)
239
  entry = f"{indent}> {quote_line}\n{entry}"
240
 
241
  # Save to global chat file
242
- await asyncio.to_thread(lambda: open(CHAT_FILE, 'a').write(f"{entry}\n"))
 
243
 
244
  # Save to user-specific history file
245
  if not os.path.exists(user_history_file):
@@ -248,11 +251,14 @@ async def save_chat_entry(username, message, is_markdown=False, quote_line=None)
248
  with open(user_history_file, 'a') as f:
249
  f.write(f"{entry}\n")
250
 
 
251
  cleaned_message = clean_text_for_tts(message)
252
  audio_processor = AudioProcessor()
253
  audio_filename = f"{format_timestamp_prefix(username)}-{hashlib.md5(cleaned_message.encode()).hexdigest()[:8]}.mp3"
254
  log_action(username, f"Attempting TTS with text: '{cleaned_message}' and voice: '{voice}'")
255
  audio_file = await audio_processor.create_audio(cleaned_message, voice, audio_filename)
 
 
256
  if audio_file:
257
  with open(HISTORY_FILE, 'a') as f:
258
  f.write(f"[{timestamp}] {username} ({voice}): Audio generated - {audio_filename}\n")
@@ -260,16 +266,11 @@ async def save_chat_entry(username, message, is_markdown=False, quote_line=None)
260
  f.write(f"{indent}[{timestamp}] Audio: {audio_filename}\n")
261
  with open(CHAT_FILE, 'a') as f:
262
  f.write(f"{indent}[{timestamp}] Audio: {audio_filename}\n")
263
-
264
- # Embed audio and image in global chat if applicable
265
- if message.startswith("Pasted image:") or message.startswith("Uploaded media:") or message.startswith("Uploaded PDF:"):
266
- with open(CHAT_FILE, 'a') as f:
267
- f.write(f"{indent}[{timestamp}] Audio: {audio_filename}\n")
268
- file_path = message.split(": ")[1]
269
- if os.path.exists(file_path) and file_path.endswith(('.png', '.jpg', '.mp4', '.pdf')):
270
- f.write(f"{indent}[{timestamp}] Media: ![Media]({file_path})\n")
271
- else:
272
- log_action(username, f"Failed to generate audio for message: '{message}'")
273
 
274
  await broadcast_message(f"{username}|{message}", "chat")
275
  st.session_state.last_chat_update = time.time()
@@ -384,16 +385,18 @@ async def async_edge_tts_generate(text, voice, rate=0, pitch=0, file_format="mp3
384
  return None
385
 
386
  # Audio player - tunes blast off! πŸ”ŠπŸš€
387
- def play_and_download_audio(file_path):
388
  if file_path and os.path.exists(file_path):
389
- st.audio(file_path)
390
- if file_path not in st.session_state.base64_cache:
391
- with open(file_path, "rb") as f:
392
- b64 = base64.b64encode(f.read()).decode()
393
- st.session_state.base64_cache[file_path] = b64
394
- b64 = st.session_state.base64_cache[file_path]
395
- dl_link = f'<a href="data:audio/mpeg;base64,{b64}" download="{os.path.basename(file_path)}">🎡 Download {os.path.basename(file_path)}</a>'
396
- st.markdown(dl_link, unsafe_allow_html=True)
 
 
397
 
398
  # Image saver - pics preserved with naming! πŸ“ΈπŸ’Ύ
399
  async def save_pasted_image(image, username):
@@ -560,7 +563,7 @@ def main():
560
  st.session_state.displayed_chat_lines = f.read().split('\n')
561
 
562
  user_url = f"/q={st.session_state.username}"
563
- st.write(f"Your unique URL path: [{user_url}]({user_url})")
564
 
565
  st.title(f"πŸ€–πŸ§ MMO {st.session_state.username}πŸ“πŸ”¬")
566
  st.markdown(f"Welcome to {START_ROOM} - chat, vote, upload, paste images, and enjoy quoting! πŸŽ‰ User ID: {st.session_state.user_id}")
@@ -572,38 +575,31 @@ def main():
572
  st.subheader(f"{START_ROOM} Chat History πŸ’¬")
573
  chat_content = await load_chat()
574
  chat_lines = [line for line in chat_content.split('\n') if line.strip() and not line.startswith('#')]
 
575
  if chat_lines:
576
  col1, col2 = st.columns([2, 1])
577
  with col1:
578
  st.write("### Text & Audio Chat")
579
- for i, line in enumerate(reversed(chat_lines)): # Descending order
580
- col_text, col_audio = st.columns([3, 1])
581
- with col_text:
582
- if "```markdown" in line:
583
- markdown_content = re.search(r'```markdown\n(.*?)(?=\n\s*\[|$)', line, re.DOTALL)
584
- if markdown_content:
585
- st.markdown(markdown_content.group(1))
586
- else:
587
- st.markdown(line)
588
- else:
589
- st.markdown(line)
590
- if "Media:" in line:
591
- file_path = line.split("Media: ")[-1].strip('![]()')
592
- if os.path.exists(file_path):
593
- if file_path.endswith(('.png', '.jpg')):
594
- st.image(file_path, use_container_width=True)
595
- elif file_path.endswith('.mp4'):
596
- st.markdown(get_video_html(file_path), unsafe_allow_html=True)
597
- elif file_path.endswith('.pdf'):
598
- st.write(f"PDF: {os.path.basename(file_path)}")
599
- with col_audio:
600
- if "Audio:" in line:
601
- audio_ref = line.split("Audio: ")[-1].strip()
602
- if os.path.exists(audio_ref):
603
- play_and_download_audio(audio_ref)
604
- username = line.split(': ')[1].split(' ')[0] if ': ' in line else "Unknown"
605
- cache_key = f"{line}_{FUN_USERNAMES.get(username, 'en-US-AriaNeural')}"
606
- st.session_state.audio_cache[cache_key] = audio_ref
607
 
608
  if st.session_state.quote_line:
609
  st.markdown(f"### Quoting: {st.session_state.quote_line}")
@@ -623,7 +619,7 @@ def main():
623
  markdown_response = f"### Quote Response\n- **Original**: {st.session_state.quote_line}\n- **{st.session_state.username} Replies**: {quote_response}"
624
  if st.session_state.pasted_image_data:
625
  markdown_response += f"\n- **Image**: ![Pasted Image]({st.session_state.pasted_image_data})"
626
- await save_chat_entry(st.session_state.username, f"Pasted image: {st.session_state.pasted_image_data}", quote_line=st.session_state.quote_line)
627
  st.session_state.pasted_image_data = None
628
  await save_chat_entry(st.session_state.username, markdown_response, is_markdown=True, quote_line=st.session_state.quote_line)
629
  st.session_state.quote_line = None
@@ -651,7 +647,7 @@ def main():
651
  st.session_state.audio_cache[f"{message}_{FUN_USERNAMES[st.session_state.username]}"] = audio_file
652
  st.audio(audio_file) # Immediate preview
653
  if st.session_state.pasted_image_data:
654
- await save_chat_entry(st.session_state.username, f"Pasted image: {st.session_state.pasted_image_data}")
655
  st.session_state.pasted_image_data = None
656
  st.session_state.message_text = ''
657
  st.rerun()
@@ -665,7 +661,7 @@ def main():
665
  st.image(paste_result_msg.image_data, caption="Received Image for Message")
666
  filename = await save_pasted_image(paste_result_msg.image_data, st.session_state.username)
667
  if filename:
668
- await save_chat_entry(st.session_state.username, f"Pasted image: {filename}")
669
  st.session_state.pasted_image_data = None
670
 
671
  tab_main = st.radio("Action:", ["πŸ“Έ Media", "πŸ” ArXiv", "πŸ“ Editor"], horizontal=True)
@@ -686,13 +682,13 @@ def main():
686
  st.success(f"Uploaded {filename}")
687
  if ext == 'pdf':
688
  pdf_filename, texts, audio_files = await save_pdf_and_generate_audio(uploaded_file, username)
689
- await save_chat_entry(username, f"Uploaded PDF: {pdf_filename}")
690
  for i, (text, audio_file) in enumerate(zip(texts, audio_files)):
691
  if audio_file:
692
  with open(CHAT_FILE, 'a') as f:
693
  f.write(f" [{timestamp}] Page {i+1} Audio: {audio_file}\n")
694
  else:
695
- await save_chat_entry(username, f"Uploaded media: {file_path}")
696
  await save_chat_history_with_image(username, file_path)
697
  st.session_state.image_hashes.add(file_hash)
698
  if file_path.endswith('.mp4'):
@@ -719,7 +715,7 @@ def main():
719
  time.sleep(1)
720
  st.rerun()
721
 
722
- # Gallery with Adjustable Tiles - Consistent Three-Set from Provided Code
723
  st.subheader("Image Gallery πŸ–Ό")
724
  image_files = glob.glob("*.png") + glob.glob("*.jpg") + glob.glob("*.jpeg")
725
  image_cols = st.slider("Image Gallery Columns πŸ–Ό", min_value=1, max_value=15, value=5)
 
224
  return cache_path
225
 
226
  # Chat saver - words locked tight! πŸ’¬πŸ”’
227
+ async def save_chat_entry(username, message, is_markdown=False, quote_line=None, media_file=None):
228
  await asyncio.to_thread(log_action, username, "πŸ’¬πŸ”’ - Chat saver - words locked tight!")
229
  central = pytz.timezone('US/Central')
230
  timestamp = datetime.now(central).strftime("%Y-%m-%d %H:%M:%S")
231
  user_history_file = f"{username}_history.md"
232
  voice = st.session_state.voice if username == st.session_state.username else FUN_USERNAMES.get(username, "en-US-AriaNeural")
233
  indent = " " if quote_line else "" # Nesting for replies
234
+
235
+ # Prepare entry
236
  if is_markdown:
237
  entry = f"{indent}[{timestamp}] {username}:\n{indent}```markdown\n{indent}{message}\n{indent}```"
238
  else:
 
241
  entry = f"{indent}> {quote_line}\n{entry}"
242
 
243
  # Save to global chat file
244
+ with open(CHAT_FILE, 'a') as f:
245
+ f.write(f"{entry}\n")
246
 
247
  # Save to user-specific history file
248
  if not os.path.exists(user_history_file):
 
251
  with open(user_history_file, 'a') as f:
252
  f.write(f"{entry}\n")
253
 
254
+ # Generate audio
255
  cleaned_message = clean_text_for_tts(message)
256
  audio_processor = AudioProcessor()
257
  audio_filename = f"{format_timestamp_prefix(username)}-{hashlib.md5(cleaned_message.encode()).hexdigest()[:8]}.mp3"
258
  log_action(username, f"Attempting TTS with text: '{cleaned_message}' and voice: '{voice}'")
259
  audio_file = await audio_processor.create_audio(cleaned_message, voice, audio_filename)
260
+
261
+ # Log audio and media
262
  if audio_file:
263
  with open(HISTORY_FILE, 'a') as f:
264
  f.write(f"[{timestamp}] {username} ({voice}): Audio generated - {audio_filename}\n")
 
266
  f.write(f"{indent}[{timestamp}] Audio: {audio_filename}\n")
267
  with open(CHAT_FILE, 'a') as f:
268
  f.write(f"{indent}[{timestamp}] Audio: {audio_filename}\n")
269
+ if media_file:
270
+ with open(CHAT_FILE, 'a') as f:
271
+ f.write(f"{indent}[{timestamp}] Media: ![Media]({media_file})\n")
272
+ with open(user_history_file, 'a') as f:
273
+ f.write(f"{indent}[{timestamp}] Media: ![Media]({media_file})\n")
 
 
 
 
 
274
 
275
  await broadcast_message(f"{username}|{message}", "chat")
276
  st.session_state.last_chat_update = time.time()
 
385
  return None
386
 
387
  # Audio player - tunes blast off! πŸ”ŠπŸš€
388
+ def play_and_download_audio(file_path, timestamp):
389
  if file_path and os.path.exists(file_path):
390
+ with open(file_path, "rb") as f:
391
+ audio_data = f.read()
392
+ b64 = base64.b64encode(audio_data).decode()
393
+ audio_html = f'''
394
+ <audio controls style="display:inline; vertical-align:middle;">
395
+ <source src="data:audio/mpeg;base64,{b64}" type="audio/mpeg">
396
+ </audio>
397
+ <a href="data:audio/mpeg;base64,{b64}" download="{os.path.basename(file_path)}" style="vertical-align:middle;">🎡 Download</a>
398
+ '''
399
+ st.markdown(f"{timestamp} {audio_html}", unsafe_allow_html=True)
400
 
401
  # Image saver - pics preserved with naming! πŸ“ΈπŸ’Ύ
402
  async def save_pasted_image(image, username):
 
563
  st.session_state.displayed_chat_lines = f.read().split('\n')
564
 
565
  user_url = f"/q={st.session_state.username}"
566
+ st.markdown(f"Your unique URL path: [{user_url}]({user_url})", unsafe_allow_html=True)
567
 
568
  st.title(f"πŸ€–πŸ§ MMO {st.session_state.username}πŸ“πŸ”¬")
569
  st.markdown(f"Welcome to {START_ROOM} - chat, vote, upload, paste images, and enjoy quoting! πŸŽ‰ User ID: {st.session_state.user_id}")
 
575
  st.subheader(f"{START_ROOM} Chat History πŸ’¬")
576
  chat_content = await load_chat()
577
  chat_lines = [line for line in chat_content.split('\n') if line.strip() and not line.startswith('#')]
578
+ current_entry = None
579
  if chat_lines:
580
  col1, col2 = st.columns([2, 1])
581
  with col1:
582
  st.write("### Text & Audio Chat")
583
+ for line in reversed(chat_lines):
584
+ if not line.startswith(' '): # Main message line
585
+ current_entry = line
586
+ st.markdown(line)
587
+ elif "Audio:" in line and current_entry:
588
+ audio_ref = line.split("Audio: ")[-1].strip()
589
+ if os.path.exists(audio_ref):
590
+ timestamp = current_entry.split('] ')[0] + ']'
591
+ play_and_download_audio(audio_ref, timestamp)
592
+ elif "Media:" in line and current_entry:
593
+ file_path = line.split("Media: ")[-1].strip('![]()')
594
+ if os.path.exists(file_path):
595
+ timestamp = current_entry.split('] ')[0] + ']'
596
+ st.markdown(f"{timestamp}")
597
+ if file_path.endswith(('.png', '.jpg')):
598
+ st.image(file_path, use_container_width=True)
599
+ elif file_path.endswith('.mp4'):
600
+ st.markdown(get_video_html(file_path), unsafe_allow_html=True)
601
+ elif file_path.endswith('.pdf'):
602
+ st.write(f"PDF: {os.path.basename(file_path)}")
 
 
 
 
 
 
 
 
603
 
604
  if st.session_state.quote_line:
605
  st.markdown(f"### Quoting: {st.session_state.quote_line}")
 
619
  markdown_response = f"### Quote Response\n- **Original**: {st.session_state.quote_line}\n- **{st.session_state.username} Replies**: {quote_response}"
620
  if st.session_state.pasted_image_data:
621
  markdown_response += f"\n- **Image**: ![Pasted Image]({st.session_state.pasted_image_data})"
622
+ await save_chat_entry(st.session_state.username, f"Pasted image: {st.session_state.pasted_image_data}", quote_line=st.session_state.quote_line, media_file=st.session_state.pasted_image_data)
623
  st.session_state.pasted_image_data = None
624
  await save_chat_entry(st.session_state.username, markdown_response, is_markdown=True, quote_line=st.session_state.quote_line)
625
  st.session_state.quote_line = None
 
647
  st.session_state.audio_cache[f"{message}_{FUN_USERNAMES[st.session_state.username]}"] = audio_file
648
  st.audio(audio_file) # Immediate preview
649
  if st.session_state.pasted_image_data:
650
+ await save_chat_entry(st.session_state.username, f"Pasted image: {st.session_state.pasted_image_data}", media_file=st.session_state.pasted_image_data)
651
  st.session_state.pasted_image_data = None
652
  st.session_state.message_text = ''
653
  st.rerun()
 
661
  st.image(paste_result_msg.image_data, caption="Received Image for Message")
662
  filename = await save_pasted_image(paste_result_msg.image_data, st.session_state.username)
663
  if filename:
664
+ await save_chat_entry(st.session_state.username, f"Pasted image: {filename}", media_file=filename)
665
  st.session_state.pasted_image_data = None
666
 
667
  tab_main = st.radio("Action:", ["πŸ“Έ Media", "πŸ” ArXiv", "πŸ“ Editor"], horizontal=True)
 
682
  st.success(f"Uploaded {filename}")
683
  if ext == 'pdf':
684
  pdf_filename, texts, audio_files = await save_pdf_and_generate_audio(uploaded_file, username)
685
+ await save_chat_entry(username, f"Uploaded PDF: {pdf_filename}", media_file=pdf_filename)
686
  for i, (text, audio_file) in enumerate(zip(texts, audio_files)):
687
  if audio_file:
688
  with open(CHAT_FILE, 'a') as f:
689
  f.write(f" [{timestamp}] Page {i+1} Audio: {audio_file}\n")
690
  else:
691
+ await save_chat_entry(username, f"Uploaded media: {file_path}", media_file=file_path)
692
  await save_chat_history_with_image(username, file_path)
693
  st.session_state.image_hashes.add(file_hash)
694
  if file_path.endswith('.mp4'):
 
715
  time.sleep(1)
716
  st.rerun()
717
 
718
+ # Consistent Three-Gallery Set
719
  st.subheader("Image Gallery πŸ–Ό")
720
  image_files = glob.glob("*.png") + glob.glob("*.jpg") + glob.glob("*.jpeg")
721
  image_cols = st.slider("Image Gallery Columns πŸ–Ό", min_value=1, max_value=15, value=5)