stakmodsco commited on
Commit
1a36166
·
verified ·
1 Parent(s): fc4e339

make leadmind ai fully functional by creatng its backend - Follow Up Deployment

Browse files
Files changed (5) hide show
  1. .env.example +5 -0
  2. backend.html +248 -0
  3. index.html +58 -18
  4. package.json +25 -0
  5. server.js +207 -0
.env.example ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ ```plaintext
2
+ MONGODB_URI=mongodb://localhost:27017/leadmind
3
+ JWT_SECRET=your_jwt_secret_key_here
4
+ PORT=5000
5
+ ```
backend.html ADDED
@@ -0,0 +1,248 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>LeadMind AI - Backend Architecture</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
9
+ </head>
10
+ <body class="bg-gray-50 font-sans">
11
+ <div class="min-h-screen flex">
12
+ <!-- Sidebar -->
13
+ <aside class="w-64 bg-white shadow-md hidden md:block">
14
+ <nav class="p-4">
15
+ <div class="mb-8">
16
+ <h2 class="text-gray-500 uppercase text-xs font-semibold tracking-wider mb-4">Navigation</h2>
17
+ <ul class="space-y-2">
18
+ <li>
19
+ <a href="index.html" class="flex items-center space-x-2 text-gray-600 hover:text-purple-600 hover:bg-purple-50 rounded-lg px-3 py-2">
20
+ <i class="fas fa-home"></i>
21
+ <span>Dashboard</span>
22
+ </a>
23
+ </li>
24
+ <li>
25
+ <a href="backend.html" class="flex items-center space-x-2 text-purple-600 bg-purple-50 rounded-lg px-3 py-2">
26
+ <i class="fas fa-server"></i>
27
+ <span>Backend</span>
28
+ </a>
29
+ </li>
30
+ </ul>
31
+ </div>
32
+ </nav>
33
+ </aside>
34
+
35
+ <!-- Main Content -->
36
+ <main class="flex-1 p-8 overflow-auto">
37
+ <div class="max-w-6xl mx-auto">
38
+ <h1 class="text-3xl font-bold text-gray-800 mb-6">Backend Architecture</h1>
39
+
40
+ <!-- Architecture Diagram -->
41
+ <div class="bg-white rounded-xl shadow-md p-6 mb-8">
42
+ <h2 class="text-xl font-bold mb-4">System Architecture</h2>
43
+ <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
44
+ <!-- Client Layer -->
45
+ <div class="bg-purple-50 p-4 rounded-lg border border-purple-200">
46
+ <div class="flex items-center mb-2">
47
+ <i class="fas fa-laptop-code text-purple-600 mr-2"></i>
48
+ <h3 class="font-semibold">Client Layer</h3>
49
+ </div>
50
+ <ul class="text-sm space-y-1">
51
+ <li>Web Dashboard</li>
52
+ <li>Mobile Apps</li>
53
+ <li>Third-party Apps</li>
54
+ </ul>
55
+ </div>
56
+
57
+ <!-- API Layer -->
58
+ <div class="bg-blue-50 p-4 rounded-lg border border-blue-200">
59
+ <div class="flex items-center mb-2">
60
+ <i class="fas fa-network-wired text-blue-600 mr-2"></i>
61
+ <h3 class="font-semibold">API Layer</h3>
62
+ </div>
63
+ <ul class="text-sm space-y-1">
64
+ <li>REST API</li>
65
+ <li>GraphQL</li>
66
+ <li>WebSockets</li>
67
+ </ul>
68
+ </div>
69
+
70
+ <!-- Service Layer -->
71
+ <div class="bg-green-50 p-4 rounded-lg border border-green-200">
72
+ <div class="flex items-center mb-2">
73
+ <i class="fas fa-cogs text-green-600 mr-2"></i>
74
+ <h3 class="font-semibold">Service Layer</h3>
75
+ </div>
76
+ <ul class="text-sm space-y-1">
77
+ <li>AI Processing</li>
78
+ <li>Auth Service</li>
79
+ <li>Analytics</li>
80
+ </ul>
81
+ </div>
82
+
83
+ <!-- Data Layer -->
84
+ <div class="bg-yellow-50 p-4 rounded-lg border border-yellow-200">
85
+ <div class="flex items-center mb-2">
86
+ <i class="fas fa-database text-yellow-600 mr-2"></i>
87
+ <h3 class="font-semibold">Data Layer</h3>
88
+ </div>
89
+ <ul class="text-sm space-y-1">
90
+ <li>PostgreSQL</li>
91
+ <li>MongoDB</li>
92
+ <li>Redis</li>
93
+ </ul>
94
+ </div>
95
+ </div>
96
+ </div>
97
+
98
+ <!-- Technology Stack -->
99
+ <div class="bg-white rounded-xl shadow-md p-6 mb-8">
100
+ <h2 class="text-xl font-bold mb-4">Technology Stack</h2>
101
+ <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
102
+ <!-- Languages/Frameworks -->
103
+ <div class="border rounded-lg p-4">
104
+ <div class="flex items-center mb-3">
105
+ <i class="fas fa-code text-purple-600 mr-2"></i>
106
+ <h3 class="font-semibold">Languages/Frameworks</h3>
107
+ </div>
108
+ <div class="space-y-2">
109
+ <div class="bg-gray-50 p-2 rounded flex items-center">
110
+ <img src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/nodejs/nodejs-original.svg" class="w-5 h-5 mr-2" />
111
+ <span>Node.js (Express)</span>
112
+ </div>
113
+ <div class="bg-gray-50 p-2 rounded flex items-center">
114
+ <img src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/python/python-original.svg" class="w-5 h-5 mr-2" />
115
+ <span>Python (FastAPI)</span>
116
+ </div>
117
+ </div>
118
+ </div>
119
+
120
+ <!-- Databases -->
121
+ <div class="border rounded-lg p-4">
122
+ <div class="flex items-center mb-3">
123
+ <i class="fas fa-database text-blue-600 mr-2"></i>
124
+ <h3 class="font-semibold">Databases</h3>
125
+ </div>
126
+ <div class="space-y-2">
127
+ <div class="bg-gray-50 p-2 rounded flex items-center">
128
+ <img src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/postgresql/postgresql-original.svg" class="w-5 h-5 mr-2" />
129
+ <span>PostgreSQL</span>
130
+ </div>
131
+ <div class="bg-gray-50 p-2 rounded flex items-center">
132
+ <img src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/mongodb/mongodb-original.svg" class="w-5 h-5 mr-2" />
133
+ <span>MongoDB</span>
134
+ </div>
135
+ <div class="bg-gray-50 p-2 rounded flex items-center">
136
+ <img src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/redis/redis-original.svg" class="w-5 h-5 mr-2" />
137
+ <span>Redis</span>
138
+ </div>
139
+ </div>
140
+ </div>
141
+
142
+ <!-- Infrastructure -->
143
+ <div class="border rounded-lg p-4">
144
+ <div class="flex items-center mb-3">
145
+ <i class="fas fa-cloud text-green-600 mr-2"></i>
146
+ <h3 class="font-semibold">Infrastructure</h3>
147
+ </div>
148
+ <div class="space-y-2">
149
+ <div class="bg-gray-50 p-2 rounded flex items-center">
150
+ <img src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/docker/docker-original.svg" class="w-5 h-5 mr-2" />
151
+ <span>Docker</span>
152
+ </div>
153
+ <div class="bg-gray-50 p-2 rounded flex items-center">
154
+ <img src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/kubernetes/kubernetes-plain.svg" class="w-5 h-5 mr-2" />
155
+ <span>Kubernetes</span>
156
+ </div>
157
+ <div class="bg-gray-50 p-2 rounded flex items-center">
158
+ <img src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/amazonwebservices/amazonwebservices-original.svg" class="w-5 h-5 mr-2" />
159
+ <span>AWS</span>
160
+ </div>
161
+ </div>
162
+ </div>
163
+ </div>
164
+ </div>
165
+
166
+ <!-- API Endpoints -->
167
+ <div class="bg-white rounded-xl shadow-md p-6 mb-8">
168
+ <h2 class="text-xl font-bold mb-4">API Endpoints</h2>
169
+ <div class="overflow-x-auto">
170
+ <table class="min-w-full divide-y divide-gray-200">
171
+ <thead class="bg-gray-50">
172
+ <tr>
173
+ <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Method</th>
174
+ <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Endpoint</th>
175
+ <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Description</th>
176
+ </tr>
177
+ </thead>
178
+ <tbody class="bg-white divide-y divide-gray-200">
179
+ <tr>
180
+ <td class="px-6 py-4 whitespace-nowrap text-sm font-mono text-purple-600">POST</td>
181
+ <td class="px-6 py-4 whitespace-nowrap text-sm font-mono">/api/auth/login</td>
182
+ <td class="px-6 py-4 whitespace-nowrap text-sm">User authentication</td>
183
+ </tr>
184
+ <tr>
185
+ <td class="px-6 py-4 whitespace-nowrap text-sm font-mono text-blue-600">GET</td>
186
+ <td class="px-6 py-4 whitespace-nowrap text-sm font-mono">/api/conversations</td>
187
+ <td class="px-6 py-4 whitespace-nowrap text-sm">List conversations</td>
188
+ </tr>
189
+ <tr>
190
+ <td class="px-6 py-4 whitespace-nowrap text-sm font-mono text-green-600">POST</td>
191
+ <td class="px-6 py-4 whitespace-nowrap text-sm font-mono">/api/ai/process</td>
192
+ <td class="px-6 py-4 whitespace-nowrap text-sm">Process AI request</td>
193
+ </tr>
194
+ </tbody>
195
+ </table>
196
+ </div>
197
+ </div>
198
+
199
+ <!-- Authentication -->
200
+ <div class="bg-white rounded-xl shadow-md p-6">
201
+ <h2 class="text-xl font-bold mb-4">Authentication Flow</h2>
202
+ <div class="bg-gray-50 p-4 rounded-lg">
203
+ <div class="flex items-start mb-4">
204
+ <div class="bg-blue-100 p-2 rounded-full mr-4">
205
+ <i class="fas fa-user text-blue-600"></i>
206
+ </div>
207
+ <div>
208
+ <h3 class="font-semibold">JWT Authentication</h3>
209
+ <p class="text-sm text-gray-600 mt-1">Secure stateless authentication using JSON Web Tokens</p>
210
+ </div>
211
+ </div>
212
+ <ol class="space-y-4">
213
+ <li class="flex items-start">
214
+ <span class="bg-purple-100 text-purple-600 text-xs font-semibold rounded-full h-6 w-6 flex items-center justify-center mr-3 mt-0.5">1</span>
215
+ <div>
216
+ <p class="font-medium">Client Login</p>
217
+ <p class="text-sm text-gray-600 mt-1">User submits credentials to /api/auth/login</p>
218
+ </div>
219
+ </li>
220
+ <li class="flex items-start">
221
+ <span class="bg-purple-100 text-purple-600 text-xs font-semibold rounded-full h-6 w-6 flex items-center justify-center mr-3 mt-0.5">2</span>
222
+ <div>
223
+ <p class="font-medium">Token Generation</p>
224
+ <p class="text-sm text-gray-600 mt-1">Server validates credentials and returns JWT</p>
225
+ </div>
226
+ </li>
227
+ <li class="flex items-start">
228
+ <span class="bg-purple-100 text-purple-600 text-xs font-semibold rounded-full h-6 w-6 flex items-center justify-center mr-3 mt-0.5">3</span>
229
+ <div>
230
+ <p class="font-medium">API Requests</p>
231
+ <p class="text-sm text-gray-600 mt-1">Client includes token in Authorization header</p>
232
+ </div>
233
+ </li>
234
+ <li class="flex items-start">
235
+ <span class="bg-purple-100 text-purple-600 text-xs font-semibold rounded-full h-6 w-6 flex items-center justify-center mr-3 mt-0.5">4</span>
236
+ <div>
237
+ <p class="font-medium">Token Validation</p>
238
+ <p class="text-sm text-gray-600 mt-1">Middleware verifies token before processing request</p>
239
+ </div>
240
+ </li>
241
+ </ol>
242
+ </div>
243
+ </div>
244
+ </div>
245
+ </main>
246
+ </div>
247
+ <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=stakmodsco/leadmind-ai" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
248
+ </html>
index.html CHANGED
@@ -97,6 +97,12 @@
97
  <span>Settings</span>
