-
Notifications
You must be signed in to change notification settings - Fork 0
/
server.js
291 lines (261 loc) · 9.52 KB
/
server.js
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
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
const dotenv = require("dotenv");
dotenv.config(); // env configaration
require("express-async-errors"); /// express error handler for catching error from async functions
const express = require("express");
const ConnectDB = require("./DB/ConnectDB");
const fs = require("fs");
const https = require("https");
const path = require("path");
const http = require("http");
const app = express();
const cors = require("cors"); // we need cors to make our server to be able to access from other domains
// /////****** trying to scale node server with cluster modulw in nodejs ****************/
const cluster = require("cluster");
const numCPUs = require("os").cpus().length;
// ///trying to compress the text base data when sending it to client side**************************/
const compression = require("compression");
app.use(
compression({
level: 6,
threshold: 0,
filter: (req, res) => {
if (req.headers["x-no-compression"]) {
// don't compress responses with this request header
return false;
}
return compression.filter(req, res);
},
})
);
// app.use(express.json({ extended: false }));
app.disable("x-powered-by");
app.disable("etag");
const Chats = require("./DBmodels/chatDb_model");
// const Conversations = require("./DBmodels/conversation_model");
const PORT = process.env.PORT || 5000;
// const { OAuth2Client } = require("google-auth-library");// we need this but in userController file to
//// decryt the token from gooogle id token
// const jwt = require("jsonwebtoken");
//// router to provide some functions to our server
const userRouter = require("./Routes/user_routes");
const conversation = require("./Routes/conversation_route");
const chatsRouter = require("./Routes/chats_routes");
///// socket io
const socketIO = require("socket.io");
// import socket from "socket.io"
const multer = require("multer");
const userPost = require("./DBmodels/userPost");
const socketioFileUploader = require("socketio-file-upload");
// app.use(cors({ origin: "http://localhost:3000" }));
app.use(cors());
const server = http.createServer(app);
// const sslServer = https.createServer(
// {
// key: fs.readFileSync(path.join(__dirname, "certs", "key.pem")),
// cert: fs.readFileSync(path.join(__dirname, "certs", "cert.pem")),
// },
// app
// );
//// dont need to use cookieParser becouse it we are using react so it cant requsting from our server so it can't
//// work
// app.use(cookieParser());
// const io = socketIO(sslServer);
const io = socketIO(server);
///// here i am getting destructuring littel bit for socket.io were in this function we can pass data or socket
/////// to our function**********
const {
saveMessage,
saveImageMessage,
updateImage,
} = require("./userControllers/chatControllers");
/// this bilow middleware is for sending images as static file to client side
app.use("/uploads", express.static(path.join(__dirname, "uploads")));
//// or we can use this below requste responce handeler
// app.get("/uploads/:image", async (req, res) => {
// const image = req.params.image;
// console.log("image", image);
// res.sendFile(path.join(__dirname, "uploads", req.params.image));
// });
app.use(express.json());
/// socket.io for getting real time images from client side socket handeler
app.use(socketioFileUploader.router);
//// initializing socket.io to web socket uploader basicly uploader is using socket.io connection***
const uploader = new socketioFileUploader();
///// *********************** Socket.io *************************
///////////////
//////////// below this all are web socket which responce to the client**********
global.onlineUser = new Map();
io.on("connection", (socket) => {
// console.log("new connection added", socket.id);
uploader.dir = "uploads";
uploader.listen(socket);
uploader.on("complete", (event) => {
event.file.clientDetail.filePath = event.file.name;
});
uploader.on("error", (event) => {
console.log("error from socket", event);
});
///// bilow here when we are using socket we are getting responce from client side socket
///// and when we want to send back we are using socket.emit to give responce to client side
socket.on("addUserToSocket", (userID) => {
global.chatSocket = socket;
console.log("conneccted===", userID, `==${socket.id}`);
onlineUser.set(userID, socket.id);
});
socket.on("disconnected", (data) => {
console.log("disconnected--disconnected-disconnected", data);
onlineUser.delete(data);
});
socket.on("image", async (image, receiversID) => {
if (image) {
const newMessage = await saveImageMessage(image, socket);
// const sentTOuser = onlineUser.get(receiversID);
// if (sentTOuser) {
// socket.to(sentTOuser).emit("backToUser", newMessage);
// }
}
});
socket.on("postImage", async (data, receiversID) => {
const sentTOuser = onlineUser.get(receiversID);
if (sentTOuser) {
socket.to(sentTOuser).emit("savedImages", data);
}
});
socket.on("updateImage", async (imageData, imageID, receiversID) => {
// console.log("from update imageData", imageData);
// console.log("imageID", imageID);
const updatedData = await updateImage(imageData, imageID, socket);
const sentTOuser = onlineUser.get(receiversID);
if (sentTOuser) {
socket.to(sentTOuser).emit("reciavedImage", updatedData, imageID);
}
});
socket.on("join", async (data) => {
console.log("available-Users are", onlineUser);
console.log("data from join", data);
try {
if (data) {
const previosMessages = await Chats.find({ conversationBy: data })
.limit(20)
.sort({ createdAt: -1 });
// console.log("previosMessages", previosMessages);
const messages = previosMessages.sort();
socket.emit("getPreviousMessages", messages);
}
} catch (error) {
console.log("error from join", error);
}
});
socket.on("message", async (data, receiversID) => {
// console.log("message coming fron react", data, "&& socketID", socket.id);
if (data) {
const newMessage = await saveMessage(data);
socket.emit("backToUser", newMessage);
const sentTOuser = onlineUser.get(receiversID);
if (sentTOuser) {
socket.to(sentTOuser).emit("backToUser", newMessage);
}
}
});
});
///////
//// below are all http handlers routes
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, "./uploads");
},
filename: function (req, file, cb) {
cb(null, file.originalname);
}, //fieldname is the name of the input field //Date.now().toString is the current time in milliseconds
});
const upload = multer({ storage: storage });
//// this is for uploading images to server using multer as middleware but it is not real time upload as
/// we are using socket.io for real time upload images
app.post("/uploadImage", upload.single("testImage"), async (req, res) => {
const userId = req.body;
try {
const newPost = {
image: {
data: fs.readFileSync("uploads/" + req.file.filename), ////pendding
contentType: "image/png",
},
fileName: req.file.filename,
fileSize: req.file.size,
filePath: req.file.path,
};
const image = await userPost.create({ ...newPost });
res.status(200).json({
success: true,
imageName: image.fileName,
imageUrl: `http:///localhost:5000/uploads/${image.fileName}`,
image: image,
});
} catch (error) {
console.log("error from uploadImage", error);
res.send("we are from the uploadImage error");
}
});
//// deleting image from the server
app.delete("/deleteImage/:imageName/:imageID", async (req, res) => {
const { imageName, imageID } = req.params;
if (!imageName) {
return res.status(400).json({
success: false,
message: "imageName is required",
});
}
try {
const deleteImage = await Chats.findOneAndDelete({ _id: imageID });
const image = await fs.unlinkSync(`./uploads/${imageName}`);
} catch (error) {
console.log("error from deleteImage", error);
}
res.send("image has been deleted");
});
app.use("/", userRouter);
app.use("/", conversation);
app.use("/", chatsRouter);
if (process.env.NODE_ENV === "production") {
app.use(express.static(path.join(__dirname, "tinder_clone", "build")));
app.get("*", (req, res) => {
res.sendFile(path.join(__dirname, "tinder_clone", "build", "index.html"));
});
}
app.use((err, req, res, next) => {
console.log("error from server endpoint", err);
// io.emit("error", err);
});
async function start() {
try {
await ConnectDB(process.env.MONGODB_URL);
// if (cluster.isMaster) {
// for (let i = 0; i < 4; i++) {
// cluster.fork();
// }
// cluster.on("exit", (worker, code, signal) => {
// console.log(`worker ${worker.id} exiteddied`, worker.process.pid);
// cluster.fork();
// });
// } else {
// server.listen(PORT, () => {
// console.log(
// `server Is listening on http://localhost:${PORT} && cluster ID", ${process.pid}`
// );
// });
// sslServer.listen(PORT, () => {
// console.log(`Server is listening on port https://localhost:${PORT}...`);
// });
// }
// sslServer.listen(PORT, () => {
// console.log(`Server is listening on port https://localhost:${PORT}...`);
// });
server.listen(PORT, () => {
console.log(
`server Is listening on http://localhost:${PORT} && cluster ID", ${process.pid}`
);
});
} catch (error) {
console.log("error from Connection making via Mongoose", error);
}
}
start();