SHODAN / script.js
jisaacso219's picture
Update script.js
cfb4d9b verified
raw
history blame
1.75 kB
const form = document.getElementById('chat-form');
const input = form.querySelector('input');
const chatbox = document.getElementById('chatbox');
const avatar = document.getElementById('avatar');
const overlay = document.getElementById('overlay');
function addBubble(text, sender = 'user') {
const bubble = document.createElement('div');
bubble.className = 'bubble ' + sender;
bubble.innerText = text;
chatbox.appendChild(bubble);
chatbox.scrollTop = chatbox.scrollHeight;
}
function streamText(text, onDone) {
const bubble = document.createElement('div');
bubble.className = 'bubble ai';
chatbox.appendChild(bubble);
chatbox.scrollTop = chatbox.scrollHeight;
let i = 0;
function stream() {
if (i < text.length) {
bubble.innerText += text[i++];
chatbox.scrollTop = chatbox.scrollHeight;
setTimeout(stream, 20);
} else {
onDone && onDone();
}
}
stream();
}
function playAudio(url) {
avatar.classList.add('speaking');
const audio = new Audio(url);
audio.play();
audio.onended = () => {
avatar.classList.remove('speaking');
fetch(`/delete_audio?path=${encodeURIComponent(url)}`);
};
}
form.onsubmit = async (e) => {
e.preventDefault();
const msg = input.value.trim();
if (!msg) return;
addBubble(msg, 'user');
input.value = '';
try {
const response = await fetch('/ask', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ message: msg })
});
const { text, audio_url } = await response.json();
streamText(text, () => {
if (audio_url) playAudio(audio_url);
});
} catch (err) {
streamText("❌ SHODAN encountered an error.", null);
console.error(err);
}
};