// Same-origin API calls const API_BASE = ""; // Session utilities function getSessionId() { let sid = localStorage.getItem("session_id"); if (!sid) { sid = crypto.randomUUID(); localStorage.setItem("session_id", sid); } return sid; } function setNewSessionId() { const sid = crypto.randomUUID(); localStorage.setItem("session_id", sid); return sid; } // UI helpers function addMessage(text, who = "bot") { const win = document.getElementById("chat-window"); const div = document.createElement("div"); div.className = `message ${who}`; div.textContent = text; win.appendChild(div); win.scrollTop = win.scrollHeight; } function disableInput(reason = "Input disabled.") { document.getElementById("chat-input").disabled = true; document.getElementById("send-btn").disabled = true; document.getElementById("status").textContent = reason; } function enableInput() { document.getElementById("chat-input").disabled = false; document.getElementById("send-btn").disabled = false; document.getElementById("status").textContent = ""; } function clearChat() { const win = document.getElementById("chat-window"); win.innerHTML = ""; document.getElementById("status").textContent = ""; } // Backend calls async function moderateText(text) { const sid = getSessionId(); const res = await fetch(`${API_BASE}/moderate`, { method: "POST", headers: { "Content-Type": "application/json", "X-Session-Id": sid }, body: JSON.stringify({ text }) }); if (!res.ok) throw new Error(`Moderate failed: ${res.status}`); return res.json(); // {allowed, banned, lock, reason?} } async function sendChat(text) { const sid = getSessionId(); const res = await fetch(`${API_BASE}/chat`, { method: "POST", headers: { "Content-Type": "application/json", "X-Session-Id": sid }, body: JSON.stringify({ text }) }); if (!res.ok) throw new Error(`Chat failed: ${res.status}`); return res.json(); // {reply} } // Flow handlers function submitName() { const nameInput = document.getElementById("name-input"); const name = (nameInput.value || "").trim(); if (!name) return; document.getElementById("name-section").classList.add("hidden"); document.getElementById("chat-section").classList.remove("hidden"); clearChat(); enableInput(); addMessage(`Welcome, ${name}!`, "bot"); addMessage(name, "user"); // immediately show name in chat } async function submitMessage() { const input = document.getElementById("chat-input"); const text = (input.value || "").trim(); if (!text) return; try { const mod = await moderateText(text); if (mod.banned) { addMessage("banned", "bot"); if (mod.lock) disableInput(mod.reason || "Input disabled due to policy violation."); return; } addMessage(text, "user"); const resp = await sendChat(text); addMessage(resp.reply, "bot"); } catch (err) { disableInput("Error communicating with server."); console.error(err); } finally { input.value = ""; } } // Top-bar actions function goHome() { // Reload root to show name section by default window.location.href = "/"; } function newUser() { // Reset session, show name input again, clear chat, re-enable input setNewSessionId(); clearChat(); enableInput(); document.getElementById("chat-section").classList.add("hidden"); document.getElementById("name-section").classList.remove("hidden"); document.getElementById("name-input").value = ""; document.getElementById("chat-input").value = ""; } // Wire up buttons and Enter keys document.getElementById("home-btn").addEventListener("click", goHome); document.getElementById("new-user-btn").addEventListener("click", newUser); document.getElementById("name-submit").addEventListener("click", submitName); document.getElementById("name-input").addEventListener("keydown", (e) => { if (e.key === "Enter") submitName(); }); document.getElementById("send-btn").addEventListener("click", submitMessage); document.getElementById("chat-input").addEventListener("keydown", (e) => { if (e.key === "Enter") submitMessage(); }); document.getElementById("clear-btn").addEventListener("click", clearChat);