awacke1 commited on
Commit
ae88433
Β·
verified Β·
1 Parent(s): 9d1d48c

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +80 -114
app.py CHANGED
@@ -134,7 +134,7 @@ if 'user_hash' not in st.session_state:
134
  def format_timestamp_prefix(username):
135
  central = pytz.timezone('US/Central')
136
  now = datetime.now(central)
137
- return f"{now.strftime('%I-%M-%p-ct-%m-%d-%Y')}-by-{username}-{st.session_state.user_id}"
138
 
139
  # Compute image hash from binary data
140
  def compute_image_hash(image_data):
@@ -225,7 +225,7 @@ class AudioProcessor:
225
  return cache_path
226
 
227
  # Chat saver - words locked tight! πŸ’¬πŸ”’
228
- async def save_chat_entry(username, message, is_markdown=False, quote_line=None, media_file=None):
229
  await asyncio.to_thread(log_action, username, "πŸ’¬πŸ”’ - Chat saver - words locked tight!")
230
  central = pytz.timezone('US/Central')
231
  timestamp = datetime.now(central).strftime("%Y-%m-%d %H:%M:%S")
@@ -252,34 +252,36 @@ async def save_chat_entry(username, message, is_markdown=False, quote_line=None,
252
  with open(user_history_file, 'a') as f:
253
  f.write(f"{entry}\n")
254
 
255
- # Generate audio
256
- cleaned_message = clean_text_for_tts(message)
257
- audio_processor = AudioProcessor()
258
- audio_filename = f"{format_timestamp_prefix(username)}-{hashlib.md5(cleaned_message.encode()).hexdigest()[:8]}.mp3"
259
- log_action(username, f"Attempting TTS with text: '{cleaned_message}' and voice: '{voice}'")
260
- audio_file = await audio_processor.create_audio(cleaned_message, voice, audio_filename)
261
-
262
- # Log audio and media
263
- if audio_file:
264
- with open(HISTORY_FILE, 'a') as f:
265
- f.write(f"[{timestamp}] {username} ({voice}): Audio generated - {audio_filename}\n")
266
- with open(user_history_file, 'a') as f:
267
- f.write(f"{indent}[{timestamp}] Audio: {audio_filename}\n")
268
- with open(CHAT_FILE, 'a') as f:
269
- f.write(f"{indent}[{timestamp}] Audio: {audio_filename}\n")
 
270
  if media_file:
271
  if isinstance(media_file, Image.Image):
272
- img_hash = compute_image_hash(media_file)
273
  timestamp_prefix = format_timestamp_prefix(username)
274
- media_filename = f"{timestamp_prefix}-{img_hash}.b64"
275
- media_path = os.path.join(MEDIA_DIR, media_filename)
276
- os.makedirs(MEDIA_DIR, exist_ok=True)
277
  img_byte_arr = io.BytesIO()
278
  media_file.save(img_byte_arr, format='PNG')
279
- img_bytes = img_byte_arr.getvalue()
280
- b64_data = base64.b64encode(img_bytes).decode()
281
- with open(media_path, 'w') as f:
282
- f.write(b64_data)
 
 
 
283
  media_file = media_filename
284
  with open(CHAT_FILE, 'a') as f:
285
  f.write(f"{indent}[{timestamp}] Media: ![Media]({media_file})\n")
@@ -413,49 +415,32 @@ def play_and_download_audio(file_path):
413
  return audio_html
414
  return ""
415
 
416
- # Image saver - pics preserved with naming as base64! πŸ“ΈπŸ’Ύ
417
  async def save_pasted_image(image, username):
418
  await asyncio.to_thread(log_action, username, "πŸ“ΈπŸ’Ύ - Image saver - pics preserved!")
419
- img_hash = compute_image_hash(image)
420
- if img_hash in st.session_state.image_hashes:
421
- return None
422
  timestamp = format_timestamp_prefix(username)
423
- voice = st.session_state.voice if username == st.session_state.username else FUN_USERNAMES.get(username, "en-US-AriaNeural")
424
- filename = f"{timestamp}-{img_hash}-voice-{voice}.b64"
425
- filepath = os.path.join(MEDIA_DIR, filename)
426
- os.makedirs(MEDIA_DIR, exist_ok=True)
427
  img_byte_arr = io.BytesIO()
428
  image.save(img_byte_arr, format='PNG')
429
- b64_data = base64.b64encode(img_byte_arr.getvalue()).decode()
430
- with open(filepath, 'w') as f:
431
- f.write(b64_data)
432
- st.session_state.image_hashes.add(img_hash)
433
- await save_chat_history_with_image(username, filepath)
434
- return filename
435
-
436
- # Display base64 image and audio
437
- def display_base64_media(media_file, width="100px"):
438
- if os.path.exists(os.path.join(MEDIA_DIR, media_file)) and media_file.endswith('.b64'):
439
- with open(os.path.join(MEDIA_DIR, media_file), 'r') as f:
440
- b64_data = f.read()
441
- img_data = base64.b64decode(b64_data)
442
- img = Image.open(io.BytesIO(img_data))
443
- st.image(img, use_container_width=True)
444
-
445
- # Find corresponding audio file
446
- timestamp = media_file.split('-by-')[0] + '-by-' + media_file.split('-by-')[1].split('-')[0]
447
- voice = media_file.split('-voice-')[1].split('.b64')[0]
448
- audio_files = glob.glob(f"{timestamp}*-{voice}.mp3")
449
- if audio_files:
450
- audio_file = audio_files[0]
451
- st.audio(audio_file)
452
 
453
  # PDF saver and audio generator
454
  async def save_pdf_and_generate_audio(pdf_file, username, max_pages=10):
455
  await asyncio.to_thread(log_action, username, "πŸ“œπŸŽΆ - PDF saver and audio generator!")
456
  timestamp = format_timestamp_prefix(username)
457
  file_hash = hashlib.md5(pdf_file.getbuffer()).hexdigest()[:8]
458
- pdf_filename = f"{timestamp}-{file_hash}.pdf"
459
  with open(pdf_filename, 'wb') as f:
460
  f.write(pdf_file.getbuffer())
461
 
@@ -470,7 +455,7 @@ async def save_pdf_and_generate_audio(pdf_file, username, max_pages=10):
470
  for i in range(total_pages):
471
  text = reader.pages[i].extract_text()
472
  texts.append(text)
473
- audio_filename = f"{timestamp}-page{i+1}-{file_hash}-voice-{voice}.mp3"
474
  audio_data = await audio_processor.create_audio(text, voice, audio_filename)
475
  if audio_data:
476
  audio_files.append(audio_filename)
@@ -683,12 +668,12 @@ def main():
683
  audio_html = play_and_download_audio(audio_file)
684
  elif "Media:" in nl:
685
  media_file = nl.split("Media: ")[-1].strip('![]()')
686
- if media_file.endswith('.b64'):
687
- media_content = display_base64_media(media_file, width="100px")
688
- elif media_file.endswith(('.png', '.jpg')):
689
  media_content = f"<img src='file://{media_file}' width='100'>"
690
  elif media_file.endswith('.mp4'):
691
  media_content = get_video_html(media_file)
 
 
692
  elif media_file.endswith('.pdf'):
693
  media_content = f"πŸ“œ {os.path.basename(media_file)}"
694
  minute_output += f"- πŸ’¬ **{user}**: {msg} {audio_html} {media_content}\n"
@@ -746,14 +731,10 @@ def main():
746
  message = st.text_input(f"Message as {st.session_state.username} (Voice: {st.session_state.voice})", key="message_input", value=st.session_state.message_text)
747
  with col_send:
748
  if st.button("Send πŸš€", key="send_button"):
749
- if message.strip():
750
- audio_file = await save_chat_entry(st.session_state.username, message, is_markdown=True)
751
- if audio_file:
752
- st.session_state.audio_cache[f"{message}_{FUN_USERNAMES[st.session_state.username]}"] = audio_file
753
- st.audio(audio_file) # Immediate preview
754
- if st.session_state.pasted_image_data:
755
- 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)
756
- st.session_state.pasted_image_data = None
757
  st.session_state.message_text = ''