98
  </a>
99
  </li>
 
 
 
 
 
 
100
  </ul>
101
  </div>
102
 
@@ -351,8 +357,8 @@
351
  </div>
352
 
353
  <div class="flex">
354
- <input type="text" placeholder="Type your message..." class="flex-1 border border-gray-300 rounded-l-lg px-4 py-2 focus:outline-none focus:ring-2 focus:ring-purple-500">
355
- <button class="bg-purple-600 hover:bg-purple-700 text-white px-4 py-2 rounded-r-lg">
356
  <i class="fas fa-paper-plane"></i>
357
  </button>
358
  </div>
@@ -399,8 +405,11 @@
399
  </div>
400
 
401
  <script>
402
- // Simple animation for the chat demo
403
  document.addEventListener('DOMContentLoaded', function() {
 
 
 
404
  // Simulate typing animation
405
  const typingElements = document.querySelectorAll('.response-animation');
406
  typingElements.forEach(el => {
@@ -417,23 +426,54 @@
417
  apiStatus.classList.toggle('opacity-50');
418
  }, 2000);
419
 
420
- // Simulate new message arrival
421
- setTimeout(() => {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
422
  const chatContainer = document.querySelector('.bg-gray-50.rounded-lg');
423
- const newMessage = document.createElement('div');
424
- newMessage.className = 'chat-message mt-4';
425
- newMessage.innerHTML = `
426
- <div class="flex items-start">
427
- <img src="https://randomuser.me/api/portraits/women/44.jpg" alt="User" class="w-8 h-8 rounded-full mr-3">
428
- <div class="bg-white p-3 rounded-lg shadow-sm max-w-xs">
429
- <p class="text-sm">Yes, please send that comparison. Also, do you offer annual discounts?</p>
430
- <p class="text-xs text-gray-500 mt-1">10:44 AM</p>
431
- </div>
432
- </div>
433
- `;
434
- chatContainer.appendChild(newMessage);
435
  chatContainer.scrollTop = chatContainer.scrollHeight;
436
- }, 5000);
 
 
 
437
  });
