awacke1 commited on
Commit
0a38743
Β·
verified Β·
1 Parent(s): 60430b4

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +119 -43
app.py CHANGED
@@ -133,7 +133,7 @@ if 'user_hash' not in st.session_state:
133
  def format_timestamp_prefix(username):
134
  central = pytz.timezone('US/Central')
135
  now = datetime.now(central)
136
- return f"{now.strftime('%I-%M-%p-ct-%m-%d-%Y')}-by-{username}"
137
 
138
  # Compute image hash from binary data
139
  def compute_image_hash(image_data):
@@ -385,7 +385,7 @@ async def async_edge_tts_generate(text, voice, rate=0, pitch=0, file_format="mp3
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()
@@ -394,9 +394,10 @@ def play_and_download_audio(file_path, timestamp):
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):
@@ -535,6 +536,40 @@ def check_query_params():
535
  st.session_state.user_id = q_value # Use as user_id if not a valid username
536
  return q_value
537
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
538
  # Main execution - let’s roll! πŸŽ²πŸš€
539
  def main():
540
  NODE_NAME, port = get_node_name()
@@ -571,35 +606,45 @@ def main():
571
  if not st.session_state.server_task:
572
  st.session_state.server_task = loop.create_task(run_websocket_server())
573
 
574
- # Unified Chat History at Top
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}")
@@ -614,7 +659,7 @@ def main():
614
  filename = await save_pasted_image(paste_result_quote.image_data, st.session_state.username)
615
  if filename:
616
  st.session_state.pasted_image_data = filename
617
- await save_chat_entry(st.session_state.username, f"Pasted image: {filename}", quote_line=st.session_state.quote_line)
618
  if st.button("Send Quote πŸš€", key="send_quote"):
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:
@@ -669,7 +714,7 @@ def main():
669
  useArxivAudio = st.checkbox("Generate Audio File for Research Paper Answers", value=False)
670
 
671
  st.subheader("Upload Media πŸŽ¨πŸŽΆπŸ“œπŸŽ₯")
672
- uploaded_file = st.file_uploader("Upload Media", type=['png', 'jpg', 'mp4', 'mp3', 'wav', 'pdf'])
673
  if uploaded_file:
674
  timestamp = format_timestamp_prefix(st.session_state.username)
675
  username = st.session_state.username
@@ -715,36 +760,67 @@ def main():
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)
722
  cols = st.columns(image_cols)
723
- for idx, image_file in enumerate(image_files):
724
  with cols[idx % image_cols]:
725
  st.image(image_file, use_container_width=True)
726
 
727
  st.subheader("Video Gallery πŸŽ₯")
728
- video_files = glob.glob("*.mp4")
729
- video_cols = st.slider("Video Gallery Columns 🎬", min_value=1, max_value=5, value=3)
730
  cols = st.columns(video_cols)
731
- for idx, video_file in enumerate(video_files):
732
  with cols[idx % video_cols]:
733
  st.markdown(get_video_html(video_file, width="100%"), unsafe_allow_html=True)
734
 
735
  st.subheader("Audio Gallery 🎧")
736
- audio_files = glob.glob("*.mp3") + glob.glob("*.wav")
737
- audio_cols = st.slider("Audio Gallery Columns 🎢", min_value=1, max_value=15, value=5)
738
  cols = st.columns(audio_cols)
739
- for idx, audio_file in enumerate(audio_files):
740
  with cols[idx % audio_cols]:
741
  st.markdown(await get_audio_html(audio_file, width="100%"), unsafe_allow_html=True)
742
 
743
- # Full Log at End
744
  st.subheader("Full Chat Log πŸ“œ")
745
- with open(HISTORY_FILE, 'r') as f:
746
  history_content = f.read()
747
  st.markdown(history_content)
 
748
 
749
  loop.run_until_complete(async_interface())
750
 
 
133
  def format_timestamp_prefix(username):
134
  central = pytz.timezone('US/Central')
135
  now = datetime.now(central)
136
+ return f"{now.strftime('%I-%M-%p-ct-%m-%d-%Y')}-by-{username}-{st.session_state.user_id}"
137
 
138
  # Compute image hash from binary data
139
  def compute_image_hash(image_data):
 
385
  return None
386
 
387
  # Audio player - tunes blast off! πŸ”ŠπŸš€
388
+ def play_and_download_audio(file_path):
389
  if file_path and os.path.exists(file_path):
390
  with open(file_path, "rb") as f:
391
  audio_data = f.read()
 
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;">🎡</a>
398
  '''
399
+ return audio_html
400
+ return ""
401
 
402
  # Image saver - pics preserved with naming! πŸ“ΈπŸ’Ύ
403
  async def save_pasted_image(image, username):
 
536
  st.session_state.user_id = q_value # Use as user_id if not a valid username
537
  return q_value
538
 
539
+ # Mermaid graph generator
540
+ def generate_mermaid_graph(chat_lines):
541
+ mermaid_code = "graph TD\n"
542
+ nodes = {}
543
+ edges = []
544
+ for i, line in enumerate(chat_lines):
545
+ if line.strip():
546
+ timestamp = line.split('] ')[0][1:] if '] ' in line else "Unknown"
547
+ minute_key = timestamp[:16] # Up to minute
548
+ content = line.split(': ', 1)[1] if ': ' in line else line
549
+ user = content.split(' ')[0] if ' ' in content else "System"
550
+ node_id = f"{user}_{i}"
551
+ nodes[node_id] = f"{user} @ {timestamp}"
552
+
553
+ if "Audio:" in line:
554
+ audio_file = line.split("Audio: ")[-1].strip()
555
+ nodes[f"audio_{i}"] = f"🎡 {os.path.basename(audio_file)}"
556
+ edges.append(f"{node_id} --> audio_{i}")
557
+ elif "Media:" in line:
558
+ media_file = line.split("Media: ")[-1].strip('![]()')
559
+ media_type = "πŸ–Ό" if media_file.endswith(('.png', '.jpg')) else "πŸŽ₯" if media_file.endswith('.mp4') else "πŸ“œ"
560
+ nodes[f"media_{i}"] = f"{media_type} {os.path.basename(media_file)}"
561
+ edges.append(f"{node_id} --> media_{i}")
562
+ elif "> " in line: # Quote
563
+ parent_line = chat_lines[i-1] if i > 0 else None
564
+ if parent_line:
565
+ parent_id = f"{parent_line.split(': ')[1].split(' ')[0]}_{i-1}"
566
+ edges.append(f"{parent_id} --> {node_id}")
567
+
568
+ for node_id, label in nodes.items():
569
+ mermaid_code += f" {node_id}[\"{label}\"]\n"
570
+ mermaid_code += "\n".join(f" {edge}" for edge in edges)
571
+ return f"```mermaid\n{mermaid_code}\n```"
572
+
573
  # Main execution - let’s roll! πŸŽ²πŸš€
574
  def main():
575
  NODE_NAME, port = get_node_name()
 
606
  if not st.session_state.server_task:
607
  st.session_state.server_task = loop.create_task(run_websocket_server())
608
 
609
+ # Unified Chat History at Top with Markdown Emoji Output
610
  st.subheader(f"{START_ROOM} Chat History πŸ’¬")
611
  chat_content = await load_chat()
612
  chat_lines = [line for line in chat_content.split('\n') if line.strip() and not line.startswith('#')]
 
613
  if chat_lines:
614
+ chat_by_minute = {}
615
+ for line in reversed(chat_lines):
616
+ timestamp = line.split('] ')[0][1:] if '] ' in line else "Unknown"
617
+ minute_key = timestamp[:16] # Up to minute
618
+ if minute_key not in chat_by_minute:
619
+ chat_by_minute[minute_key] = []
620
+ chat_by_minute[minute_key].append(line)
621
+
622
+ markdown_output = ""
623
+ for minute, lines in chat_by_minute.items():
624
+ minute_output = f"### {minute}\n"
625
+ for line in lines:
626
+ if ': ' in line and not line.startswith(' '):
627
+ user_message = line.split(': ', 1)[1]
628
+ minute_output += f"- πŸ’¬ **{user_message.split(' ')[0]}**: {user_message.split(' ', 1)[1] if ' ' in user_message else ''}\n"
629
+ elif "Audio:" in line:
630
+ audio_file = line.split("Audio: ")[-1].strip()
631
+ audio_html = play_and_download_audio(audio_file)
632
+ minute_output += f" - 🎡 {audio_html}\n"
633
+ elif "Media:" in line:
634
+ media_file = line.split("Media: ")[-1].strip('![]()')
635
+ if media_file.endswith(('.png', '.jpg')):
636
+ minute_output += f" - πŸ–Ό <img src='file://{media_file}' width='100'>\n"
637
+ elif media_file.endswith('.mp4'):
638
+ minute_output += f" - πŸŽ₯ <video src='file://{media_file}' width='100' controls autoplay muted loop></video>\n"
639
+ elif media_file.endswith('.pdf'):
640
+ minute_output += f" - πŸ“œ {os.path.basename(media_file)}\n"
641
+ markdown_output += minute_output
642
+ st.markdown(markdown_output, unsafe_allow_html=True)
643
+
644
+ # Mermaid Graph Visualization
645
+ st.subheader("Chat Relationship Tree 🌳")
646
+ mermaid_graph = generate_mermaid_graph(chat_lines)
647
+ st.markdown(mermaid_graph)
648
 
649
  if st.session_state.quote_line:
650
  st.markdown(f"### Quoting: {st.session_state.quote_line}")
 
659
  filename = await save_pasted_image(paste_result_quote.image_data, st.session_state.username)
660
  if filename:
661
  st.session_state.pasted_image_data = filename
662
+ await save_chat_entry(st.session_state.username, f"Pasted image: {filename}", quote_line=st.session_state.quote_line, media_file=filename)
663
  if st.button("Send Quote πŸš€", key="send_quote"):
664
  markdown_response = f"### Quote Response\n- **Original**: {st.session_state.quote_line}\n- **{st.session_state.username} Replies**: {quote_response}"
665
  if st.session_state.pasted_image_data:
 
714
  useArxivAudio = st.checkbox("Generate Audio File for Research Paper Answers", value=False)
715
 
716
  st.subheader("Upload Media πŸŽ¨πŸŽΆπŸ“œπŸŽ₯")
717
+ uploaded_file = st.file_uploader("Upload Media", type=['png', 'jpg', 'mp4', 'mp3', 'wav', 'pdf', 'txt', 'md', 'py'])
718
  if uploaded_file:
719
  timestamp = format_timestamp_prefix(st.session_state.username)
720
  username = st.session_state.username
 
760
  time.sleep(1)
761
  st.rerun()
762
 
763
+ # Separate Galleries for Own and Shared Files
764
+ all_files = glob.glob("*.md") + glob.glob("*.pdf") + glob.glob("*.txt") + glob.glob("*.py") + glob.glob("*.png") + glob.glob("*.jpg") + glob.glob("*.mp3") + glob.glob("*.mp4")
765
+ own_files = [f for f in all_files if st.session_state.user_id in f]
766
+ shared_files = [f for f in all_files if f not in own_files and not f in [CHAT_FILE, QUOTE_VOTES_FILE, MEDIA_VOTES_FILE, HISTORY_FILE, STATE_FILE]]
767
+
768
+ st.subheader("Your Files πŸ“‚")
769
+ st.subheader("Image Gallery πŸ–Ό")
770
+ own_image_files = [f for f in own_files if f.endswith(('.png', '.jpg'))]
771
+ image_cols = st.slider("Image Gallery Columns πŸ–Ό (Own)", min_value=1, max_value=15, value=5)
772
+ cols = st.columns(image_cols)
773
+ for idx, image_file in enumerate(own_image_files):
774
+ with cols[idx % image_cols]:
775
+ st.image(image_file, use_container_width=True)
776
+
777
+ st.subheader("Video Gallery πŸŽ₯")
778
+ own_video_files = [f for f in own_files if f.endswith('.mp4')]
779
+ video_cols = st.slider("Video Gallery Columns 🎬 (Own)", min_value=1, max_value=5, value=3)
780
+ cols = st.columns(video_cols)
781
+ for idx, video_file in enumerate(own_video_files):
782
+ with cols[idx % video_cols]:
783
+ st.markdown(get_video_html(video_file, width="100%"), unsafe_allow_html=True)
784
+
785
+ st.subheader("Audio Gallery 🎧")
786
+ own_audio_files = [f for f in own_files if f.endswith(('.mp3', '.wav'))]
787
+ audio_cols = st.slider("Audio Gallery Columns 🎢 (Own)", min_value=1, max_value=15, value=5)
788
+ cols = st.columns(audio_cols)
789
+ for idx, audio_file in enumerate(own_audio_files):
790
+ with cols[idx % audio_cols]:
791
+ st.markdown(await get_audio_html(audio_file, width="100%"), unsafe_allow_html=True)
792
+
793
+ st.subheader("Shared Files πŸ“€")
794
  st.subheader("Image Gallery πŸ–Ό")
795
+ shared_image_files = [f for f in shared_files if f.endswith(('.png', '.jpg'))]
796
+ image_cols = st.slider("Image Gallery Columns πŸ–Ό (Shared)", min_value=1, max_value=15, value=5)
797
  cols = st.columns(image_cols)
798
+ for idx, image_file in enumerate(shared_image_files):
799
  with cols[idx % image_cols]:
800
  st.image(image_file, use_container_width=True)
801
 
802
  st.subheader("Video Gallery πŸŽ₯")
803
+ shared_video_files = [f for f in shared_files if f.endswith('.mp4')]
804
+ video_cols = st.slider("Video Gallery Columns 🎬 (Shared)", min_value=1, max_value=5, value=3)
805
  cols = st.columns(video_cols)
806
+ for idx, video_file in enumerate(shared_video_files):
807
  with cols[idx % video_cols]:
808
  st.markdown(get_video_html(video_file, width="100%"), unsafe_allow_html=True)
809
 
810
  st.subheader("Audio Gallery 🎧")
811
+ shared_audio_files = [f for f in shared_files if f.endswith(('.mp3', '.wav'))]
812
+ audio_cols = st.slider("Audio Gallery Columns 🎢 (Shared)", min_value=1, max_value=15, value=5)
813
  cols = st.columns(audio_cols)
814
+ for idx, audio_file in enumerate(shared_audio_files):
815
  with cols[idx % audio_cols]:
816
  st.markdown(await get_audio_html(audio_file, width="100%"), unsafe_allow_html=True)
817
 
818
+ # Full Log at End with Download
819
  st.subheader("Full Chat Log πŸ“œ")
820
+ with open(CHAT_FILE, 'r') as f:
821
  history_content = f.read()
822
  st.markdown(history_content)
823
+ st.download_button("Download Chat Log as .md", history_content, file_name=f"chat_{st.session_state.user_id}.md", mime="text/markdown")
824
 
825
  loop.run_until_complete(async_interface())
826