| |
| |
| |
| |
| |
| document.addEventListener('DOMContentLoaded', function() { |
| const token = localStorage.getItem('authToken'); |
| const userInfoDiv = document.getElementById('user-info'); |
| const loginLink = document.getElementById('login-link'); |
| const charchaButton = document.getElementById('charchaButton'); |
| |
| if (token) { |
| |
| fetch('https://thevera-botveradb.hf.space/validate_token', { |
| method: 'GET', |
| headers: { |
| 'Authorization': `Bearer ${token}` |
| } |
| }) |
| .then(response => response.json()) |
| .then(data => { |
| |
| if (data.message === "Token is valid!") { |
| |
| const userObject = jwt_decode(token); |
| const email = userObject.email; |
| const username = email.split('@')[0]; |
| |
| document.getElementById('user-name').innerText = username; |
| userInfoDiv.style.display = 'block'; |
| document.getElementById('logout-button').style.display = 'inline'; |
| loginLink.style.display = 'none'; |
| } else { |
| |
| localStorage.removeItem('authToken'); |
| console.log('Invalid token, user not logged in.'); |
| loginLink.style.display = 'inline'; |
| } |
| }) |
| .catch(error => { |
| console.error('Error:', error); |
| |
| localStorage.removeItem('authToken'); |
| loginLink.style.display = 'inline'; |
| }); |
| } else { |
| |
| console.log('No token found, user not logged in.'); |
| loginLink.style.display = 'inline'; |
| } |
| |
| |
| const logoutButton = document.getElementById('logout-button'); |
| if (logoutButton) { |
| logoutButton.onclick = function() { |
| localStorage.removeItem('authToken'); |
| window.location.reload(); |
| }; |
| } |
|
|
| |
| function redirectToCharcha() { |
| if (token) { |
| |
| fetch('https://thevera-botveradb.hf.space/validate_token', { |
| method: 'GET', |
| headers: { |
| 'Authorization': `Bearer ${token}` |
| } |
| }) |
| .then(response => response.json()) |
| .then(data => { |
| if (data.message === "Token is valid!") { |
| |
| window.location.href = 'https://thevera-shastracharcha.static.hf.space'; |
| window.location.href = 'sastra.html'; |
| } else { |
| |
| localStorage.removeItem('authToken'); |
| window.location.href = 'login.html'; |
| } |
| }) |
| .catch(error => { |
| console.error('Error:', error); |
| localStorage.removeItem('authToken'); |
| window.location.href = 'login.html'; |
| }); |
| } else { |
| |
| window.location.href = 'login.html'; |
| } |
| } |
|
|
| |
| if (charchaButton) { |
| charchaButton.addEventListener('click', redirectToCharcha); |
| } |
| }); |
|
|
|
|
| if ('serviceWorker' in navigator) { |
| window.addEventListener('load', () => { |
| navigator.serviceWorker.register('/service-worker.js') |
| .then(registration => { |
| console.log('ServiceWorker registered: ', registration); |
| }) |
| .catch(error => { |
| console.log('ServiceWorker registration failed: ', error); |
| }); |
| }); |
| } |
|
|
|
|
| |
| if (!('webkitSpeechRecognition' in window)) { |
| alert("Your browser doesn't support speech recognition. Please use Google Chrome."); |
| } else { |
| |
| const recognition = new webkitSpeechRecognition(); |
| recognition.continuous = false; |
| recognition.interimResults = false; |
| recognition.lang = 'en-IN'; |
|
|
| const micButton = document.getElementById('micButton'); |
| const userInput = document.getElementById('userInput'); |
| const chatBody = document.getElementById('chatBody'); |
|
|
| |
| micButton.addEventListener('click', () => { |
| if (micButton.classList.contains('active')) { |
| recognition.stop(); |
| } else { |
| recognition.start(); |
| } |
| }); |
|
|
| |
| recognition.onstart = () => { |
| micButton.classList.add('active'); |
| }; |
|
|
| |
| recognition.onend = () => { |
| micButton.classList.remove('active'); |
| }; |
|
|
| |
| recognition.onresult = (event) => { |
| const transcript = event.results[0][0].transcript; |
| userInput.value = transcript; |
| sendMessage(); |
| }; |
|
|
| |
| recognition.onerror = (event) => { |
| alert('Speech recognition error: ' + event.error); |
| micButton.classList.remove('active'); |
| }; |
| } |
|
|
| |
| const userInput = document.getElementById('userInput'); |
|
|
| userInput.addEventListener('keydown', function(event) { |
| |
| if (event.key === 'Enter') { |
| event.preventDefault(); |
| sendMessage(); |
| } |
| }); |
|
|
|
|
| let isSpeakEnabled = true; |
|
|
| function toggleHistory() { |
| const historyPanel = document.querySelector('.history-panel'); |
| const chatHistoryText = document.querySelector('.chat-history-text'); |
| |
| |
| if (historyPanel.style.width === '0px') { |
| historyPanel.style.width = '250px'; |
| chatHistoryText.style.display = 'block'; |
| } else { |
| historyPanel.style.width = '0px'; |
| chatHistoryText.style.display = 'none'; |
| } |
| } |
|
|
|
|
| function toggleMenu() { |
| const menu = document.getElementById("menuOptions"); |
| menu.style.display = menu.style.display === "block" ? "none" : "block"; |
| } |
|
|
| function openSettings() { |
| document.getElementById("settingsModal").style.display = "block"; |
| document.getElementById("menuOptions").style.display = "none"; |
| } |
|
|
| function closeSettings() { |
| document.getElementById("settingsModal").style.display = "none"; |
| } |
|
|
| function toggleSpeak() { |
| const speakToggle = document.getElementById("speakToggle"); |
| isSpeakEnabled = speakToggle.checked; |
| console.log(isSpeakEnabled ? "Speech enabled" : "Speech disabled"); |
| } |
|
|
|
|
| |
| window.onclick = function(event) { |
| const modal = document.getElementById("settingsModal"); |
| if (event.target === modal) { |
| closeSettings(); |
| } |
| } |
|
|
|
|
| function startNewChat() { |
| |
| const chatBody = document.getElementById('chatBody'); |
|
|
| |
| chatBody.innerHTML = ''; |
|
|
| |
| const welcomeMessage = document.createElement('div'); |
| welcomeMessage.classList.add('bot-message'); |
| welcomeMessage.textContent = "Hello! How can I assist you today?"; |
|
|
| chatBody.appendChild(welcomeMessage); |
|
|
| |
| chatBody.scrollTop = chatBody.scrollHeight; |
| } |
|
|
| function remove_special_chars(text) { |
| |
| const allow = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890 :,.?!"; |
| |
| text = text.replace(/<br>/g, " "); |
| let newtxt = ""; |
| |
| for (let char of text) { |
| if (allow.includes(char)) { |
| newtxt += char; |
| } |
| } |
| return newtxt; |
| } |
|
|
|
|
|
|
| |
| function speakTextSequential(text, language, callback) { |
| if (!isSpeakEnabled) { |
| console.log('Speech is disabled.'); |
| if (callback) callback(); |
| return; |
| } |
|
|
| |
| text = text.replace(/<\/?[^>]+(>|$)/g, ""); |
|
|
| if ('speechSynthesis' in window) { |
| |
| window.speechSynthesis.cancel(); |
|
|
| const utterance = new SpeechSynthesisUtterance(text); |
|
|
| |
| switch (language) { |
| case 'hi': |
| utterance.lang = 'hi-IN'; |
| break; |
| case 'en': |
| default: |
| utterance.lang = 'en-IN'; |
| break; |
| } |
|
|
| |
| const voices = window.speechSynthesis.getVoices(); |
| const maleVoice = voices.find(voice => { |
| return (voice.name.includes('Google') || voice.name.includes('Indian')) && voice.name.toLowerCase().includes('male'); |
| }); |
|
|
| if (maleVoice) { |
| utterance.voice = maleVoice; |
| } else { |
| |
| const defaultVoice = voices.find(voice => voice.name.includes('Google') || voice.name.includes('Indian')); |
| if (defaultVoice) { |
| utterance.voice = defaultVoice; |
| } |
| } |
|
|
| |
| utterance.pitch = 1; |
| utterance.rate = 1; |
| utterance.volume = 1; |
|
|
| |
| const pauseDuration = 500; |
| const splitText = text.split(/(?<=[.!?])\s+/); |
| const speakingOrder = splitText.map(part => part.trim()).filter(part => part); |
|
|
| |
| const speakSegment = (index) => { |
| if (index < speakingOrder.length) { |
| const segment = speakingOrder[index]; |
| if (segment) { |
| utterance.text = segment; |
| speechSynthesis.speak(utterance); |
| utterance.onend = () => speakSegment(index + 1); |
| } else { |
| speakSegment(index + 1); |
| } |
| } else { |
| if (callback) { |
| callback(); |
| } |
| } |
| }; |
|
|
| |
| speakSegment(0); |
|
|
| |
| utterance.onerror = function(event) { |
| console.error('SpeechSynthesisUtterance error:', event.error); |
| if (callback) { |
| callback(); |
| } |
| }; |
|
|
| } else { |
| alert('Text-to-Speech not supported in your browser.'); |
| if (callback) { |
| callback(); |
| } |
| } |
| } |
|
|
|
|
|
|
| |
| function formatBotResponse(rawResponse) { |
| |
| let rawResponseList = rawResponse.split('\n'); |
| let category = rawResponseList.length > 0 ? rawResponseList[0] : "General"; |
| let onlyResponse = rawResponseList.slice(1).join('\n'); |
|
|
| let formattedResponse = onlyResponse |
| .replace(/\n/g, '<br>') |
| .replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>') |
| .replace(/\*(.*?)\*/g, '<em>$1</em>') |
| .replace(/(\d+\.\s.*?)(?=\n|$)/g, '<li>$1</li>'); |
|
|
| |
| formattedResponse = formattedResponse.replace(/(<li>.*?<\/li>)+/g, '<ul>$&</ul>'); |
|
|
| return { formattedResponse, category }; |
| } |
|
|
|
|
| function sendMessage() { |
| const message = userInput.value.trim(); |
|
|
| if (message !== "") { |
| appendMessage(message, 'user-message'); |
| userInput.value = ''; |
|
|
| |
| micButton.disabled = true; |
|
|
| let username = null; |
| let isRegisteredUser = false; |
|
|
| |
| try { |
| const token = localStorage.getItem('authToken'); |
| if (token) { |
| const userObject = jwt_decode(token); |
| username = userObject.email; |
| isRegisteredUser = !!username; |
| } |
| } catch (error) { |
| console.error("Error decoding token or no token found:", error); |
| } |
|
|
| |
| const requestData = { |
| user_data: message, |
| bot_data: null |
| }; |
|
|
| |
| fetch('https://thevera-backendvera.hf.space/generate_result', { |
| method: 'POST', |
| headers: { |
| 'Content-Type': 'application/json', |
| }, |
| body: JSON.stringify({ message: message }) |
| }) |
| .then(response => { |
| if (!response.ok) { |
| throw new Error("Failed to generate result"); |
| } |
| return response.json(); |
| }) |
| .then(data => { |
| let botResponses = data.response; |
| const language = data.language || 'en'; |
| |
| const { formattedResponse: botResponse, category } = formatBotResponse(botResponses); |
| |
| appendMessage(category, 'bot-message'); |
| |
| |
| const mantraRegex = /\[\[(.*?)\]\]/g; |
| let lastIndex = 0; |
| let blocks = []; |
| |
| let match; |
| |
| |
| while ((match = mantraRegex.exec(botResponse)) !== null) { |
| const mantraText = match[1].trim(); |
| const mantraStartIndex = match.index; |
| |
| |
| const beforeMantraText = botResponse.substring(lastIndex, mantraStartIndex).trim(); |
| if (beforeMantraText) { |
| blocks.push({ type: 'text', content: beforeMantraText }); |
| } |
| |
| |
| blocks.push({ type: 'mantra', content: mantraText }); |
| |
| |
| lastIndex = mantraRegex.lastIndex; |
| } |
| |
| |
| const afterLastMantraText = botResponse.substring(lastIndex).trim(); |
| if (afterLastMantraText) { |
| blocks.push({ type: 'text', content: afterLastMantraText }); |
| } |
| |
| |
| processSequentially(blocks, language); |
| |
| |
| |
| requestData.bot_data = botResponse; |
| |
| |
| const baseURL = 'https://thevera-botveradb.hf.space'; |
| const storeChatURL = isRegisteredUser |
| ? `${baseURL}/store_registered_chat/${username}` |
| : `${baseURL}/store_anonymous_chat`; |
| |
| |
| return fetch(storeChatURL, { |
| method: 'POST', |
| headers: { |
| 'Content-Type': 'application/json', |
| }, |
| body: JSON.stringify(requestData) |
| }); |
| }) |
| .then(response => { |
| if (!response.ok) { |
| throw new Error("Failed to store chat data"); |
| } |
| return response.json(); |
| }) |
| .then(data => { |
| console.log(data.message); |
| micButton.disabled = false; |
| }) |
| .catch(error => { |
| alert('Failed to connect to the backend. Please try again later.'); |
| console.error('Error:', error); |
| micButton.disabled = false; |
| }); |
| } |
| } |
|
|
| |
| |
| function processSequentially(blocks, language, index = 0) { |
| if (index >= blocks.length) { |
| return; |
| } |
|
|
| const block = blocks[index]; |
|
|
| if (block.type === 'text') { |
| |
| appendMessage(block.content, 'bot-message'); |
| speakTextSequential(block.content, language, () => { |
| |
| processSequentially(blocks, language, index + 1); |
| }); |
| } else if (block.type === 'mantra') { |
| |
| displayMantra(block.content); |
| speakMantraSequential(block.content, 1, () => { |
| |
| processSequentially(blocks, language, index + 1); |
| }); |
| } |
| } |
|
|
| |
| function displayMantra(mantraText) { |
| const mantraBlock = document.createElement('div'); |
| mantraBlock.className = 'mantra-block'; |
| mantraBlock.innerHTML = `<pre id="mantraText">${mantraText}</pre> |
| <label for="repeat-count">Repeat mantra:</label> |
| <div id="repeat-control"> |
| <button onclick="decreaseCount()">-</button> |
| <input type="number" id="repeat-count" value="1" min="1" max="100" /> |
| <button onclick="increaseCount()">+</button> |
| </div> |
| <div class="play-mantra-button-container"> |
| <button class="play-mantra-button" onclick="repeatMantra()">▶</button> <!-- Play button icon --> |
| </div>`; |
| |
| document.getElementById('chatBody').appendChild(mantraBlock); |
| } |
|
|
|
|
| |
| function hideMantraBlock() { |
| let mantraBlock = document.getElementById('mantra-block'); |
| mantraBlock.style.display = 'none'; |
| } |
|
|
| |
| function decreaseCount() { |
| let repeatCountInput = document.getElementById('repeat-count'); |
| let currentValue = parseInt(repeatCountInput.value); |
| |
| if (currentValue > 1) { |
| repeatCountInput.value = currentValue - 1; |
| } |
| } |
|
|
| |
| function increaseCount() { |
| let repeatCountInput = document.getElementById('repeat-count'); |
| let currentValue = parseInt(repeatCountInput.value); |
| |
| repeatCountInput.value = currentValue + 1; |
| } |
|
|
|
|
| |
| function speakMantraSequential(mantraText, repeatCount, callback) { |
| const utterance = new SpeechSynthesisUtterance(mantraText); |
| utterance.lang = 'sa-IN'; |
| utterance.rate = 0.8; |
| utterance.pitch = 1.0; |
| |
| utterance.onend = function() { |
| if (repeatCount > 1) { |
| repeatCount--; |
| speechSynthesis.speak(utterance); |
| } else if (callback) { |
| callback(); |
| } |
| }; |
|
|
| |
| utterance.onerror = function(event) { |
| console.error('SpeechSynthesisUtterance error:', event.error); |
| if (callback) { |
| callback(); |
| } |
| }; |
|
|
| |
| window.speechSynthesis.cancel(); |
| speechSynthesis.speak(utterance); |
| } |
|
|
|
|
|
|
| |
| function repeatMantra() { |
| let mantraText = document.getElementById('mantraText').textContent; |
| let repeatCount = parseInt(document.getElementById('repeat-count').value); |
|
|
| if (repeatCount < 1) { |
| alert("Repeat count must be at least 1"); |
| return; |
| } |
|
|
| |
| speakMantraSequential(mantraText, repeatCount, 1); |
| } |
|
|
| |
|
|
| let isFirstMessage = true; |
|
|
| |
| function appendMessage(text, className) { |
| |
| if (isFirstMessage) { |
| const welcomeMessage = document.querySelector('.welcome-message'); |
| if (welcomeMessage) { |
| welcomeMessage.remove(); |
| } |
| isFirstMessage = false; |
| } |
| const messageElement = document.createElement('div'); |
| messageElement.classList.add('user-message', className); |
| |
| |
| messageElement.innerHTML = text; |
| chatBody.appendChild(messageElement); |
| chatBody.scrollTop = chatBody.scrollHeight; |
| } |
|
|
| |
| |
| |
| |
| |
| |
|
|
| |
| function showDonateModal() { |
| document.getElementById('donateModal').style.display = 'block'; |
| } |
|
|
| |
| function closeDonateModal() { |
| document.getElementById('donateModal').style.display = 'none'; |
| } |
|
|
| |
| function copyUpiId() { |
| const upiId = document.getElementById("upiId").innerText; |
| navigator.clipboard.writeText(upiId).then(() => { |
| alert("UPI ID copied to clipboard"); |
| }).catch(err => { |
| console.error('Could not copy text: ', err); |
| }); |
| } |
|
|
|
|
|
|