438
  </script>
439
  <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=stakmodsco/leadmind-ai" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
 
97
  <span>Settings</span>
98
  </a>
99
  </li>
100
+ <li>
101
+ <a href="backend.html" class="flex items-center space-x-2 text-gray-600 hover:text-purple-600 hover:bg-purple-50 rounded-lg px-3 py-2">
102
+ <i class="fas fa-server"></i>
103
+ <span>Backend</span>
104
+ </a>
105
+ </li>
106
  </ul>
107
  </div>
108
 
 
357
  </div>
358
 
359
  <div class="flex">
360
+ <input type="text" id="chatInput" placeholder="Type your message..." class="flex-1 border border-gray-300 rounded-l-lg px-4 py-2 focus:outline-none focus:ring-2 focus:ring-purple-500">
361
+ <button onclick="sendMessage()" class="bg-purple-600 hover:bg-purple-700 text-white px-4 py-2 rounded-r-lg">
362
  <i class="fas fa-paper-plane"></i>
363
  </button>
364
  </div>
 
405
  </div>
406
 
407
  <script>
408
+ // Chat functionality
409
  document.addEventListener('DOMContentLoaded', function() {
410
+ // Load conversations from API
411
+ fetchConversations();
412
+
413
  // Simulate typing animation
414
  const typingElements = document.querySelectorAll('.response-animation');
415
  typingElements.forEach(el => {
 
426
  apiStatus.classList.toggle('opacity-50');
427
  }, 2000);
428
 
429
+ // API status indicator animation
430
+ const apiStatus = document.querySelector('.api-status-pulse');
431
+ setInterval(() => {
432
+ apiStatus.classList.toggle('opacity-50');
433
+ }, 2000);
434
+ });
435
+
436
+ async function fetchConversations() {
437
+ try {
438
+ const response = await fetch('http://localhost:5000/api/conversations', {
439
+ headers: {
440
+ 'Authorization': `Bearer ${localStorage.getItem('token')}`
441
+ }
442
+ });
443
+ const conversations = await response.json();
444
+ // Render conversations in UI
445
+ } catch (err) {
446
+ console.error('Error fetching conversations:', err);
447
+ }
448
+ }
449
+
450
+ async function sendMessage() {
451
+ const input = document.getElementById('chatInput');
452
+ const message = input.value.trim();
453
+ if (!message) return;
454
+
455
+ try {
456
+ const response = await fetch('http://localhost:5000/api/ai/process', {
457
+ method: 'POST',
458
+ headers: {
459
+ 'Content-Type': 'application/json',
460
+ 'X-API-Key': localStorage.getItem('apiKey')
461
+ },
462
+ body: JSON.stringify({ content: message })
463
+ });
464
+ const aiResponse = await response.json();
465
+
466
+ // Update UI with message and response
467
  const chatContainer = document.querySelector('.bg-gray-50.rounded-lg');
468
+ // Add user message
469
+ // Add AI response
470
+
471
+ input.value = '';
 
 
 
 
 
 
 
 
472
  chatContainer.scrollTop = chatContainer.scrollHeight;
473
+ } catch (err) {
474
+ console.error('Error sending message:', err);
475
+ }
476
+ }
477
  });