758
  st.rerun()
759
 
@@ -766,43 +747,34 @@ def main():
766
  st.image(paste_result_msg.image_data, caption="Received Image for Quote")
767
  filename = await save_pasted_image(paste_result_msg.image_data, st.session_state.username)
768
  if filename:
769
- await save_chat_entry(st.session_state.username, f"Pasted image: {filename}", media_file=paste_result_msg.image_data)
 
770
  st.session_state.pasted_image_data = None
 
771
 
772
  with st.container():
773
- tab_main = st.radio("Action:", ["πŸ“Έ Media", "πŸ” ArXiv", "πŸ“ Editor"], horizontal=True, label_visibility="collapsed")
774
- useArxiv = st.checkbox("Search Arxiv for Research Paper Answers", value=True, label_visibility="collapsed")
775
- useArxivAudio = st.checkbox("Generate Audio File for Research Paper Answers", value=False, label_visibility="collapsed")
776
-
777
  st.markdown("###### Upload Media πŸŽ¨πŸŽΆπŸ“œπŸŽ₯")
778
  uploaded_file = st.file_uploader("Upload Media", type=['png', 'jpg', 'mp4', 'mp3', 'wav', 'pdf', 'txt', 'md', 'py'])
779
  if uploaded_file:
780
  timestamp = format_timestamp_prefix(st.session_state.username)
