Update app.py
Browse files
app.py
CHANGED
@@ -16,7 +16,6 @@ import edge_tts
|
|
16 |
from audio_recorder_streamlit import audio_recorder
|
17 |
import nest_asyncio
|
18 |
import re
|
19 |
-
from streamlit_paste_button import paste_image_button
|
20 |
import pytz
|
21 |
import shutil
|
22 |
import anthropic
|
@@ -128,7 +127,7 @@ def init_session_state():
|
|
128 |
'autosend': True, 'autosearch': True, 'last_message': "", 'last_query': "",
|
129 |
'mp3_files': {}, 'timer_start': time.time(), 'quote_index': 0,
|
130 |
'quote_source': "famous", 'last_sent_transcript': "", 'old_val': None,
|
131 |
-
'last_refresh': time.time(), 'paper_metadata': {}, '
|
132 |
}
|
133 |
for k, v in defaults.items():
|
134 |
if k not in st.session_state:
|
@@ -564,6 +563,53 @@ def create_zip_of_files(md_files, mp3_files, png_files, mp4_files, query):
|
|
564 |
[z.write(f) for f in all_files]
|
565 |
return zip_name
|
566 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
567 |
# 🎮 Main Interface
|
568 |
def main():
|
569 |
init_session_state()
|
@@ -610,40 +656,35 @@ def main():
|
|
610 |
st.code(numbered_content, language="python")
|
611 |
|
612 |
message = st.text_input(f"Message as {st.session_state.username}", key="message_input")
|
613 |
-
|
614 |
-
|
615 |
-
|
|
|
|
|
616 |
voice = FUN_USERNAMES.get(st.session_state.username, "en-US-AriaNeural")
|
617 |
-
|
618 |
-
|
619 |
-
|
620 |
-
|
621 |
-
st.
|
622 |
-
|
623 |
-
|
624 |
-
|
625 |
-
|
626 |
-
|
627 |
-
|
628 |
-
|
629 |
-
|
630 |
-
|
631 |
-
|
632 |
-
|
633 |
-
|
634 |
-
|
635 |
-
|
636 |
-
|
637 |
-
|
638 |
-
if audio_file_arxiv:
|
639 |
-
play_and_download_audio(audio_file_arxiv)
|
640 |
-
st.session_state.pasted_image_data = None
|
641 |
-
st.session_state['paste_trigger'] = False
|
642 |
-
st.session_state.timer_start = time.time()
|
643 |
-
save_username(st.session_state.username)
|
644 |
-
st.rerun()
|
645 |
|
646 |
-
if (message and message != st.session_state.last_message) or (st.session_state.pasted_image_data and not st.session_state['
|
647 |
st.session_state.last_message = message
|
648 |
col_send, col_claude, col_arxiv = st.columns([1, 1, 1])
|
649 |
|
|
|
16 |
from audio_recorder_streamlit import audio_recorder
|
17 |
import nest_asyncio
|
18 |
import re
|
|
|
19 |
import pytz
|
20 |
import shutil
|
21 |
import anthropic
|
|
|
127 |
'autosend': True, 'autosearch': True, 'last_message': "", 'last_query': "",
|
128 |
'mp3_files': {}, 'timer_start': time.time(), 'quote_index': 0,
|
129 |
'quote_source': "famous", 'last_sent_transcript': "", 'old_val': None,
|
130 |
+
'last_refresh': time.time(), 'paper_metadata': {}, 'paste_image_base64': None
|
131 |
}
|
132 |
for k, v in defaults.items():
|
133 |
if k not in st.session_state:
|
|
|
563 |
[z.write(f) for f in all_files]
|
564 |
return zip_name
|
565 |
|
566 |
+
# Custom Paste Image Component
|
567 |
+
def paste_image_component():
|
568 |
+
# JavaScript to capture clipboard image and send it to Streamlit
|
569 |
+
paste_script = """
|
570 |
+
<script>
|
571 |
+
function pasteImage() {
|
572 |
+
navigator.clipboard.read().then(clipboardItems => {
|
573 |
+
for (const item of clipboardItems) {
|
574 |
+
if (item.types.includes('image/png') || item.types.includes('image/jpeg')) {
|
575 |
+
item.getType('image/png').then(blob => {
|
576 |
+
const reader = new FileReader();
|
577 |
+
reader.onload = function(event) {
|
578 |
+
document.getElementById('paste_input').value = event.target.result.split(',')[1];
|
579 |
+
document.getElementById('paste_form').submit();
|
580 |
+
};
|
581 |
+
reader.readAsDataURL(blob);
|
582 |
+
});
|
583 |
+
break;
|
584 |
+
}
|
585 |
+
}
|
586 |
+
}).catch(err => {
|
587 |
+
console.error('Failed to read clipboard: ', err);
|
588 |
+
document.getElementById('paste_input').value = 'ERROR: ' + err.message;
|
589 |
+
document.getElementById('paste_form').submit();
|
590 |
+
});
|
591 |
+
}
|
592 |
+
</script>
|
593 |
+
<form id="paste_form" action="/" method="POST" style="display: none;">
|
594 |
+
<input type="text" id="paste_input" name="paste_data" />
|
595 |
+
</form>
|
596 |
+
<button onclick="pasteImage()">Paste Image 📋</button>
|
597 |
+
"""
|
598 |
+
paste_data = components.html(paste_script, height=50)
|
599 |
+
if paste_data and 'paste_data' in paste_data:
|
600 |
+
base64_str = paste_data['paste_data']
|
601 |
+
if base64_str.startswith('ERROR:'):
|
602 |
+
st.warning(f"Paste failed: {base64_str}")
|
603 |
+
return None
|
604 |
+
try:
|
605 |
+
img_bytes = base64.b64decode(base64_str)
|
606 |
+
img = Image.open(io.BytesIO(img_bytes))
|
607 |
+
return img
|
608 |
+
except Exception as e:
|
609 |
+
st.warning(f"Error decoding pasted image: {e}")
|
610 |
+
return None
|
611 |
+
return None
|
612 |
+
|
613 |
# 🎮 Main Interface
|
614 |
def main():
|
615 |
init_session_state()
|
|
|
656 |
st.code(numbered_content, language="python")
|
657 |
|
658 |
message = st.text_input(f"Message as {st.session_state.username}", key="message_input")
|
659 |
+
|
660 |
+
# Custom Paste Image Button
|
661 |
+
pasted_image = paste_image_component()
|
662 |
+
if pasted_image is not None and st.session_state['paste_image_base64'] != pasted_image.tobytes():
|
663 |
+
st.session_state['paste_image_base64'] = pasted_image.tobytes()
|
664 |
voice = FUN_USERNAMES.get(st.session_state.username, "en-US-AriaNeural")
|
665 |
+
st.image(pasted_image, caption="Pasted Image")
|
666 |
+
filename = asyncio.run(save_pasted_image(pasted_image, st.session_state.username))
|
667 |
+
if filename:
|
668 |
+
st.session_state.pasted_image_data = filename
|
669 |
+
image_prompt = st.text_input("Add a prompt for Claude (e.g., 'OCR this image')", key="image_prompt")
|
670 |
+
if image_prompt:
|
671 |
+
md_file_claude, audio_file_claude, claude_result = asyncio.run(
|
672 |
+
perform_claude_search(image_prompt, st.session_state.username, pasted_image)
|
673 |
+
)
|
674 |
+
if audio_file_claude:
|
675 |
+
play_and_download_audio(audio_file_claude)
|
676 |
+
md_file_arxiv, audio_file_arxiv = asyncio.run(
|
677 |
+
perform_arxiv_search(image_prompt, st.session_state.username, claude_result)
|
678 |
+
)
|
679 |
+
if audio_file_arxiv:
|
680 |
+
play_and_download_audio(audio_file_arxiv)
|
681 |
+
st.session_state.pasted_image_data = None
|
682 |
+
st.session_state['paste_image_base64'] = None
|
683 |
+
st.session_state.timer_start = time.time()
|
684 |
+
save_username(st.session_state.username)
|
685 |
+
st.rerun()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
686 |
|
687 |
+
if (message and message != st.session_state.last_message) or (st.session_state.pasted_image_data and not st.session_state['paste_image_base64']):
|
688 |
st.session_state.last_message = message
|
689 |
col_send, col_claude, col_arxiv = st.columns([1, 1, 1])
|
690 |
|