//javascript // let audioEnabled = false; // audio is ooff // let audioMuted = true; let currentAudio = null; async function playReply(src) { if (currentAudio) { currentAudio.pause(); currentAudio = null; } currentAudio = new Audio(src); await currentAudio.play(); } document.getElementById('toggle-audio').addEventListener('click', () => { audioEnabled = !audioEnabled; audioMuted = !audioMuted; const icon = audioEnabled ? '🔊' : '🔇'; const label = audioEnabled ? 'Audio: On' : 'Audio: Off'; document.getElementById('toggle-audio').textContent = `${icon} ${label}`; // stop any in-flight audio if (currentAudio) { currentAudio.pause(); currentAudio = null; } // speechSynthesis.cancel(); // Stop anything currently speaking console.log('🔇 Audio muted'); }); let audio_instruction; // = 'Speak in a funny middle aged and funny tone, like a sasquatch'; const openingTaglines = [ 'Hey there, forest friend—Willy Squatch here! What wild wisdom can I share today?', 'Willy’s in the woods but I heard you—what cryptid conundrum’s on your mind?', 'Sup, woodland wanderer? Willy Squatch at your service—let’s get squatchy!', 'Growl! Willy Squatch reporting—hit me with your best question!', 'You rang? Willy Squatch here—ready to dish out some hairy advice!', 'What’s crackling among the leaves today? Willy Squatch is all ears!', 'Good day, tree trooper—Willy Squatch listening, shoot me your question!', 'Roar! Willy Squatch on the line—what’s got you curious in these woods?', 'Willy Squatch in the underbrush—what’s the scoop from your corner of the forest?', ]; function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } // pick one at random const randomTag = openingTaglines[ Math.floor(Math.random() * openingTaglines.length) ]; // you can extract your greeting logic into its own async fn: async function fireGreeting() { sendBtn.disabled = true; const typingEl = showTypingIndicator(); let payload; audio_instruction = 'Speak in a mean old man and scarey tone, like a sasquatch, end in a GRRRRRRR! HA Ha HA'; try { payload = await speakWithEleven(randomTag); } catch (err) { console.error('TTS error:', err); removeTypingIndicator(typingEl); appendMsg('assist', randomTag, true); return; } if (!payload.audio) { console.error('No audio returned'); removeTypingIndicator(typingEl); appendMsg('assist', randomTag, true); return; } const audio = new Audio(payload.audio); audio.addEventListener('play', () => { removeTypingIndicator(typingEl); appendMsg('assist', randomTag, true); }, { once: true }); try { await audio.play(); } catch (err) { console.error('Playback failed:', err); removeTypingIndicator(typingEl); appendMsg('assist', randomTag, true); } /// send an adv const cpaHtml = `

Top Q to Ask Willy! (click)

