-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathuserController.js
More file actions
237 lines (191 loc) · 7.89 KB
/
Copy pathuserController.js
File metadata and controls
237 lines (191 loc) · 7.89 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
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
import { generateToken } from "../lib/utils.js";
import User from "../models/User.js";
import bcrypt from "bcryptjs";
import cloudinary from "../lib/cloudinary.js";
//Signup a new user
export const signup=async(req,res)=>{
const {fullname,email,password,bio}=req.body;
try {
if (!fullname || !email || !password || !bio) {
return res.json({success:false,message:"Missing Details"})
}
const user=await User.findOne({email});
if (user) {
return res.json({success:false,message:"Account already exists"})
}
const salt= await bcrypt.genSalt(10);
const hashedPassword =await bcrypt.hash(password,salt);
const newUser=await User.create({
fullname,email,password:hashedPassword,bio
})
const token= generateToken(newUser._id)
res.json({success:true,userData:newUser,token, message:"Account Created Successfully"})
} catch (error) {
console.log(error)
return res.json({success:false,message:error.message})
}
}
//Controller to login User
export const login =async (req,res) => {
try {
const {email,password} = req.body;
const userData=await User.findOne({email});
const isPasswordCorrected= await bcrypt.compare(password,userData.password);
if (!isPasswordCorrected) {
return res.json({success:false,message:"Invalid Credentials"})
}
const token=generateToken(userData._id)
res.json({success:true,userData,token,message:"Login Successful"})
} catch (error) {
console.log(error)
res.json({success:false,message:error.message})
}
}
//Controller to check if user is authenticated ?
export const checkAuth=(req,res)=>{
res.json({success:true,user:req.user})
}
//Controller to update user profile details
export const updateProfile = async (req,res) => {
try {
const {profilePic,bio,fullname}=req.body;
const userId =req.user._id;
let updatedUser;
if (!profilePic) {
updatedUser=await User.findByIdAndUpdate(userId,{bio,fullname},{new:true});
}
else{
const upload=await cloudinary.uploader.upload(profilePic);
updatedUser=await User.findByIdAndUpdate(userId,{profilePic:upload.secure_url,bio,fullname},{new:true})
}
res.json({success:true,user:updatedUser})
} catch (error) {
console.log(error.message);
res.json({success:false,message:error.message})
}
}
// Controller to get chatbot response using Groq API
export const getChatbotResponse = async (req, res) => {
try {
const { messages } = req.body;
if (!messages || !Array.isArray(messages)) {
return res.status(400).json({ success: false, message: "Invalid or missing messages list" });
}
const apiKey = process.env.GROQ_API_KEY;
if (!apiKey) {
return res.status(500).json({ success: false, message: "GROQ_API_KEY is not configured on the server" });
}
// Limit context to last 15 messages (sliding window)
const recentMessages = messages.slice(-15);
// Format history for Groq API
const formattedMessages = [
{
role: "system",
content: "You are Dialogue Bot, a helpful, premium AI assistant inside the Dialogue enterprise chat application. Help users with questions about Dialogue (client-side AES-256 E2EE encryption, Socket.io real-time indicators, group admin, local development, etc.) or general questions. Answer concisely and professionally."
},
...recentMessages.map(msg => ({
role: msg.sender === 'user' ? 'user' : 'assistant',
content: msg.text
}))
];
const response = await fetch("https://api.groq.com/openai/v1/chat/completions", {
method: "POST",
headers: {
"Authorization": `Bearer ${apiKey}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
model: "meta-llama/llama-4-scout-17b-16e-instruct",
messages: formattedMessages,
temperature: 0.7,
max_completion_tokens: 512,
top_p: 1,
stream: true
})
});
if (!response.ok) {
const errData = await response.json().catch(() => ({}));
const errMsg = errData.error?.message || "Failed to initialize Groq stream";
console.error("Groq API error response:", errMsg);
return res.status(500).json({ success: false, message: errMsg });
}
// Set headers for chunked streaming
res.setHeader('Content-Type', 'text/plain; charset=utf-8');
res.setHeader('Transfer-Encoding', 'chunked');
const decoder = new TextDecoder("utf-8");
let buffer = "";
if (response.body && typeof response.body.getReader === 'function') {
const reader = response.body.getReader();
while (true) {
const { done, value } = await reader.read();
if (done) break;
buffer += decoder.decode(value, { stream: true });
const lines = buffer.split("\n");
buffer = lines.pop() || "";
for (const line of lines) {
const cleanedLine = line.trim();
if (!cleanedLine) continue;
if (cleanedLine === "data: [DONE]") continue;
if (cleanedLine.startsWith("data: ")) {
try {
const json = JSON.parse(cleanedLine.slice(6));
const text = json.choices?.[0]?.delta?.content || "";
if (text) {
res.write(text);
}
} catch (err) {
// ignore partial JSON parse errors
}
}
}
}
} else if (response.body) {
// Node-style stream or async iterable fallback
for await (const chunk of response.body) {
buffer += decoder.decode(chunk, { stream: true });
const lines = buffer.split("\n");
buffer = lines.pop() || "";
for (const line of lines) {
const cleanedLine = line.trim();
if (!cleanedLine) continue;
if (cleanedLine === "data: [DONE]") continue;
if (cleanedLine.startsWith("data: ")) {
try {
const json = JSON.parse(cleanedLine.slice(6));
const text = json.choices?.[0]?.delta?.content || "";
if (text) {
res.write(text);
}
} catch (err) {
// ignore partial JSON parse errors
}
}
}
}
}
// Send any remaining data in the buffer
if (buffer) {
const cleanedLine = buffer.trim();
if (cleanedLine && cleanedLine !== "data: [DONE]" && cleanedLine.startsWith("data: ")) {
try {
const json = JSON.parse(cleanedLine.slice(6));
const text = json.choices?.[0]?.delta?.content || "";
if (text) {
res.write(text);
}
} catch (err) {
// ignore
}
}
}
res.end();
} catch (error) {
console.error("Chatbot controller error:", error);
// If headers are already sent, we cannot send a json response
if (!res.headersSent) {
res.status(500).json({ success: false, message: error.message });
} else {
res.end();
}
}
}