781
  username = st.session_state.username
782
- ext = uploaded_file.name.split('.')[-1]
783
- file_hash = hashlib.md5(uploaded_file.getbuffer()).hexdigest()[:8]
784
- if file_hash not in st.session_state.image_hashes:
785
- filename = f"{timestamp}-{file_hash}.{ext}"
786
- file_path = filename # Top-level file
787
- await asyncio.to_thread(lambda: open(file_path, 'wb').write(uploaded_file.getbuffer()))
788
- st.success(f"Uploaded {filename}")
789
- if ext == 'pdf':
790
- pdf_filename, texts, audio_files = await save_pdf_and_generate_audio(uploaded_file, username)
791
- await save_chat_entry(username, f"Uploaded PDF: {pdf_filename}", media_file=pdf_filename)
792
- for i, (text, audio_file) in enumerate(zip(texts, audio_files)):
793
- if audio_file:
794
- with open(CHAT_FILE, 'a') as f:
795
- f.write(f" [{timestamp}] Page {i+1} Audio: {audio_file}\n")
796
- else:
797
- await save_chat_entry(username, f"Uploaded media: {file_path}", media_file=file_path)
798
- await save_chat_history_with_image(username, file_path)
799
- st.session_state.image_hashes.add(file_hash)
800
- if file_path.endswith('.mp4'):
801
- st.session_state.media_notifications.append(file_path)
802
 
803
  # Big Red Delete Button
804
  st.markdown("###### πŸ›‘ Danger Zone")
805
- if st.button("Try Not To Delete It All On Your First Day", key="delete_all", help="Deletes all user-added files!", type="primary", use_container_width=True, label_visibility="collapsed"):
806
  deleted_files = delete_user_files()
807
  if deleted_files:
808
  st.markdown("### πŸ—‘οΈ Deleted Files:\n" + "\n".join([f"- `{file}`" for file in deleted_files]))
@@ -811,7 +783,7 @@ def main():
811
  st.rerun()
812
 
813
  st.markdown("###### Refresh ⏳")
814
- refresh_rate = st.slider("Refresh Rate", 1, 300, st.session_state.refresh_rate, label_visibility="collapsed")
815
  st.session_state.refresh_rate = refresh_rate
816
  timer_placeholder = st.empty()
817
  for i in range(st.session_state.refresh_rate, -1, -1):
@@ -824,24 +796,21 @@ def main():
824
  # Separate Galleries for Own and Shared Files
825
  with st.container():
826
  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") + glob.glob(os.path.join(MEDIA_DIR, "*.b64"))
827
- own_files = [f for f in all_files if st.session_state.user_id in os.path.basename(f)]
828
  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, os.path.join(MEDIA_DIR, "*")]]
829
 
830
  st.markdown("###### Your Files πŸ“‚")
831
  st.markdown("###### Image Gallery πŸ–Ό")
832
- own_image_files = [f for f in own_files if f.endswith(('.png', '.jpg', '.b64'))]
833
- image_cols = st.slider("Image Gallery Columns πŸ–Ό (Own)", min_value=1, max_value=15, value=5, label_visibility="collapsed")
834
  cols = st.columns(image_cols)
835
  for idx, image_file in enumerate(own_image_files):
