SHODAN / script.js
jisaacso219's picture
Update script.js
a1b6108 verified
raw
history blame
1.96 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 res = await fetch('/chat', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ message: msg })
});
if (!res.ok) {
// log the actual payload for debugging:
const text = await res.text();
console.error('Chat error:', res.status, text);
throw new Error(`Status ${res.status}`);
}
const { response: text, audio_url } = await res.json();
streamText(text, () => {
if (audio_url) playAudio(audio_url);
});
} catch (err) {
streamText("❌ SHODAN encountered an error.", null);
console.error(err);
}
};