File size: 23,083 Bytes
dc18f90 ca7d642 76ce326 c674fc7 3ec1f10 c674fc7 6fa3e37 76ce326 c674fc7 2396855 c674fc7 2396855 3f8a43e c674fc7 3f8a43e c674fc7 3f8a43e c674fc7 3f8a43e c674fc7 3f8a43e c674fc7 3f8a43e 76ce326 9a17648 610d0de 9a17648 3ec1f10 9a17648 3ec1f10 9a17648 3ec1f10 9a17648 c674fc7 f84f799 c674fc7 f0b3a83 9dddb7c f0b3a83 9dddb7c f0b3a83 7a3a139 9a17648 5d7b3f0 7a3a139 9dddb7c 7a3a139 614185c 0c62990 7a3a139 5d7b3f0 5c9b443 46c3b9c 5d7b3f0 5227530 9dddb7c 5227530 9dddb7c 5227530 9dddb7c 5227530 9dddb7c 5227530 9dddb7c 5227530 ed1b5fc 3c99815 5227530 cae2692 d18d80b cae2692 d18d80b cae2692 d18d80b 5d7b3f0 d18d80b 7ebcabb d18d80b 7ebcabb d18d80b 7ebcabb d18d80b 7ebcabb d18d80b 7ebcabb d18d80b 7ebcabb d18d80b f0b3a83 5d7b3f0 7ebcabb 182b1e5 d154fde d868a54 05e3623 d868a54 05e3623 d868a54 d154fde d868a54 d154fde f0b3a83 a3a7f0e 881217c a3a7f0e d7a884a a3a7f0e d7a884a 5e7868b a3a7f0e 5e7868b 9de352b 807d76a 9de352b d868a54 807d76a 9de352b 807d76a 9de352b 807d76a 9de352b 807d76a 9de352b 807d76a d868a54 807d76a 9de352b 807d76a 9de352b 807d76a d868a54 a3a7f0e d868a54 38fe949 d7a884a d868a54 a3a7f0e d7a884a 6fa3e37 a3a7f0e 6fa3e37 a3a7f0e 5e7868b d7a884a a3a7f0e 5e7868b 6fa3e37 f0b3a83 89717b4 807d76a 89717b4 a5ea3fb 38fe949 a5ea3fb a410f9f 2b4fccf a5ea3fb 38fe949 89717b4 a410f9f 38fe949 89717b4 cae2692 89717b4 18cbbee 89717b4 cae2692 89717b4 cae2692 89717b4 cae2692 89717b4 d18d80b 89717b4 a3a7f0e 7a3a139 38fe949 18cbbee 7a3a139 18cbbee f0b3a83 8f2ba3c c76d922 8cc1d61 c76d922 f16988b c76d922 27ffa1a f16988b | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 | // Load data from JSON file
// window.speechSynthesis.onvoiceschanged = () => {
// const voices = window.speechSynthesis.getVoices();
// console.log('Available voices:', voices);
// };
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) {
// Check token validity with backend
fetch('https://thevera-botveradb.hf.space/validate_token', {
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`
}
})
.then(response => response.json())
.then(data => {
// if (data.success) {
if (data.message === "Token is valid!") {
// Token is valid, extract user's email and display it
const userObject = jwt_decode(token); // Decode the token to get user info
const email = userObject.email; // Assuming the email is stored in the token
const username = email.split('@')[0];
// Display user information
document.getElementById('user-name').innerText = username; // Display first name
userInfoDiv.style.display = 'block'; // Show user info
document.getElementById('logout-button').style.display = 'inline'; // Show logout button
loginLink.style.display = 'none'; // Hide login link
} else {
// Token is invalid, clear invalid token
localStorage.removeItem('authToken');
console.log('Invalid token, user not logged in.');
loginLink.style.display = 'inline'; // Show login link
}
})
.catch(error => {
console.error('Error:', error);
// Handle the error (e.g., network issues)
localStorage.removeItem('authToken'); // Clear token in case of error
loginLink.style.display = 'inline'; // Show login link
});
} else {
// No token found, show login link
console.log('No token found, user not logged in.');
loginLink.style.display = 'inline';
}
// Logout function
const logoutButton = document.getElementById('logout-button');
if (logoutButton) {
logoutButton.onclick = function() {
localStorage.removeItem('authToken'); // Clear token
window.location.reload(); // Refresh page to update UI
};
}
// Function to handle redirection for Sastra Charcha button
function redirectToCharcha() {
if (token) {
// If the token exists, verify it
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!") {
// Token is valid, redirect to Sastra Charcha page
window.location.href = 'https://thevera-shastracharcha.static.hf.space';
window.location.href = 'sastra.html';
} else {
// Token is invalid, redirect to registration page
localStorage.removeItem('authToken'); // Clear invalid token
window.location.href = 'login.html';
}
})
.catch(error => {
console.error('Error:', error);
localStorage.removeItem('authToken'); // Clear token on error
window.location.href = 'login.html'; // Redirect to registration if there's an error
});
} else {
// No token, redirect to registration page
window.location.href = 'login.html';
}
}
// Attach the redirect function to the button
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);
});
});
}
// Check if the browser supports the Web Speech API
if (!('webkitSpeechRecognition' in window)) {
alert("Your browser doesn't support speech recognition. Please use Google Chrome.");
} else {
// Initialize speech recognition
const recognition = new webkitSpeechRecognition();
recognition.continuous = false;
recognition.interimResults = false;
recognition.lang = 'en-IN'; // Default language (can be 'hi-IN' for Hindi)
const micButton = document.getElementById('micButton'); // Microphone icon
const userInput = document.getElementById('userInput'); // Text input field
const chatBody = document.getElementById('chatBody'); // Chat history container
// Voice Input Button Click Event
micButton.addEventListener('click', () => {
if (micButton.classList.contains('active')) {
recognition.stop(); // Stop if already active
} else {
recognition.start(); // Start listening
}
});
// When speech recognition starts
recognition.onstart = () => {
micButton.classList.add('active'); // Change mic color to green
};
// When speech recognition ends
recognition.onend = () => {
micButton.classList.remove('active'); // Reset mic color to red
};
// When speech recognition result is detected
recognition.onresult = (event) => {
const transcript = event.results[0][0].transcript;
userInput.value = transcript; // Fill the input with transcribed text
sendMessage(); // Call sendMessage after getting the input
};
// Handle errors during speech recognition
recognition.onerror = (event) => {
alert('Speech recognition error: ' + event.error);
micButton.classList.remove('active'); // Reset mic color to red if error occurs
};
}
// Add an event listener to the input field to detect the Enter key
const userInput = document.getElementById('userInput');
userInput.addEventListener('keydown', function(event) {
// Check if the Enter key (key code 13) is pressed
if (event.key === 'Enter') {
event.preventDefault(); // Prevent the default behavior (new line)
sendMessage(); // Call your send message function
}
});
let isSpeakEnabled = true;
function toggleHistory() {
const historyPanel = document.querySelector('.history-panel');
const chatHistoryText = document.querySelector('.chat-history-text');
// Toggle the width of the history panel
if (historyPanel.style.width === '0px') {
historyPanel.style.width = '250px'; // Open the panel
chatHistoryText.style.display = 'block'; // Show "Chat History" text
} else {
historyPanel.style.width = '0px'; // Close the panel
chatHistoryText.style.display = 'none'; // Hide "Chat History" text
}
}
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"; // Close menu when settings open
}
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");
}
// Close the modal when clicking outside of it
window.onclick = function(event) {
const modal = document.getElementById("settingsModal");
if (event.target === modal) {
closeSettings();
}
}
function startNewChat() {
// Select the chat body element
const chatBody = document.getElementById('chatBody');
// Remove all chat messages
chatBody.innerHTML = ''; // This clears all existing messages
// Optionally, add the default welcome message again
const welcomeMessage = document.createElement('div');
welcomeMessage.classList.add('bot-message');
welcomeMessage.textContent = "Hello! How can I assist you today?";
chatBody.appendChild(welcomeMessage);
// Scroll to the top after resetting chat
chatBody.scrollTop = chatBody.scrollHeight;
}
function remove_special_chars(text) {
// Allow only specified characters
const allow = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890 :,.?!";
// Replace <br> with a space for better readability
text = text.replace(/<br>/g, " ");
let newtxt = "";
// Iterate through the text and include only allowed characters
for (let char of text) {
if (allow.includes(char)) {
newtxt += char;
}
}
return newtxt;
}
// Helper function to speak text and execute a callback when done
function speakTextSequential(text, language, callback) {
if (!isSpeakEnabled) {
console.log('Speech is disabled.');
if (callback) callback(); // Call callback even if speech is disabled
return; // Exit if speech is disabled
}
// Clean the text of HTML tags
text = text.replace(/<\/?[^>]+(>|$)/g, "");
if ('speechSynthesis' in window) {
// Cancel any ongoing speech synthesis to avoid overlap
window.speechSynthesis.cancel();
const utterance = new SpeechSynthesisUtterance(text);
// Set the language based on the input
switch (language) {
case 'hi':
utterance.lang = 'hi-IN'; // Hindi
break;
case 'en':
default:
utterance.lang = 'en-IN'; // English (India)
break;
}
// Set voice preferences to find a male voice
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 {
// If no specific male voice found, fallback to any voice
const defaultVoice = voices.find(voice => voice.name.includes('Google') || voice.name.includes('Indian'));
if (defaultVoice) {
utterance.voice = defaultVoice;
}
}
// Set pitch, rate, and volume for a more natural sound
utterance.pitch = 1; // Adjust pitch for a male voice
utterance.rate = 1; // Normal speed
utterance.volume = 1; // Maximum volume
// Insert pauses for a more teaching-like effect
const pauseDuration = 500; // Pause duration in milliseconds
const splitText = text.split(/(?<=[.!?])\s+/); // Split text by punctuation and following spaces
const speakingOrder = splitText.map(part => part.trim()).filter(part => part); // Clean up split results and filter out empty strings
// Function to speak the segments sequentially
const speakSegment = (index) => {
if (index < speakingOrder.length) {
const segment = speakingOrder[index];
if (segment) {
utterance.text = segment; // Set the text to speak
speechSynthesis.speak(utterance);
utterance.onend = () => speakSegment(index + 1); // Speak next segment after the current one ends
} else {
speakSegment(index + 1); // Move to the next index if the segment is empty
}
} else {
if (callback) {
callback(); // Call the callback when done
}
}
};
// Start speaking the first segment
speakSegment(0);
// Handle potential speech synthesis errors
utterance.onerror = function(event) {
console.error('SpeechSynthesisUtterance error:', event.error);
if (callback) {
callback(); // Call callback even if there's an error
}
};
} else {
alert('Text-to-Speech not supported in your browser.');
if (callback) {
callback(); // Call callback if TTS is not supported
}
}
}
// Format bot response and handle categories
function formatBotResponse(rawResponse) {
// Replace newlines with actual <br> for line breaks
let rawResponseList = rawResponse.split('\n');
let category = rawResponseList.length > 0 ? rawResponseList[0] : "General"; // Use ternary for category assignment
let onlyResponse = rawResponseList.slice(1).join('\n'); // Use slice to skip the first element
let formattedResponse = onlyResponse
.replace(/\n/g, '<br>') // Replace newline with line breaks
.replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>') // Bold text between ** **
.replace(/\*(.*?)\*/g, '<em>$1</em>') // Italic text between * *
.replace(/(\d+\.\s.*?)(?=\n|$)/g, '<li>$1</li>'); // Convert numbered lists
// Wrap list items in <ul> tags
formattedResponse = formattedResponse.replace(/(<li>.*?<\/li>)+/g, '<ul>$&</ul>');
return { formattedResponse, category }; // Return an object for clarity
}
function sendMessage() {
const message = userInput.value.trim();
if (message !== "") {
appendMessage(message, 'user-message');
userInput.value = '';
// Disable the mic button to prevent multiple submissions during processing
micButton.disabled = true;
let username = null;
let isRegisteredUser = false;
// Try to get the user info from the token stored in local storage
try {
const token = localStorage.getItem('authToken');
if (token) {
const userObject = jwt_decode(token); // Decode the JWT token to get user info
username = userObject.email; // Extract username (email) from the decoded token
isRegisteredUser = !!username; // Check if user is registered (truthy if email exists)
}
} catch (error) {
console.error("Error decoding token or no token found:", error);
}
// Prepare the request data to send to the backend
const requestData = {
user_data: message,
bot_data: null // Placeholder for the bot's response
};
// Send the user message to the backend for processing
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); // Destructure correctly
appendMessage(category, 'bot-message'); // Show the category
// Regular expression to match all mantras or sloks within [[ ]]
const mantraRegex = /\[\[(.*?)\]\]/g;
let lastIndex = 0; // Keep track of the last index processed
let blocks = []; // Array to hold the sections of text and mantras
let match;
// Loop over all mantra matches and build blocks array
while ((match = mantraRegex.exec(botResponse)) !== null) {
const mantraText = match[1].trim(); // Extract the mantra/slok content
const mantraStartIndex = match.index; // Start of mantra/slok
// Extract the text before this mantra and add it to blocks
const beforeMantraText = botResponse.substring(lastIndex, mantraStartIndex).trim();
if (beforeMantraText) {
blocks.push({ type: 'text', content: beforeMantraText });
}
// Add the mantra/slok to the blocks
blocks.push({ type: 'mantra', content: mantraText });
// Update the last index to move past the current mantra/slok
lastIndex = mantraRegex.lastIndex;
}
// Add any remaining text after the last mantra/slok
const afterLastMantraText = botResponse.substring(lastIndex).trim();
if (afterLastMantraText) {
blocks.push({ type: 'text', content: afterLastMantraText });
}
// Process the blocks sequentially
processSequentially(blocks, language);
// Store the conversation in MongoDB
requestData.bot_data = botResponse; // Add the bot's response before saving
// Determine backend URL for storing the chat
const baseURL = 'https://thevera-botveradb.hf.space';
const storeChatURL = isRegisteredUser
? `${baseURL}/store_registered_chat/${username}`
: `${baseURL}/store_anonymous_chat`;
// Store chat data
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); // Success message for storing chat
micButton.disabled = false; // Re-enable mic button after response
})
.catch(error => {
alert('Failed to connect to the backend. Please try again later.');
console.error('Error:', error);
micButton.disabled = false; // Re-enable mic button after error
});
}
}
// Manta Block Function
// Recursive function to process each block sequentially
function processSequentially(blocks, language, index = 0) {
if (index >= blocks.length) {
return; // Exit if all blocks are processed
}
const block = blocks[index];
if (block.type === 'text') {
// Show and speak the text block
appendMessage(block.content, 'bot-message');
speakTextSequential(block.content, language, () => {
// Move to the next block once speaking is done
processSequentially(blocks, language, index + 1);
});
} else if (block.type === 'mantra') {
// Show and speak the mantra block
displayMantra(block.content);
speakMantraSequential(block.content, 1, () => {
// Move to the next block once the mantra is spoken
processSequentially(blocks, language, index + 1);
});
}
}
// Function to display the mantra block
function displayMantra(mantraText) {
const mantraBlock = document.createElement('div');
mantraBlock.className = 'mantra-block'; // Add class for styling
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); // Append to chat body
}
// Function to hide the mantra block when there are no mantras
function hideMantraBlock() {
let mantraBlock = document.getElementById('mantra-block');
mantraBlock.style.display = 'none';
}
// Function to decrease the repeat count
function decreaseCount() {
let repeatCountInput = document.getElementById('repeat-count');
let currentValue = parseInt(repeatCountInput.value);
if (currentValue > 1) {
repeatCountInput.value = currentValue - 1;
}
}
// Function to increase the repeat count
function increaseCount() {
let repeatCountInput = document.getElementById('repeat-count');
let currentValue = parseInt(repeatCountInput.value);
repeatCountInput.value = currentValue + 1;
}
// Function to speak the mantra with repeat functionality
function speakMantraSequential(mantraText, repeatCount, callback) {
const utterance = new SpeechSynthesisUtterance(mantraText);
utterance.lang = 'sa-IN'; // Sanskrit
utterance.rate = 0.8; // Slow speech for mantras
utterance.pitch = 1.0; // Natural pitch
utterance.onend = function() {
if (repeatCount > 1) {
repeatCount--;
speechSynthesis.speak(utterance); // Speak again if more repetitions are needed
} else if (callback) {
callback(); // Call the callback when done
}
};
// Handle potential speech synthesis errors
utterance.onerror = function(event) {
console.error('SpeechSynthesisUtterance error:', event.error);
if (callback) {
callback(); // Call callback even if there's an error
}
};
// Cancel any ongoing speech synthesis before speaking
window.speechSynthesis.cancel();
speechSynthesis.speak(utterance);
}
// Function to handle mantra repetition based on user input
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;
}
// Speak the mantra the number of times entered by the user
speakMantraSequential(mantraText, repeatCount, 1);
}
// Mantra Black Function extends
let isFirstMessage = true; // Flag to track if it's the first message
// Function to speak the mantra
function appendMessage(text, className) {
// Remove the default message when the user sends the first message
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);
// Use innerHTML to allow formatted content (e.g., bold, italic, line breaks)
messageElement.innerHTML = text;
chatBody.appendChild(messageElement);
chatBody.scrollTop = chatBody.scrollHeight; // Auto scroll to the latest message
}
// Donate Logic
// Toggle menu visibility
// function toggleMenu() {
// const menuOptions = document.getElementById('menuOptions');
// menuOptions.style.display = menuOptions.style.display === 'none' ? 'block' : 'none';
// }
// Show donate modal
function showDonateModal() {
document.getElementById('donateModal').style.display = 'block';
}
// Close donate modal
function closeDonateModal() {
document.getElementById('donateModal').style.display = 'none';
}
// Copy UPI ID to clipboard
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);
});
}
|