Hpt / script.js
Oss11's picture
Make ai assistant like chatgpt and use API keys and users can add your own API key
d962c58 verified
// Shared JavaScript across all pages
class ChatApp {
constructor() {
this.apiKey = localStorage.getItem('openai-api-key') || '';
this.messages = [];
this.init();
}
init() {
this.bindEvents();
this.loadApiKey();
this.updateApiKeyDisplay();
}
bindEvents() {
document.getElementById('send-button').addEventListener('click', () => this.sendMessage());
document.getElementById('message-input').addEventListener('keypress', (e) => {
if (e.key === 'Enter') this.sendMessage();
});
document.getElementById('save-api-key').addEventListener('click', () => this.saveApiKey());
}
loadApiKey() {
const savedKey = localStorage.getItem('openai-api-key');
if (savedKey) {
this.apiKey = savedKey;
document.getElementById('api-key-input').value = savedKey;
}
}
saveApiKey() {
const keyInput = document.getElementById('api-key-input');
if (keyInput.value.trim()) {
this.apiKey = keyInput.value.trim();
localStorage.setItem('openai-api-key', this.apiKey);
this.updateApiKeyDisplay();
this.showNotification('API key saved successfully!', 'success');
} else {
this.showNotification('Please enter a valid API key', 'error');
}
}
updateApiKeyDisplay() {
const keyInput = document.getElementById('api-key-input');
if (this.apiKey) {
keyInput.placeholder = 'API key saved';
} else {
keyInput.placeholder = 'Enter your OpenAI API key';
}
}
async sendMessage() {
const input = document.getElementById('message-input');
const message = input.value.trim();
if (!message) return;
if (!this.apiKey) {
this.showNotification('Please enter your OpenAI API key first', 'error');
return;
}
// Add user message to UI
this.addMessage(message, 'user');
input.value = '';
// Show typing indicator
const typingIndicator = this.addTypingIndicator();
try {
const response = await this.callOpenAI(message);
// Remove typing indicator
typingIndicator.remove();
// Add assistant response
this.addMessage(response, 'assistant');
} catch (error) {
// Remove typing indicator
typingIndicator.remove();
this.addMessage('Sorry, I encountered an error. Please try again.', 'assistant');
console.error('Error:', error);
}
}
addMessage(content, sender) {
const messagesContainer = document.getElementById('messages');
const messageDiv = document.createElement('div');
messageDiv.className = `message ${sender}-message rounded-lg p-4 max-w-[80%] ${sender === 'user' ? 'ml-auto' : ''}`;
if (sender === 'user') {
messageDiv.innerHTML = `
<div class="font-bold text-blue-200 mb-1">You</div>
<div>${content}</div>
`;
} else {
messageDiv.innerHTML = `
<div class="font-bold text-blue-400 mb-1">Assistant</div>
<div>${content}</div>
`;
}
messagesContainer.appendChild(messageDiv);
messagesContainer.scrollTop = messagesContainer.scrollHeight;
return messageDiv;
}
addTypingIndicator() {
const messagesContainer = document.getElementById('messages');
const typingDiv = document.createElement('div');
typingDiv.className = 'message assistant-message rounded-lg p-4';
typingDiv.innerHTML = `
<div class="font-bold text-blue-400 mb-1">Assistant</div>
<div class="flex space-x-1">
<div class="w-2 h-2 bg-blue-400 rounded-full animate-bounce"></div>
<div class="w-2 h-2 bg-blue-400 rounded-full animate-bounce" style="animation-delay: 0.2s"></div>
<div class="w-2 h-2 bg-blue-400 rounded-full animate-bounce" style="animation-delay: 0.4s"></div>
</div>
`;
messagesContainer.appendChild(typingDiv);
messagesContainer.scrollTop = messagesContainer.scrollHeight;
return typingDiv;
}
async callOpenAI(message) {
const response = await fetch('https://api.openai.com/v1/chat/completions', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${this.apiKey}`
},
body: JSON.stringify({
model: 'gpt-3.5-turbo',
messages: [
{ role: 'system', content: 'You are a helpful assistant.' },
{ role: 'user', content: message }
],
temperature: 0.7
})
});
if (!response.ok) {
if (response.status === 401) {
throw new Error('Invalid API key. Please check your API key and try again.');
} else if (response.status === 429) {
throw new Error('Rate limit exceeded. Please wait before sending another request.');
} else {
throw new Error(`API request failed with status ${response.status}`);
}
}
const data = await response.json();
return data.choices[0].message.content;
}
showNotification(message, type) {
// Remove existing notifications
const existing = document.querySelector('.notification');
if (existing) existing.remove();
const notification = document.createElement('div');
notification.className = `notification fixed top-4 right-4 px-6 py-4 rounded-lg shadow-lg z-50 ${
type === 'success' ? 'bg-green-600' : 'bg-red-600'
} text-white`;
notification.textContent = message;
document.body.appendChild(notification);
setTimeout(() => {
notification.remove();
}, 3000);
}
}
// Initialize the app when DOM is loaded
document.addEventListener('DOMContentLoaded', () => {
window.chatApp = new ChatApp();
});