forked from omroy07/AgriTech
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathchat.js
More file actions
174 lines (148 loc) · 6.32 KB
/
chat.js
File metadata and controls
174 lines (148 loc) · 6.32 KB
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
document.addEventListener('DOMContentLoaded', () => {
const chatWindow = document.getElementById('chat-window');
const chatForm = document.getElementById('chat-form');
const chatInput = document.getElementById('chat-input');
const sendBtn = document.getElementById('send-button');
// Initialize JSON-based chatbot
const jsonChatbot = new JSONChatbot();
// Gemini AI fallback configuration
const API_KEY = 'GEMINI_API_KEY'; // get api key from https://ai.google.dev/
const API_URL = `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash-exp:generateContent?key=${API_KEY}`;
const USE_AI_FALLBACK = false; // Set to true if you want to use Gemini AI as fallback
const systemMsg = {
role: "user",
parts: [{ text: "You are an expert agricultural assistant named AgriBot. Provide detailed, accurate and helpful responses about farming, crops, weather impact, soil health, pest control, and sustainable agriculture practices. Format your answers with clear concise minimal paragraphs. If asked about something outside agriculture except greetings, politely decline and refocus on farming topics." }]
};
let history = [systemMsg];
// HTML escaping function to prevent XSS
function escapeHtml(text) {
return text
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''');
}
// Secure message rendering function
function displayMessage(messageContent, sender) {
const messageElement = document.createElement('div');
messageElement.className = `message ${sender}`;
const time = new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
const name = sender === 'user' ? 'You' : 'AgriBot';
// Create message header
const headerDiv = document.createElement('div');
headerDiv.className = 'message-header';
const icon = document.createElement('i');
icon.className = `fas fa-${sender === 'user' ? 'user' : 'robot'}`;
headerDiv.appendChild(icon);
headerDiv.appendChild(document.createTextNode(` ${name}`));
// Create message text (safely formatted)
const textDiv = document.createElement('div');
textDiv.className = 'message-text';
textDiv.innerHTML = format(escapeHtml(messageContent)); // Safe formatting after escaping
// Create timestamp
const timeDiv = document.createElement('div');
timeDiv.className = 'timestamp';
timeDiv.textContent = time;
// Assemble message
messageElement.appendChild(headerDiv);
messageElement.appendChild(textDiv);
messageElement.appendChild(timeDiv);
chatWindow.appendChild(messageElement);
chatWindow.scrollTop = chatWindow.scrollHeight;
}
document.addEventListener('click', (e) => {
if (e.target.classList.contains('suggestion')) {
chatInput.value = e.target.textContent;
chatForm.dispatchEvent(new Event('submit'));
}
});
chatForm.addEventListener('submit', async (e) => {
e.preventDefault();
const input = chatInput.value.trim();
if (!input) return;
// Input validation - limit message length
if (input.length > 1000) {
alert('Message too long. Please keep messages under 1000 characters.');
return;
}
displayMessage(input, 'user');
chatInput.value = '';
const typing = showTyping();
toggleInput(true);
try {
// Try JSON chatbot first
let reply = await jsonChatbot.getResponse(input);
// If JSON chatbot returns a fallback and AI is enabled, try Gemini AI
if (USE_AI_FALLBACK && reply.includes("Sorry, I didn't understand")) {
console.log('Falling back to Gemini AI...');
history.push({ role: "user", parts: [{ text: input }] });
const res = await fetch(API_URL, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
contents: history,
generationConfig: {
temperature: 0.7,
maxOutputTokens: 1000,
topP: 0.8,
topK: 40
}
})
});
if (res.ok) {
const data = await res.json();
const aiReply = data?.candidates?.[0]?.content?.parts?.[0]?.text;
if (aiReply) {
reply = aiReply;
history.push({ role: "model", parts: [{ text: reply }] });
}
}
}
// Add smooth animation delay for more natural feel
setTimeout(() => {
displayMessage(reply, 'bot');
}, Math.random() * 800 + 400); // Random delay between 400-1200ms
} catch (error) {
console.error('Chatbot Error:', error);
setTimeout(() => {
displayMessage("⚠️ I'm having trouble right now. Please try asking your question again!", 'bot');
}, 500);
} finally {
setTimeout(() => {
typing.remove();
toggleInput(false);
}, Math.random() * 800 + 600); // Remove typing indicator after response
}
});
const addMessage = (who, txt) => {
displayMessage(txt, who);
};
const showTyping = () => {
const typing = document.createElement('div');
typing.className = 'typing-indicator';
typing.innerHTML = `<div>AgriBot is typing</div><span></span><span></span><span></span>`;
chatWindow.appendChild(typing);
chatWindow.scrollTop = chatWindow.scrollHeight;
return typing;
};
const toggleInput = (disable) => {
sendBtn.disabled = disable;
chatInput.disabled = disable;
if (!disable) chatInput.focus();
};
const format = (txt) =>
txt.replace(/\n/g, '<br>')
.replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>')
.replace(/\*(.*?)\*/g, '<em>$1</em>')
.replace(/`(.*?)`/g, '<code>$1</code>');
// Initialize chatbot with welcome message
setTimeout(async () => {
await jsonChatbot.getResponse('hello').then(welcomeMsg => {
displayMessage(welcomeMsg, 'bot');
}).catch(() => {
displayMessage('Hello! 🌱 I\'m AgriBot, your agricultural assistant. I can help you with farming questions, crop management, soil health, pest control, and more. How can I assist you today?', 'bot');
});
}, 500);
chatInput.focus();
});