thunderai / index.html
ThunderOwnerx's picture
<!DOCTYPE html><html lang="en"> <head> <meta charset="UTF-8"/> <meta name="viewport" content="width=device-width, initial-scale=1.0"/> <title>Thunder AI</title> <script src="https://cdn.tailwindcss.com"></script> <link href="https://fonts.googleapis.com/css2?family=Google+Sans:wght@400;500;700&display=swap" rel="stylesheet"> <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet"> <script src="https://js.puter.com/v2/"></script> <style> body { font-family: 'Google Sans', Arial, sans-serif; background-color: #121212; color: #ffffff; height: 100vh; margin: 0; display: flex; flex-direction: column; } .chat-container { height: calc(100vh - 110px); overflow-y: auto; } .message-user { background-color: #1e1e1e; border-radius: 18px 18px 0 18px; } .message-ai { background-color: #1f1f1f; border-radius: 18px 18px 18px 0; position: relative; } .input-container { box-shadow: 0 -2px 5px rgba(255, 255, 255, 0.1); } .speak-btn { cursor: pointer; margin-left: 10px; font-size: 18px; background: none; border: none; color: #4285f4; } .voice-button { position: absolute; bottom: 8px; right: -40px; background: #4285f4; color: white; border-radius: 50%; width: 28px; height: 28px; font-size: 18px; display: flex; align-items: center; justify-content: center; } #menuModal { display: none; position: absolute; top: 60px; right: 20px; background: #1e1e1e; box-shadow: 0 2px 10px rgba(255, 255, 255, 0.2); border-radius: 10px; z-index: 100; } #menuModal p { padding: 10px 15px; cursor: pointer; font-size: 14px; color: #4285f4; } #menuModal p:hover { background: #333333; } </style> </head> <body> <header class="bg-gray-800 shadow-sm py-3 px-4 flex items-center justify-between relative"> <div class="flex items-center"> <div class="w-10 h-10 rounded-full bg-gradient-to-r from-blue-500 to-purple-500 flex items-center justify-center text-white font-bold mr-3">T</div> <h1 class="text-xl font-medium">Thunder AI</h1> </div> <div class="flex items-center space-x-2"> <button id="restart-btn" class="text-gray-400 hover:bg-gray-700 p-2 rounded-full"> <span class="material-icons">refresh</span> </button> <button id="menu-btn" class="text-gray-400 hover:bg-gray-700 p-2 rounded-full"> <span class="material-icons">menu</span> </button> </div> <div id="menuModal"> <p onclick="alert('Chat saved!')">Save Chat</p> <p onclick="alert('For any query: moodthunder00@gmail.com')">Help</p> </div> </header> <div id="chatBox" class="chat-container flex-1 overflow-y-auto p-4 space-y-4"> <div class="message-ai p-4 shadow-sm max-w-[80%]"> <p class="text-gray-200">Hello! How can I help you today?</p> </div> </div> <div class="input-container bg-gray-800 p-4"> <div class="max-w-3xl mx-auto flex items-end space-x-2"> <div class="flex-1 bg-gray-700 rounded-full px-4 py-3 flex items-center"> <textarea id="userInput" class="flex-1 bg-transparent outline-none resize-none max-h-32 overflow-y-auto" placeholder="Message Anything...." rows="1"></textarea> <button class="material-icons speak-btn" onclick="readLastMessage()">volume_up</button> <button class="material-icons speak-btn" onclick="startVoiceInput()">mic</button> </div> <button onclick="sendMessage()" class="bg-blue-500 hover:bg-blue-600 text-white rounded-full p-3"> <span class="material-icons">send</span> </button> </div> <div class="text-xs text-gray-400 text-center mt-2 flex justify-center space-x-4"> <a href="https://t.me/Thunderownerx" target="_blank" class="hover:text-blue-600"><span class="material-icons">telegram</span></a> <a href="https://instagram.com/Thunderownerx" target="_blank" class="hover:text-pink-600"><span class="material-icons">photo_camera</span></a> <span>Contact Us <strong>moodthunder00@gmail.com</strong></span> </div> </div> <script> const tools = [ { type: "function", function: { name: "get_weather", description: "Get current weather for a given location", parameters: { type: "object", properties: { location: { type: "string", description: "City name e.g. Paris, London" } }, required: ["location"] }, strict: true } } ]; function getWeather(location) { const data = { 'Paris': '22°C, Partly Cloudy', 'London': '18°C, Rainy', 'Tokyo': '28°C, Clear', 'New York': '25°C, Sunny' }; return data[location] || '20°C, Unknown'; } let lastAIMessage = ""; document.getElementById("restart-btn").addEventListener("click", () => { document.getElementById("chatBox").innerHTML = ""; }); document.getElementById("menu-btn").addEventListener("click", () => { const modal = document.getElementById("menuModal"); modal.style.display = modal.style.display === "block" ? "none" : "block"; }); async function sendMessage(text = null) { const input = document.getElementById("userInput"); const message = text || input.value.trim(); if (!message) return; appendMessage(message, 'user'); input.value = ''; try { const completion = await puter.ai.chat(message, { tools }); let finalResponse; if (completion.message.tool_calls && completion.message.tool_calls.length > 0) { const toolCall = completion.message.tool_calls[0]; if (toolCall.function.name === 'get_weather') { const args = JSON.parse(toolCall.function.arguments); const result = getWeather(args.location); finalResponse = await puter.ai.chat([ { role: "user", content: message }, completion.message, { role: "tool", tool_call_id: toolCall.id, content: result } ]); } } else { finalResponse = completion; } const reply = finalResponse.message?.content || "Sorry, no reply."; appendMessage(reply, 'ai'); lastAIMessage = reply; } catch (err) { appendMessage("API Error: " + err.message, 'ai'); } } function appendMessage(text, sender) { const chatBox = document.getElementById("chatBox"); const msgDiv = document.createElement("div"); msgDiv.className = `flex items-start space-x-3 max-w-3xl mx-auto ${sender === 'user' ? 'justify-end' : ''}`; if (sender === 'user') { msgDiv.innerHTML = ` <div class='message-user p-4 shadow-sm max-w-[80%]'><p class='text-gray-200'>${text}</p></div> <div class='w-10 h-10 rounded-full bg-blue-100 flex items-center justify-center text-blue-500'><span class='material-icons'>person</span></div>`; } else { const safeText = text.replace(/[`\\]/g, '\\$&'); // 🔥 Yeh line important hai! msgDiv.innerHTML = ` <div class='w-10 h-10 rounded-full bg-gray-200 flex items-center justify-center text-gray-600'><span class='material-icons'>smart_toy</span></div> <div class='message-ai p-4 shadow-sm max-w-[80%] relative'> <p class='text-gray-200'>${text}</p> <div class="voice-button" onclick="playVoice(\`${safeText}\`)">🔊</div> </div>`; } chatBox.appendChild(msgDiv); chatBox.scrollTop = chatBox.scrollHeight; } function readLastMessage() { if (lastAIMessage) playVoice(lastAIMessage); else alert("No AI message to read."); } function playVoice(text) { const utter = new SpeechSynthesisUtterance(text); utter.lang = "en-US"; utter.rate = 1; speechSynthesis.speak(utter); } function startVoiceInput() { try { const recognition = new (window.SpeechRecognition || window.webkitSpeechRecognition)(); recognition.lang = "en-US"; recognition.start(); recognition.onresult = (event) => { const transcript = event.results[0][0].transcript; sendMessage(transcript); }; recognition.onerror = (event) => { alert("Voice input error: " + event.error); }; } catch (err) { alert("Your browser doesn't support voice input."); } } </script></body> </html> isme gmail se our phone number se id login hone ka system dalo signing our login ka our chat history save ho same like chat gpt - Initial Deployment
35e7740 verified
Raw
History Blame Contribute Delete
28.6 kB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>Thunder AI</title>
<script src="https://cdn.tailwindcss.com"></script>
<link href="https://fonts.googleapis.com/css2?family=Google+Sans:wght@400;500;700&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<script src="https://js.puter.com/v2/"></script>
<style>
body {
font-family: 'Google Sans', Arial, sans-serif;
background-color: #121212;
color: #ffffff;
height: 100vh;
margin: 0;
display: flex;
flex-direction: column;
}
.chat-container { height: calc(100vh - 110px); overflow-y: auto; }
.message-user { background-color: #1e1e1e; border-radius: 18px 18px 0 18px; }
.message-ai { background-color: #1f1f1f; border-radius: 18px 18px 18px 0; position: relative; }
.input-container { box-shadow: 0 -2px 5px rgba(255, 255, 255, 0.1); }
.speak-btn {
cursor: pointer;
margin-left: 10px;
font-size: 18px;
background: none;
border: none;
color: #4285f4;
}
.voice-button {
position: absolute;
bottom: 8px;
right: -40px;
background: #4285f4;
color: white;
border-radius: 50%;
width: 28px;
height: 28px;
font-size: 18px;
display: flex;
align-items: center;
justify-content: center;
}
#menuModal {
display: none;
position: absolute;
top: 60px;
right: 20px;
background: #1e1e1e;
box-shadow: 0 2px 10px rgba(255, 255, 255, 0.2);
border-radius: 10px;
z-index: 100;
}
#menuModal p {
padding: 10px 15px;
cursor: pointer;
font-size: 14px;
color: #4285f4;
}
#menuModal p:hover {
background: #333333;
}
#authModal {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.8);
z-index: 1000;
justify-content: center;
align-items: center;
}
.auth-container {
background: #1e1e1e;
border-radius: 12px;
width: 90%;
max-width: 400px;
padding: 30px;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);
}
.auth-tabs {
display: flex;
margin-bottom: 20px;
border-bottom: 1px solid #333;
}
.auth-tab {
padding: 10px 20px;
cursor: pointer;
color: #777;
font-weight: 500;
}
.auth-tab.active {
color: #4285f4;
border-bottom: 2px solid #4285f4;
}
.auth-content {
display: none;
}
.auth-content.active {
display: block;
}
.otp-input {
display: flex;
justify-content: space-between;
margin: 20px 0;
}
.otp-input input {
width: 40px;
height: 50px;
text-align: center;
font-size: 18px;
background: #333;
border: none;
border-radius: 8px;
color: white;
}
#chatHistoryModal {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.8);
z-index: 1000;
justify-content: center;
align-items: center;
}
.chat-history-container {
background: #1e1e1e;
border-radius: 12px;
width: 90%;
max-width: 600px;
height: 70%;
padding: 20px;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);
overflow-y: auto;
}
.chat-history-item {
padding: 15px;
margin-bottom: 10px;
background: #252525;
border-radius: 8px;
cursor: pointer;
transition: all 0.2s;
}
.chat-history-item:hover {
background: #333;
}
.chat-history-item h3 {
margin: 0;
font-size: 16px;
color: #fff;
}
.chat-history-item p {
margin: 5px 0 0;
font-size: 14px;
color: #aaa;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
</style>
</head>
<body>
<div id="authModal">
<div class="auth-container">
<div class="auth-tabs">
<div class="auth-tab active" onclick="switchAuthTab('login')">Login</div>
<div class="auth-tab" onclick="switchAuthTab('signup')">Sign Up</div>
</div>
<div id="loginContent" class="auth-content active">
<h2 class="text-xl font-medium mb-6 text-center">Login to Thunder AI</h2>
<div class="mb-4">
<label class="block text-gray-400 mb-2">Email or Phone</label>
<input type="text" id="loginEmail" class="w-full bg-gray-700 rounded-lg px-4 py-3 text-white outline-none">
</div>
<div class="mb-6">
<label class="block text-gray-400 mb-2">Password</label>
<input type="password" id="loginPassword" class="w-full bg-gray-700 rounded-lg px-4 py-3 text-white outline-none">
</div>
<button onclick="login()" class="w-full bg-blue-500 hover:bg-blue-600 text-white rounded-lg py-3 font-medium">Login</button>
<p class="text-center mt-4 text-gray-400">Forgot password? <span class="text-blue-400 cursor-pointer" onclick="switchAuthTab('forgot')">Reset</span></p>
</div>
<div id="signupContent" class="auth-content">
<h2 class="text-xl font-medium mb-6 text-center">Create Account</h2>
<div class="mb-4">
<label class="block text-gray-400 mb-2">Email or Phone</label>
<input type="text" id="signupEmail" class="w-full bg-gray-700 rounded-lg px-4 py-3 text-white outline-none">
</div>
<div class="mb-4">
<label class="block text-gray-400 mb-2">Password</label>
<input type="password" id="signupPassword" class="w-full bg-gray-700 rounded-lg px-4 py-3 text-white outline-none">
</div>
<div class="mb-6">
<label class="block text-gray-400 mb-2">Confirm Password</label>
<input type="password" id="signupConfirmPassword" class="w-full bg-gray-700 rounded-lg px-4 py-3 text-white outline-none">
</div>
<button onclick="signup()" class="w-full bg-blue-500 hover:bg-blue-600 text-white rounded-lg py-3 font-medium">Sign Up</button>
</div>
<div id="forgotContent" class="auth-content">
<h2 class="text-xl font-medium mb-6 text-center">Reset Password</h2>
<div class="mb-4">
<label class="block text-gray-400 mb-2">Email or Phone</label>
<input type="text" id="forgotEmail" class="w-full bg-gray-700 rounded-lg px-4 py-3 text-white outline-none">
</div>
<button onclick="sendResetCode()" class="w-full bg-blue-500 hover:bg-blue-600 text-white rounded-lg py-3 font-medium">Send Reset Code</button>
<p class="text-center mt-4 text-gray-400">Remember password? <span class="text-blue-400 cursor-pointer" onclick="switchAuthTab('login')">Login</span></p>
</div>
<div id="otpContent" class="auth-content">
<h2 class="text-xl font-medium mb-6 text-center">Verify OTP</h2>
<p class="text-gray-400 mb-4 text-center">We've sent a 6-digit code to your email/phone</p>
<div class="otp-input">
<input type="text" maxlength="1" oninput="moveToNext(this, 1)">
<input type="text" maxlength="1" oninput="moveToNext(this, 2)">
<input type="text" maxlength="1" oninput="moveToNext(this, 3)">
<input type="text" maxlength="1" oninput="moveToNext(this, 4)">
<input type="text" maxlength="1" oninput="moveToNext(this, 5)">
<input type="text" maxlength="1" oninput="moveToNext(this, 6)">
</div>
<button onclick="verifyOTP()" class="w-full bg-blue-500 hover:bg-blue-600 text-white rounded-lg py-3 font-medium">Verify</button>
<p class="text-center mt-4 text-gray-400">Didn't receive code? <span class="text-blue-400 cursor-pointer" onclick="resendOTP()">Resend</span></p>
</div>
</div>
</div>
<div id="chatHistoryModal">
<div class="chat-history-container">
<div class="flex justify-between items-center mb-6">
<h2 class="text-xl font-medium">Chat History</h2>
<span class="material-icons cursor-pointer" onclick="closeChatHistory()">close</span>
</div>
<div id="chatHistoryList">
<!-- Chat history items will be added here -->
</div>
</div>
</div>
<header class="bg-gray-800 shadow-sm py-3 px-4 flex items-center justify-between relative">
<div class="flex items-center">
<div class="w-10 h-10 rounded-full bg-gradient-to-r from-blue-500 to-purple-500 flex items-center justify-center text-white font-bold mr-3">T</div>
<h1 class="text-xl font-medium">Thunder AI</h1>
</div>
<div class="flex items-center space-x-2">
<button id="history-btn" class="text-gray-400 hover:bg-gray-700 p-2 rounded-full">
<span class="material-icons">history</span>
</button>
<button id="restart-btn" class="text-gray-400 hover:bg-gray-700 p-2 rounded-full">
<span class="material-icons">refresh</span>
</button>
<button id="menu-btn" class="text-gray-400 hover:bg-gray-700 p-2 rounded-full">
<span class="material-icons">menu</span>
</button>
<button id="user-btn" class="text-gray-400 hover:bg-gray-700 p-2 rounded-full">
<span class="material-icons">account_circle</span>
</button>
</div>
<div id="menuModal">
<p onclick="saveCurrentChat()">Save Chat</p>
<p onclick="showChatHistory()">Chat History</p>
<p onclick="alert('For any query: moodthunder00@gmail.com')">Help</p>
<p onclick="logout()">Logout</p>
</div>
</header>
<div id="chatBox" class="chat-container flex-1 overflow-y-auto p-4 space-y-4">
<div class="message-ai p-4 shadow-sm max-w-[80%]">
<p class="text-gray-200">Hello! Please login to start chatting.</p>
</div>
</div>
<div class="input-container bg-gray-800 p-4">
<div class="max-w-3xl mx-auto flex items-end space-x-2">
<div class="flex-1 bg-gray-700 rounded-full px-4 py-3 flex items-center">
<textarea id="userInput" class="flex-1 bg-transparent outline-none resize-none max-h-32 overflow-y-auto" placeholder="Please login to chat..." rows="1" disabled></textarea>
<button class="material-icons speak-btn" onclick="readLastMessage()">volume_up</button>
<button class="material-icons speak-btn" onclick="startVoiceInput()">mic</button>
</div>
<button onclick="sendMessage()" class="bg-blue-500 hover:bg-blue-600 text-white rounded-full p-3">
<span class="material-icons">send</span>
</button>
</div>
<div class="text-xs text-gray-400 text-center mt-2 flex justify-center space-x-4">
<a href="https://t.me/Thunderownerx" target="_blank" class="hover:text-blue-600"><span class="material-icons">telegram</span></a>
<a href="https://instagram.com/Thunderownerx" target="_blank" class="hover:text-pink-600"><span class="material-icons">photo_camera</span></a>
<span>Contact Us <strong>moodthunder00@gmail.com</strong></span>
</div>
</div>
<script>
// Authentication state
let currentUser = null;
let isLoggedIn = false;
let currentChatId = null;
let chatHistory = {};
// Initialize with demo data if localStorage is empty
if (!localStorage.getItem('thunderAIUsers')) {
localStorage.setItem('thunderAIUsers', JSON.stringify({
'user@example.com': {
password: 'password123',
phone: '+1234567890',
chats: {}
}
}));
}
// Check if user is already logged in
if (localStorage.getItem('thunderAICurrentUser')) {
currentUser = localStorage.getItem('thunderAICurrentUser');
isLoggedIn = true;
loadUserChats();
document.getElementById('userInput').placeholder = "Message Anything....";
document.getElementById('userInput').disabled = false;
} else {
document.getElementById('authModal').style.display = 'flex';
}
const tools = [
{
type: "function",
function: {
name: "get_weather",
description: "Get current weather for a given location",
parameters: {
type: "object",
properties: {
location: {
type: "string",
description: "City name e.g. Paris, London"
}
},
required: ["location"]
},
strict: true
}
}
];
function getWeather(location) {
const data = {
'Paris': '22°C, Partly Cloudy',
'London': '18°C, Rainy',
'Tokyo': '28°C, Clear',
'New York': '25°C, Sunny'
};
return data[location] || '20°C, Unknown';
}
let lastAIMessage = "";
document.getElementById("restart-btn").addEventListener("click", () => {
if (!isLoggedIn) {
alert("Please login to start a new chat");
return;
}
document.getElementById("chatBox").innerHTML = `
<div class="message-ai p-4 shadow-sm max-w-[80%]">
<p class="text-gray-200">Hello! How can I help you today?</p>
</div>
`;
currentChatId = 'chat_' + Date.now();
saveCurrentChat();
});
document.getElementById("menu-btn").addEventListener("click", () => {
const modal = document.getElementById("menuModal");
modal.style.display = modal.style.display === "block" ? "none" : "block";
});
document.getElementById("history-btn").addEventListener("click", () => {
if (!isLoggedIn) {
alert("Please login to view chat history");
return;
}
showChatHistory();
});
document.getElementById("user-btn").addEventListener("click", () => {
if (isLoggedIn) {
const modal = document.getElementById("menuModal");
modal.style.display = modal.style.display === "block" ? "none" : "block";
} else {
document.getElementById("authModal").style.display = 'flex';
}
});
async function sendMessage(text = null) {
if (!isLoggedIn) {
alert("Please login to chat");
return;
}
const input = document.getElementById("userInput");
const message = text || input.value.trim();
if (!message) return;
appendMessage(message, 'user');
input.value = '';
// Show loading indicator
const loadingDiv = document.createElement("div");
loadingDiv.className = "flex items-start space-x-3 max-w-3xl mx-auto";
loadingDiv.innerHTML = `
<div class='w-10 h-10 rounded-full bg-gray-200 flex items-center justify-center text-gray-600'><span class='material-icons'>smart_toy</span></div>
<div class='message-ai p-4 shadow-sm max-w-[80%] relative'>
<div class="flex space-x-2">
<div class="w-2 h-2 rounded-full bg-gray-400 animate-bounce"></div>
<div class="w-2 h-2 rounded-full bg-gray-400 animate-bounce" style="animation-delay: 0.2s"></div>
<div class="w-2 h-2 rounded-full bg-gray-400 animate-bounce" style="animation-delay: 0.4s"></div>
</div>
</div>
`;
document.getElementById("chatBox").appendChild(loadingDiv);
document.getElementById("chatBox").scrollTop = document.getElementById("chatBox").scrollHeight;
try {
const completion = await puter.ai.chat(message, { tools });
let finalResponse;
if (completion.message.tool_calls && completion.message.tool_calls.length > 0) {
const toolCall = completion.message.tool_calls[0];
if (toolCall.function.name === 'get_weather') {
const args = JSON.parse(toolCall.function.arguments);
const result = getWeather(args.location);
finalResponse = await puter.ai.chat([
{ role: "user", content: message },
completion.message,
{ role: "tool", tool_call_id: toolCall.id, content: result }
]);
}
} else {
finalResponse = completion;
}
// Remove loading indicator
document.getElementById("chatBox").removeChild(loadingDiv);
const reply = finalResponse.message?.content || "Sorry, no reply.";
appendMessage(reply, 'ai');
lastAIMessage = reply;
// Save the chat after each message
saveCurrentChat();
} catch (err) {
// Remove loading indicator
document.getElementById("chatBox").removeChild(loadingDiv);
appendMessage("API Error: " + err.message, 'ai');
}
}
function appendMessage(text, sender) {
const chatBox = document.getElementById("chatBox");
const msgDiv = document.createElement("div");
msgDiv.className = `flex items-start space-x-3 max-w-3xl mx-auto ${sender === 'user' ? 'justify-end' : ''}`;
if (sender === 'user') {
msgDiv.innerHTML = `
<div class='message-user p-4 shadow-sm max-w-[80%]'><p class='text-gray-200'>${text}</p></div>
<div class='w-10 h-10 rounded-full bg-blue-100 flex items-center justify-center text-blue-500'><span class='material-icons'>person</span></div>`;
} else {
const safeText = text.replace(/[`\\]/g, '\\$&');
msgDiv.innerHTML = `
<div class='w-10 h-10 rounded-full bg-gray-200 flex items-center justify-center text-gray-600'><span class='material-icons'>smart_toy</span></div>
<div class='message-ai p-4 shadow-sm max-w-[80%] relative'>
<p class='text-gray-200'>${text}</p>
<div class="voice-button" onclick="playVoice(\`${safeText}\`)">🔊</div>
</div>`;
}
chatBox.appendChild(msgDiv);
chatBox.scrollTop = chatBox.scrollHeight;
}
function readLastMessage() {
if (lastAIMessage) playVoice(lastAIMessage);
else alert("No AI message to read.");
}
function playVoice(text) {
const utter = new SpeechSynthesisUtterance(text);
utter.lang = "en-US";
utter.rate = 1;
speechSynthesis.speak(utter);
}
function startVoiceInput() {
if (!isLoggedIn) {
alert("Please login to use voice input");
return;
}
try {
const recognition = new (window.SpeechRecognition || window.webkitSpeechRecognition)();
recognition.lang = "en-US";
recognition.start();
recognition.onresult = (event) => {
const transcript = event.results[0][0].transcript;
sendMessage(transcript);
};
recognition.onerror = (event) => {
alert("Voice input error: " + event.error);
};
} catch (err) {
alert("Your browser doesn't support voice input.");
}
}
// Authentication functions
function switchAuthTab(tab) {
document.querySelectorAll('.auth-tab').forEach(t => t.classList.remove('active'));
document.querySelectorAll('.auth-content').forEach(c => c.classList.remove('active'));
if (tab === 'login') {
document.querySelector('.auth-tab:nth-child(1)').classList.add('active');
document.getElementById('loginContent').classList.add('active');
} else if (tab === 'signup') {
document.querySelector('.auth-tab:nth-child(2)').classList.add('active');
document.getElementById('signupContent').classList.add('active');
} else if (tab === 'forgot') {
document.getElementById('forgotContent').classList.add('active');
} else if (tab === 'otp') {
document.getElementById('otpContent').classList.add('active');
}
}
function login() {
const email = document.getElementById('loginEmail').value.trim();
const password = document.getElementById('loginPassword').value;
if (!email || !password) {
alert('Please enter both email/phone and password');
return;
}
const users = JSON.parse(localStorage.getItem('thunderAIUsers'));
let userFound = false;
// Check email or phone login
for (const key in users) {
if (key === email || users[key].phone === email) {
if (users[key].password === password) {
userFound = true;
currentUser = key;
break;
}
}
}
if (userFound) {
isLoggedIn = true;
localStorage.setItem('thunderAICurrentUser', currentUser);
document.getElementById('authModal').style.display = 'none';
document.getElementById('userInput').placeholder = "Message Anything....";
document.getElementById('userInput').disabled = false;
// Start a new chat session
document.getElementById("chatBox").innerHTML = `
<div class="message-ai p-4 shadow-sm max-w-[80%]">
<p class="text-gray-200">Hello! How can I help you today?</p>
</div>
`;
currentChatId = 'chat_' + Date.now();
loadUserChats();
} else {
alert('Invalid email/phone or password');
}
}
function signup() {
const email = document.getElementById('signupEmail').value.trim();
const password = document.getElementById('signupPassword').value;
const confirmPassword = document.getElementById('signupConfirmPassword').value;
if (!email) {
alert('Please enter your email or phone number');
return;
}
if (!password || password.length < 6) {
alert('Password must be at least 6 characters');
return;
}
if (password !== confirmPassword) {
alert('Passwords do not match');
return;
}
const users = JSON.parse(localStorage.getItem('thunderAIUsers'));
// Check if email is already registered
if (users[email]) {
alert('This email/phone is already registered');
return;
}
// Add new user
users[email] = {
password: password,
phone: email.includes('@') ? '' : email, // Store phone if it's not email
chats: {}
};
localStorage.setItem('thunderAIUsers', JSON.stringify(users));
alert('Account created successfully! Please login.');
switchAuthTab('login');
document.getElementById('loginEmail').value = email;
}
function sendResetCode() {
const email = document.getElementById('forgotEmail').value.trim();
if (!email) {
alert('Please enter your email or phone number');
return;
}
// In a real app, you would send an OTP to the user's email/phone
// Here we'll just simulate it
alert(`OTP sent to ${email} (simulated)`);
switchAuthTab('otp');
}
function resendOTP() {
alert('New OTP sent (simulated)');
}
function verifyOTP() {
// In a real app, you would verify the OTP
// Here we'll just simulate successful verification
alert('Password reset successful! Please login with your new password.');
switchAuthTab('login');
}
function moveToNext(input, next) {
if (input.value.length === 1) {
if (next <= 6) {
const nextInput = input.parentElement.querySelector(`input:nth-child(${next})`);
if (nextInput) nextInput.focus();
}
}
}
function logout() {
isLoggedIn = false;
currentUser = null;
localStorage.removeItem('thunderAICurrentUser');
document.getElementById('menuModal').style.display = 'none';
document.getElementById('authModal').style.display = 'flex';
document.getElementById('userInput').placeholder = "Please login to chat...";
document.getElementById('userInput').disabled = true;
document.getElementById("chatBox").innerHTML = `
<div class="message-ai p-4 shadow-sm max-w-[80%]">
<p class="text-gray-200">Hello! Please login to start chatting.</p>
</div>
`;
}
// Chat history functions
function saveCurrentChat() {
if (!isLoggedIn || !currentChatId) return;
const chatBox = document.getElementById('chatBox');
const messages = [];
// Get all messages from chat
chatBox.querySelectorAll('.flex.items-start').forEach(msgDiv => {
const isUser = msgDiv.classList.contains('justify-end');
const messageText = msgDiv.querySelector('p')?.textContent || '';
if (messageText) {
messages.push({
sender: isUser ? 'user' : 'ai',
text: messageText
});
}
});
// Save to user's chat history
const users = JSON.parse(localStorage.getItem('thunderAIUsers'));
if (!users[currentUser].chats) users[currentUser].chats = {};
users[currentUser].chats[currentChatId] = {
id: currentChatId,
title: messages.length > 0 ? messages[0].text.substring(0, 30) : 'New Chat',
lastMessage: messages.length > 0 ? messages[messages.length-1].text.substring(0, 50) : '',
timestamp: Date.now(),
messages: messages
};
localStorage.setItem('thunderAIUsers', JSON.stringify(users));
loadUserChats();
}
function loadUserChats() {
if (!isLoggedIn) return;
const users = JSON.parse(localStorage.getItem('thunderAIUsers'));
chatHistory = users[currentUser].chats || {};
// If no current chat, create a new one
if (!currentChatId || !chatHistory[currentChatId]) {
currentChatId = 'chat_' + Date.now();
chatHistory[currentChatId] = {
id: currentChatId,
title: 'New Chat',
lastMessage: '',
timestamp: Date.now(),
messages: []
};
saveCurrentChat();
}
}
function showChatHistory() {
if (!isLoggedIn) return;
const chatHistoryList = document.getElementById('chatHistoryList');
chatHistoryList.innerHTML = '';
const users = JSON.parse(localStorage.getItem('thunderAIUsers'));
const chats = users[currentUser].chats;
// Sort chats by timestamp (newest first)
const sortedChats = Object.values(chats).sort((a, b) => b.timestamp - a.timestamp);
sortedChats.forEach(chat => {
const chatItem = document.createElement('div');
chatItem.className = 'chat-history-item';
chatItem.innerHTML = `
<h3>${chat.title}</h3>
<p>${chat.lastMessage || 'No messages yet'}</p>
`;
chatItem.onclick = () => loadChat(chat.id);
chatHistoryList.appendChild(chatItem);
});
document.getElementById('chatHistoryModal').style.display = 'flex';
}
function closeChatHistory() {
document.getElementById('chatHistoryModal').style.display = 'none';
}
function loadChat(chatId) {
if (!isLoggedIn) return;
const users = JSON.parse(localStorage.getItem('thunderAIUsers'));
const chat = users[currentUser].chats[chatId];
if (!chat) return;
currentChatId = chatId;
// Clear current chat
const chatBox = document.getElementById('chatBox');
chatBox.innerHTML = '';
// Load messages from chat history
chat.messages.forEach(msg => {
appendMessage(msg.text, msg.sender);
});
closeChatHistory();
}
// Initialize a new chat if none exists
if (isLoggedIn && (!currentChatId || !chatHistory[currentChatId])) {
currentChatId = 'chat_' + Date.now();
saveCurrentChat();
}
</script>
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=ThunderOwnerx/thunderai" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>