478
  </script>
479
  <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=stakmodsco/leadmind-ai" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
package.json ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ```json
2
+ {
3
+ "name": "leadmind-ai-backend",
4
+ "version": "1.0.0",
5
+ "description": "Backend for LeadMind AI",
6
+ "main": "server.js",
7
+ "scripts": {
8
+ "start": "node server.js",
9
+ "dev": "nodemon server.js"
10
+ },
11
+ "dependencies": {
12
+ "bcryptjs": "^2.4.3",
13
+ "cors": "^2.8.5",
14
+ "dotenv": "^16.0.3",
15
+ "express": "^4.18.2",
16
+ "express-rate-limit": "^6.7.0",
17
+ "jsonwebtoken": "^9.0.0",
18
+ "mongoose": "^7.4.3",
19
+ "uuid": "^9.0.0"
20
+ },
21
+ "devDependencies": {
22
+ "nodemon": "^3.0.1"
23
+ }
24
+ }
25
+ ```
server.js ADDED
@@ -0,0 +1,207 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ```javascript
2
+ require('dotenv').config();
3
+ const express = require('express');
4
+ const mongoose = require('mongoose');
5
+ const jwt = require('jsonwebtoken');
6
+ const bcrypt = require('bcryptjs');
7
+ const cors = require('cors');
8
+ const { v4: uuidv4 } = require('uuid');
9
+ const rateLimit = require('express-rate-limit');
10
+
11
+ const app = express();
12
+
13
+ // Middleware
14
+ app.use(cors());
15
+ app.use(express.json());
16
+
17
+ // Rate limiting
18
+ const limiter = rateLimit({
19
+ windowMs: 15 * 60 * 1000, // 15 minutes
20
+ max: 100 // limit each IP to 100 requests per windowMs
21
+ });
22
+ app.use('/api/', limiter);
23
+
24
+ // Database connection
25
+ mongoose.connect(process.env.MONGODB_URI, {
26
+ useNewUrlParser: true,
27
+ useUnifiedTopology: true
28
+ })
29
+ .then(() => console.log('Connected to MongoDB'))
30
+ .catch(err => console.error('MongoDB connection error:', err));
31
+
32
+ // Models
33
+ const User = mongoose.model('User', new mongoose.Schema({
34
+ username: { type: String, required: true, unique: true },
35
+ password: { type: String, required: true },
36
+ role: { type: String, default: 'user' },
37
+ apiKey: { type: String, default: uuidv4 }
38
+ }));
39
+
40
+ const Conversation = mongoose.model('Conversation', new mongoose.Schema({
41
+ userId: { type: mongoose.Schema.Types.ObjectId, ref: 'User' },
42
+ messages: [{
43
+ content: String,
44
+ sender: { type: String, enum: ['user', 'ai'] },
45
+ timestamp: { type: Date, default: Date.now }
46
+ }],
47
+ status: { type: String, enum: ['active', 'resolved'], default: 'active' },
48
+ createdAt: { type: Date, default: Date.now }
49
+ }));
50
+
51
+ const Lead = mongoose.model('Lead', new mongoose.Schema({
52
+ name: String,
53
+ email: { type: String, required: true, unique: true },
54
+ phone: String,
55
+ status: { type: String, enum: ['new', 'contacted', 'qualified', 'converted'], default: 'new' },
56
+ source: String,
57
+ notes: String,
58
+ createdAt: { type: Date, default: Date.now }
59
+ }));
60
+
61
+ // Authentication middleware
62
+ const authenticate = (req, res, next) => {
63
+ const token = req.header('Authorization')?.replace('Bearer ', '');
64
+ if (!token) return res.status(401).send('Access denied');
65
+
66
+ try {
67
+ const verified = jwt.verify(token, process.env.JWT_SECRET);
68
+ req.user = verified;
69
+ next();
70
+ } catch (err) {
71
+ res.status(400).send('Invalid token');
72
+ }
73
+ };
74
+
75
+ // Routes
76
+ // Auth routes
77
+ app.post('/api/auth/register', async (req, res) => {
78
+ try {
79
+ const { username, password } = req.body;
80
+ const hashedPassword = await bcrypt.hash(password, 10);
81
+ const user = new User({ username, password: hashedPassword });
82
+ await user.save();
83
+ res.status(201).send({ message: 'User created successfully' });
84
+ } catch (err) {
85
+ res.status(400).send(err.message);
86
+ }
87
+ });
88
+
89
+ app.post('/api/auth/login', async (req, res) => {
90
+ try {
91
+ const { username, password } = req.body;
92
+ const user = await User.findOne({ username });
93
+ if (!user) return res.status(400).send('Invalid credentials');
94
+
95
+ const validPass = await bcrypt.compare(password, user.password);
96
+ if (!validPass) return res.status(400).send('Invalid credentials');
97
+
98
+ const token = jwt.sign({ _id: user._id, role: user.role }, process.env.JWT_SECRET, { expiresIn: '1h' });
99
+ res.send({ token, apiKey: user.apiKey });
100
+ } catch (err) {
101
+ res.status(400).send(err.message);
102
+ }
103
+ });
104
+
105
+ // Conversation routes
106
+ app.get('/api/conversations', authenticate, async (req, res) => {
107
+ try {
108
+ const conversations = await Conversation.find({ userId: req.user._id }).sort({ createdAt: -1 });
109
+ res.send(conversations);
110
+ } catch (err) {
111
+ res.status(400).send(err.message);
112
+ }
113
+ });
114
+
115
+ app.post('/api/conversations', authenticate, async (req, res) => {
116
+ try {
117
+ const conversation = new Conversation({ userId: req.user._id });
118
+ await conversation.save();
119
+ res.status(201).send(conversation);
120
+ } catch (err) {
121
+ res.status(400).send(err.message);
122
+ }
123
+ });
124
+
125
+ app.post('/api/conversations/:id/messages', authenticate, async (req, res) => {
126
+ try {
127
+ const conversation = await Conversation.findOne({
128
+ _id: req.params.id,
129
+ userId: req.user._id
130
+ });
131
+ if (!conversation) return res.status(404).send('Conversation not found');
132
+
133
+ // Process AI response (simplified for demo)
134
+ const aiResponse = {
135
+ content: `AI response to: "${req.body.content}". This is a simulated response.`,
136
+ sender: 'ai'
137
+ };
138
+
139
+ conversation.messages.push({
140
+ content: req.body.content,
141
+ sender: 'user'
142
+ });
143
+ conversation.messages.push(aiResponse);
144
+ await conversation.save();
145
+
146
+ res.send(conversation);
147
+ } catch (err) {
148
+ res.status(400).send(err.message);
149
+ }
150
+ });
151
+
152
+ // Lead routes
153
+ app.get('/api/leads', authenticate, async (req, res) => {
154
+ try {
155
+ const leads = await Lead.find().sort({ createdAt: -1 });
156
+ res.send(leads);
157
+ } catch (err) {
158
+ res.status(400).send(err.message);
159
+ }
160
+ });
161
+
162
+ app.post('/api/leads', authenticate, async (req, res) => {
163
+ try {
164
+ const lead = new Lead(req.body);
165
+ await lead.save();
166
+ res.status(201).send(lead);
167
+ } catch (err) {
168
+ res.status(400).send(err.message);
169
+ }
170
+ });
171
+
172
+ app.put('/api/leads/:id', authenticate, async (req, res) => {
173
+ try {
174
+ const lead = await Lead.findByIdAndUpdate(req.params.id, req.body, { new: true });
175
+ if (!lead) return res.status(404).send('Lead not found');
176
+ res.send(lead);
177
+ } catch (err) {
178
+ res.status(400).send(err.message);
179
+ }
180
+ });
181
+
182
+ // API Key authentication
183
+ app.post('/api/ai/process', async (req, res) => {
184
+ try {
185
+ const apiKey = req.header('X-API-Key');
186
+ if (!apiKey) return res.status(401).send('API key required');
187
+
188
+ const user = await User.findOne({ apiKey });
189
+ if (!user) return res.status(401).send('Invalid API key');
190
+
191
+ // Process AI request (simplified for demo)
192
+ const response = {
193
+ id: uuidv4(),
194
+ content: `AI processed: "${req.body.content}". This is a simulated response.`,
195
+ timestamp: new Date()
196
+ };
197
+
198
+ res.send(response);
199
+ } catch (err) {
200
+ res.status(400).send(err.message);
201
+ }
202
+ });
203
+
204
+ // Start server
205
+ const PORT = process.env.PORT || 5000;
206
+ app.listen(PORT, () => console.log(`Server running on port ${PORT}`));
207
+ ```