836
  with cols[idx % image_cols]:
837
- if image_file.endswith('.b64'):
838
- display_base64_media(os.path.basename(image_file))
839
- else:
840
- st.image(image_file, use_container_width=True)
841
 
842
  st.markdown("###### Video Gallery πŸŽ₯")
843
  own_video_files = [f for f in own_files if f.endswith('.mp4')]
844
- video_cols = st.slider("Video Gallery Columns 🎬 (Own)", min_value=1, max_value=5, value=3, label_visibility="collapsed")
845
  cols = st.columns(video_cols)
846
  for idx, video_file in enumerate(own_video_files):
847
  with cols[idx % video_cols]:
@@ -849,7 +818,7 @@ def main():
849
 
850
  st.markdown("###### Audio Gallery 🎧")
851
  own_audio_files = [f for f in own_files if f.endswith(('.mp3', '.wav'))]
852
- audio_cols = st.slider("Audio Gallery Columns 🎢 (Own)", min_value=1, max_value=15, value=5, label_visibility="collapsed")
853
  cols = st.columns(audio_cols)
854
  for idx, audio_file in enumerate(own_audio_files):
855
  with cols[idx % audio_cols]:
@@ -857,19 +826,16 @@ def main():
857
 
858
  st.markdown("###### Shared Files πŸ“€")
859
  st.markdown("###### Image Gallery πŸ–Ό")
860
- shared_image_files = [f for f in shared_files if f.endswith(('.png', '.jpg', '.b64'))]
861
- image_cols = st.slider("Image Gallery Columns πŸ–Ό (Shared)", min_value=1, max_value=15, value=5, label_visibility="collapsed")
862
  cols = st.columns(image_cols)
863
  for idx, image_file in enumerate(shared_image_files):
864
  with cols[idx % image_cols]:
865
- if image_file.endswith('.b64'):
866
- display_base64_media(os.path.basename(image_file))
867
- else:
868
- st.image(image_file, use_container_width=True)
869
 
870
  st.markdown("###### Video Gallery πŸŽ₯")
871
  shared_video_files = [f for f in shared_files if f.endswith('.mp4')]
872
- video_cols = st.slider("Video Gallery Columns 🎬 (Shared)", min_value=1, max_value=5, value=3, label_visibility="collapsed")
873
  cols = st.columns(video_cols)
874
  for idx, video_file in enumerate(shared_video_files):
875
  with cols[idx % video_cols]:
@@ -877,7 +843,7 @@ def main():
877
 
878
  st.markdown("###### Audio Gallery 🎧")
879
  shared_audio_files = [f for f in shared_files if f.endswith(('.mp3', '.wav'))]
880
- audio_cols = st.slider("Audio Gallery Columns 🎢 (Shared)", min_value=1, max_value=15, value=5, label_visibility="collapsed")
881
  cols = st.columns(audio_cols)
882
  for idx, audio_file in enumerate(shared_audio_files):
883
  with cols[idx % audio_cols]:
@@ -889,7 +855,7 @@ def main():
889
  with open(CHAT_FILE, 'r') as f:
890
  history_content = f.read()
891
  st.markdown(history_content)
892
- st.download_button("Download Chat Log as .md", history_content, file_name=f"chat_{st.session_state.user_id}.md", mime="text/markdown", label_visibility="collapsed")
893
 
894
  loop.run_until_complete(async_interface())
895
 
 
134
  def format_timestamp_prefix(username):
135
  central = pytz.timezone('US/Central')
136
  now = datetime.now(central)
137
+ return f"{username}-{now.strftime('%I-%M-%p-%m-%d-%Y')}"
138
 
139
  # Compute image hash from binary data
140
  def compute_image_hash(image_data):
 
225
  return cache_path
226
 
227
  # Chat saver - words locked tight! πŸ’¬πŸ”’
228
+ async def save_chat_entry(username, message, is_markdown=False, quote_line=None, media_file=None, skip_audio=False):
229
  await asyncio.to_thread(log_action, username, "πŸ’¬πŸ”’ - Chat saver - words locked tight!")
230
  central = pytz.timezone('US/Central')
231
  timestamp = datetime.now(central).strftime("%Y-%m-%d %H:%M:%S")
 
252
  with open(user_history_file, 'a') as f:
253
  f.write(f"{entry}\n")
254
 
255
+ # Generate audio (unless skipped)
256
+ if not skip_audio and message.strip():
257
+ cleaned_message = clean_text_for_tts(message)
258
+ audio_processor = AudioProcessor()
259
+ audio_filename = f"{format_timestamp_prefix(username)}-{hashlib.md5(cleaned_message.encode()).hexdigest()[:8]}.mp3"
260
+ log_action(username, f"Attempting TTS with text: '{cleaned_message}' and voice: '{voice}'")
261
+ audio_file = await audio_processor.create_audio(cleaned_message, voice, audio_filename)
262
+
263
+ # Log audio
264
+ if audio_file:
265
+ with open(HISTORY_FILE, 'a') as f:
266
+ f.write(f"[{timestamp}] {username} ({voice}): Audio generated - {audio_filename}\n")
267
+ with open(user_history_file, 'a') as f:
268
+ f.write(f"{indent}[{timestamp}] Audio: {audio_filename}\n")
269
+ with open(CHAT_FILE, 'a') as f:
270
+ f.write(f"{indent}[{timestamp}] Audio: {audio_filename}\n")
271
  if media_file:
272
  if isinstance(media_file, Image.Image):
 
273
  timestamp_prefix = format_timestamp_prefix(username)
274
+ media_filename = f"{username}-{timestamp_prefix.split('-')[-1]}.png"
275
+ media_path = media_filename # Save at root
 
276
  img_byte_arr = io.BytesIO()
277
  media_file.save(img_byte_arr, format='PNG')
278
+ await asyncio.to_thread(lambda: open(media_path, 'wb').write(img_byte_arr.getvalue()))
279
+ media_file = media_filename
280
+ elif media_file.name in ['png', 'jpg', 'mp4', 'mp3']:
281
+ timestamp_prefix = format_timestamp_prefix(username)
282
+ media_filename = f"{username}-{timestamp_prefix.split('-')[-1]}.{media_file.name.split('.')[-1]}"
283
+ media_path = media_filename # Save at root
284
+ await asyncio.to_thread(lambda: open(media_path, 'wb').write(media_file.getbuffer()))
285
  media_file = media_filename
286
  with open(CHAT_FILE, 'a') as f:
287
  f.write(f"{indent}[{timestamp}] Media: ![Media]({media_file})\n")
 
415
  return audio_html
416
  return ""
417
 
418
+ # Image saver - pics preserved with naming! πŸ“ΈπŸ’Ύ
419
  async def save_pasted_image(image, username):
420
  await asyncio.to_thread(log_action, username, "πŸ“ΈπŸ’Ύ - Image saver - pics preserved!")
 
 
 
421
  timestamp = format_timestamp_prefix(username)
422
+ media_filename = f"{username}-{timestamp.split('-')[-1]}.png"
423
+ media_path = media_filename # Save at root
 
 
424
  img_byte_arr = io.BytesIO()
425
  image.save(img_byte_arr, format='PNG')
426
+ await asyncio.to_thread(lambda: open(media_path, 'wb').write(img_byte_arr.getvalue()))
427
+ return media_filename
428
+
429
+ # Video and Audio savers
430
+ async def save_media(file, username, ext):
431
+ await asyncio.to_thread(log_action, username, f"πŸ“ΈπŸ’Ύ - Media saver - {ext} preserved!")
432
+ timestamp = format_timestamp_prefix(username)
433
+ media_filename = f"{username}-{timestamp.split('-')[-1]}.{ext}"
434
+ media_path = media_filename # Save at root
435
+ await asyncio.to_thread(lambda: open(media_path, 'wb').write(file.getbuffer()))
436
+ return media_filename
 
 
 
 
 
 
 
 
 
 
 
 
437
 
438
  # PDF saver and audio generator
439
  async def save_pdf_and_generate_audio(pdf_file, username, max_pages=10):
440
  await asyncio.to_thread(log_action, username, "πŸ“œπŸŽΆ - PDF saver and audio generator!")
441
  timestamp = format_timestamp_prefix(username)
442
  file_hash = hashlib.md5(pdf_file.getbuffer()).hexdigest()[:8]