`; // appendMsg('list', cpaHtml, true); sendBtn.disabled = false; inputEl.focus(); } // --- DOM References --- const chatEl = document.getElementById('chat'); const inputEl = document.getElementById('input'); const sendBtn = document.getElementById('send'); let userHasInteracted = false; // delegate all clicks on .ask_q, even if added later document.addEventListener('click', async (e) => { const li = e.target.closest('.ask_q'); if (!li) return; // grab the question const msg = li.getAttribute('data-message'); inputEl.value = msg; // fire your send routine await sendMessage(); }); // --- Typing Indicator --- function showTypingIndicator() { const indicator = document.createElement('div'); indicator.className = 'typing-indicator'; indicator.innerHTML = '...'; chatEl.appendChild(indicator); chatEl.scrollTop = chatEl.scrollHeight; return indicator; } function removeTypingIndicator(ind) { if (ind && ind.parentNode) ind.parentNode.removeChild(ind); } // --- Append Messages --- function appendMsg(role, content, isHtml = false) { const wrapper = document.createElement('div'); wrapper.classList.add('msg', role === 'user' ? 'user' : role === 'assist' ? 'assist' : role === 'adv' ? 'adv' : 'assist'); if (role === 'assist') { const avatar = document.createElement('img'); avatar.src = 'willy_logo.png'; avatar.alt = 'Willy'; avatar.className = 'avatar'; wrapper.appendChild(avatar); } // if this is an “adv” message, inject an AdSense block if (role === 'adv') { // 1. Create a new, un-marked ins const adIns = document.createElement('ins'); adIns.className = 'adsbygoogle'; adIns.style.display = 'block'; adIns.style.width = '100%'; adIns.style.maxWidth = '300px'; adIns.setAttribute('data-ad-client', 'ca-pub-2528341625965597'); adIns.setAttribute('data-ad-slot', '4861484366'); // adIns.setAttribute('data-ad-format', 'fluid'); adIns.setAttribute('data-ad-layout-key', '-6t+ed+2i-1n-4w'); adIns.setAttribute('data-ad-format', 'fluid'); adIns.setAttribute('data-full-width-responsive', 'true'); wrapper.appendChild(adIns); chatEl.appendChild(wrapper); chatEl.scrollTop = chatEl.scrollHeight; // 2. Mark it immediately and push only this one adIns.dataset.adsInitiated = 'true'; setTimeout(() => { try { (adsbygoogle = window.adsbygoogle || []).push({}); } catch (e) { // no-op } }, 0); } const textEl = document.createElement('div'); if (isHtml) textEl.innerHTML = content; else textEl.textContent = content; wrapper.appendChild(textEl); chatEl.appendChild(wrapper); chatEl.scrollTop = chatEl.scrollHeight; } inputEl.addEventListener('keydown', e => { if (e.key === 'Enter' && !sendBtn.disabled) { e.preventDefault(); // prevent a form submit if you have one sendMessage(); } }); // --- Send Message --- async function sendMessage() { if (sendBtn.disabled) return; userHasInteracted = true; const msg = inputEl.value.trim(); if (!msg) return; appendMsg('user', msg); inputEl.value = ''; sendBtn.disabled = true; const typingEl = showTypingIndicator(); try { const res = await fetch('../../../../scripts/yeti_chat.js.php', { method: 'POST', credentials: 'same-origin', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ message: msg }) }); const data = await res.json(); /// look for action if (data.action) { eval(data.action);} if (data.error) { appendMsg('assist', `Error: ${data.error}`, true); } else { let payload; try { audio_instruction = 'Speak in a kind old man and scruffy tone, like a sasquatch, end in a happy Grrrrr and a laugh! Ha Ha HA!'; payload = await speakWithEleven(data.reply); } catch (err) { console.error('TTS error:', err); appendMsg('assist', data.reply, true); return; } if (!payload.audio) { removeTypingIndicator(typingEl); console.error('No audio returned'); appendMsg('assist', data.reply, true); return; } const audio = new Audio(payload.audio); audio.addEventListener('play', () => { appendMsg('assist', data.reply, true); }, { once: true }); audio.addEventListener('ended', () => { console.log('Audio has finished playing'); sendBtn.disabled = false; }, { once: true }); try { await audio.play(); } catch (err) { console.error('Playback failed:', err); appendMsg('assist', data.reply, true); } } removeTypingIndicator(typingEl); } catch (err) { removeTypingIndicator(typingEl); appendMsg('assist', 'Network error, Service in these woods is sketchy!! try again.', true); console.error(err); } finally { sendBtn.disabled = false; inputEl.focus(); } } // --- Event Listeners --- sendBtn.addEventListener('click', sendMessage); inputEl.addEventListener('keydown', e => { if (e.key === 'Enter') sendMessage(); }); function stripTags(str) { return str.replace(/<[^>]*>/g, ''); } async function speakWithEleven(text) { if (audioMuted) {return { error: "Audio is muted so no audio" }; } text = stripTags(text); try { const token = 'a4456a6b-128d-4f9c-8dbc-85e8b2584303'; const res = await fetch('../../../../../scripts/chat_voicekiller.js.php', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ instructions: audio_instruction, token, text }) }); const payload = await res.json(); if (!res.ok) throw new Error(payload.error || 'TTS failed'); return payload; } catch (err) { console.error(err); window.speechSynthesis.speak(new SpeechSynthesisUtterance(text)); } }