443
+ pdf_filename = f"{username}-{timestamp.split('-')[-1]}-{file_hash}.pdf"
444
  with open(pdf_filename, 'wb') as f:
445
  f.write(pdf_file.getbuffer())
446
 
 
455
  for i in range(total_pages):
456
  text = reader.pages[i].extract_text()
457
  texts.append(text)
458
+ audio_filename = f"{username}-{timestamp.split('-')[-1]}-page{i+1}-{file_hash}-voice-{voice}.mp3"
459
  audio_data = await audio_processor.create_audio(text, voice, audio_filename)
460
  if audio_data:
461
  audio_files.append(audio_filename)
 
668
  audio_html = play_and_download_audio(audio_file)
669
  elif "Media:" in nl:
670
  media_file = nl.split("Media: ")[-1].strip('![]()')
671
+ if media_file.endswith(('.png', '.jpg')):
 
 
672
  media_content = f"<img src='file://{media_file}' width='100'>"
673
  elif media_file.endswith('.mp4'):
674
  media_content = get_video_html(media_file)
675
+ elif media_file.endswith('.mp3'):
676
+ media_content = await get_audio_html(media_file)
677
  elif media_file.endswith('.pdf'):
678
  media_content = f"πŸ“œ {os.path.basename(media_file)}"
679
  minute_output += f"- πŸ’¬ **{user}**: {msg} {audio_html} {media_content}\n"
 
731
  message = st.text_input(f"Message as {st.session_state.username} (Voice: {st.session_state.voice})", key="message_input", value=st.session_state.message_text)
732
  with col_send:
733
  if st.button("Send πŸš€", key="send_button"):
734
+ if message.strip() or st.session_state.pasted_image_data:
735
+ await save_chat_entry(st.session_state.username, message if message.strip() else "Image shared", is_markdown=True, media_file=st.session_state.pasted_image_data if st.session_state.pasted_image_data else None, skip_audio=not message.strip())
736
+ if st.session_state.pasted_image_data:
737
+ st.session_state.pasted_image_data = None
 
 
 
 
738
  st.session_state.message_text = ''
739
  st.rerun()
740
 
 
747
  st.image(paste_result_msg.image_data, caption="Received Image for Quote")
748
  filename = await save_pasted_image(paste_result_msg.image_data, st.session_state.username)
749
  if filename:
750
+ st.session_state.pasted_image_data = filename
751
+ await save_chat_entry(st.session_state.username, "Image shared", is_markdown=True, media_file=paste_result_msg.image_data, skip_audio=True)
752
  st.session_state.pasted_image_data = None
753
+ st.rerun()
754
 
755
  with st.container():
 
 
 
 
756
  st.markdown("###### Upload Media πŸŽ¨πŸŽΆπŸ“œπŸŽ₯")
757
  uploaded_file = st.file_uploader("Upload Media", type=['png', 'jpg', 'mp4', 'mp3', 'wav', 'pdf', 'txt', 'md', 'py'])
758
  if uploaded_file:
759
  timestamp = format_timestamp_prefix(st.session_state.username)
760
  username = st.session_state.username
761
+ ext = uploaded_file.name.split('.')[-1].lower()
762
+ if ext in ['png', 'jpg']:
763
+ filename = await save_pasted_image(uploaded_file, username)
764
+ elif ext in ['mp4', 'mp3', 'wav']:
765
+ filename = await save_media(uploaded_file, username, ext)
766
+ elif ext == 'pdf':
767
+ pdf_filename, _, _ = await save_pdf_and_generate_audio(uploaded_file, username)
768
+ filename = pdf_filename
769
+ else:
770
+ filename = f"{username}-{timestamp.split('-')[-1]}.{ext}"
771
+ await asyncio.to_thread(lambda: open(filename, 'wb').write(uploaded_file.getbuffer()))
772
+ await save_chat_entry(username, f"Uploaded {ext.upper()}: {os.path.basename(filename)}", media_file=uploaded_file, skip_audio=True)
773
+ st.success(f"Uploaded {filename}")
 
 
 
 
 
 
 
774
 
775
  # Big Red Delete Button
776
  st.markdown("###### πŸ›‘ Danger Zone")
777
+ if st.button("Try Not To Delete It All On Your First Day", key="delete_all", help="Deletes all user-added files!", type="primary", use_container_width=True):
778
  deleted_files = delete_user_files()
779
  if deleted_files:
780
  st.markdown("### πŸ—‘οΈ Deleted Files:\n" + "\n".join([f"- `{file}`" for file in deleted_files]))
 
783
  st.rerun()
784
 
785
  st.markdown("###### Refresh ⏳")
786
+ refresh_rate = st.slider("Refresh Rate", 1, 300, st.session_state.refresh_rate)
787
  st.session_state.refresh_rate = refresh_rate
788
  timer_placeholder = st.empty()
789
  for i in range(st.session_state.refresh_rate, -1, -1):
 
796
  # Separate Galleries for Own and Shared Files
797
  with st.container():
798
  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") + glob.glob(os.path.join(MEDIA_DIR, "*.b64"))
799
+ own_files = [f for f in all_files if st.session_state.user_id in os.path.basename(f) or st.session_state.username in os.path.basename(f)]
800
  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, os.path.join(MEDIA_DIR, "*")]]
801
 
802
  st.markdown("###### Your Files πŸ“‚")
803
  st.markdown("###### Image Gallery πŸ–Ό")
804
+ own_image_files = [f for f in own_files if f.endswith(('.png', '.jpg'))]
805
+ image_cols = st.slider("Image Gallery Columns πŸ–Ό (Own)", min_value=1, max_value=15, value=5)
806
  cols = st.columns(image_cols)
807
  for idx, image_file in enumerate(own_image_files):
808
  with cols[idx % image_cols]:
809
+ st.image(image_file, use_container_width=True)
 
 
 
810
 
811
  st.markdown("###### Video Gallery πŸŽ₯")
812
  own_video_files = [f for f in own_files if f.endswith('.mp4')]
813
+ video_cols = st.slider("Video Gallery Columns 🎬 (Own)", min_value=1, max_value=5, value=3)
814
  cols = st.columns(video_cols)
815
  for idx, video_file in enumerate(own_video_files):
816
  with cols[idx % video_cols]:
 
818
 
819
  st.markdown("###### Audio Gallery 🎧")
820
  own_audio_files = [f for f in own_files if f.endswith(('.mp3', '.wav'))]
821
+ audio_cols = st.slider("Audio Gallery Columns 🎢 (Own)", min_value=1, max_value=15, value=5)
822
  cols = st.columns(audio_cols)
823
  for idx, audio_file in enumerate(own_audio_files):
824
  with cols[idx % audio_cols]:
 
826
 
827
  st.markdown("###### Shared Files πŸ“€")
828
  st.markdown("###### Image Gallery πŸ–Ό")
829
+ shared_image_files = [f for f in shared_files if f.endswith(('.png', '.jpg'))]
830
+ image_cols = st.slider("Image Gallery Columns πŸ–Ό (Shared)", min_value=1, max_value=15, value=5)
831
  cols = st.columns(image_cols)
832
  for idx, image_file in enumerate(shared_image_files):
833
  with cols[idx % image_cols]:
834
+ st.image(image_file, use_container_width=True)
 
 
 
835
 
836
  st.markdown("###### Video Gallery πŸŽ₯")
837
  shared_video_files = [f for f in shared_files if f.endswith('.mp4')]
838
+ video_cols = st.slider("Video Gallery Columns 🎬 (Shared)", min_value=1, max_value=5, value=3)
839
  cols = st.columns(video_cols)
840
  for idx, video_file in enumerate(shared_video_files):
841
  with cols[idx % video_cols]:
 
843
 
844
  st.markdown("###### Audio Gallery 🎧")
845
  shared_audio_files = [f for f in shared_files if f.endswith(('.mp3', '.wav'))]
846
+ audio_cols = st.slider("Audio Gallery Columns 🎢 (Shared)", min_value=1, max_value=15, value=5)
847
  cols = st.columns(audio_cols)
848
  for idx, audio_file in enumerate(shared_audio_files):
849
  with cols[idx % audio_cols]:
 
855
  with open(CHAT_FILE, 'r') as f:
856
  history_content = f.read()
857
  st.markdown(history_content)
858
+ st.download_button("Download Chat Log as .md", history_content, file_name=f"chat_{st.session_state.user_id}.md", mime="text/markdown")
859
 
860
  loop.run_until_complete(async_interface())
861