You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

274 lines
8.0 KiB

3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
  1. import express, { Request, Response } from "express";
  2. import { createServer, Server as HTTPServer } from "http";
  3. import { Server as SocketIOServer, Socket } from "socket.io";
  4. import cors from "cors";
  5. import {
  6. activeCallMapType,
  7. callRequestAReject,
  8. ConnectRequest,
  9. OnlineUser,
  10. rtcAnswer,
  11. rtcCandidate,
  12. rtcOffer,
  13. UserDetails,
  14. } from "./types/sType.js";
  15. import { getSecsFromDates, saveCallLogs } from "./helper";
  16. // Initialize Express
  17. const app = express();
  18. // Set up CORS middleware for Express
  19. app.use(
  20. cors({
  21. origin: "*",
  22. })
  23. );
  24. // Create an HTTP server
  25. const httpServer: HTTPServer = createServer(app);
  26. // Initialize Socket.io on the server
  27. const io = new SocketIOServer(httpServer, {
  28. path: "/socket", // Define the WebSocket path
  29. cors: {
  30. origin: "*", // Update this to the origin of your client
  31. methods: ["GET", "POST"],
  32. },
  33. });
  34. // Store online users
  35. const onlineUsers: Map<string, OnlineUser> = new Map();
  36. // Remap the socket ID to the user ID
  37. const socketToUserId: Map<string, string> = new Map();
  38. //call request
  39. const activeCalls: activeCallMapType = new Map();
  40. // Handle WebSocket connections
  41. io.on("connection", (socket: Socket) => {
  42. console.log("User connected", socket.id);
  43. // Handle user-online event
  44. socket.on("user-online", (user: UserDetails) => {
  45. const { userId, userName, image } = user;
  46. // Now we store the socket ID along with the user details
  47. onlineUsers.set(userId, {
  48. userId: userId,
  49. userName,
  50. image,
  51. socketId: socket.id,
  52. });
  53. socketToUserId.set(socket.id, userId);
  54. });
  55. // Handle connect request event
  56. socket.on("connect-req", (user: ConnectRequest) => {
  57. const { caller, callee, userName, image } = user;
  58. // Now we store the socket ID along with the user details
  59. const details = onlineUsers.get(String(callee));
  60. console.log("connect-req", details, onlineUsers, user);
  61. if (details) {
  62. socket.to(details.socketId).emit("connect-res", {
  63. userId: caller,
  64. userName,
  65. image,
  66. time: new Date(),
  67. });
  68. }
  69. });
  70. // Handle user-online event
  71. socket.on("connect-reject-req", (data: { users: number[] }) => {
  72. const { users } = data;
  73. console.log("connect-reject-req", data);
  74. // Now we store the socket ID along with the user details
  75. for (const user of users) {
  76. const details = onlineUsers.get(String(user));
  77. console.log("connect-reject-req", details);
  78. if (details) {
  79. socket.to(details.socketId).emit("connect-reject-res", {
  80. reject: true,
  81. });
  82. }
  83. }
  84. });
  85. // Handle user disconnect event
  86. socket.on("disconnect", async () => {
  87. const user = activeCalls.get(socket.id);
  88. console.log("disconnect", user);
  89. if (user) {
  90. if (user?.from) {
  91. const calleeU = socketToUserId.get(socket.id);
  92. const callerU = socketToUserId.get(user.from);
  93. if (calleeU && callerU) {
  94. const caller = onlineUsers.get(callerU);
  95. const callee = onlineUsers.get(calleeU);
  96. if (caller && callee) {
  97. const meetTime = getSecsFromDates(user.callTime);
  98. const callLog = {
  99. to: callee.userId,
  100. from: caller.userId,
  101. time: meetTime,
  102. };
  103. await saveCallLogs(callLog);
  104. socket.to(caller.socketId).emit("call-rejected");
  105. }
  106. }
  107. }
  108. if (user?.to) {
  109. const callerU = socketToUserId.get(socket.id);
  110. const calleeU = socketToUserId.get(user.to);
  111. if (calleeU && callerU) {
  112. const caller = onlineUsers.get(callerU);
  113. const callee = onlineUsers.get(calleeU);
  114. if (caller && callee) {
  115. const meetTime = getSecsFromDates(user.callTime);
  116. const callLog = {
  117. to: callee.userId,
  118. from: caller.userId,
  119. time: meetTime,
  120. };
  121. await saveCallLogs(callLog);
  122. socket.to(callee.socketId).emit("call-rejected");
  123. }
  124. }
  125. }
  126. const secUser = user?.to || user?.from;
  127. if (secUser) {
  128. activeCalls.delete(socket.id);
  129. activeCalls.delete(secUser);
  130. }
  131. }
  132. const userId = socketToUserId.get(socket.id);
  133. if (userId) {
  134. onlineUsers.delete(userId);
  135. socketToUserId.delete(socket.id);
  136. }
  137. });
  138. // Handle user ice candidate event
  139. socket.on("ice-candidate", (data: rtcCandidate) => {
  140. const { candidate, to } = data;
  141. const calledTo = onlineUsers.get(to);
  142. if (calledTo) {
  143. console.log("get-ice-candidate", to);
  144. // Emit to the recipient's socket ID
  145. socket.to(calledTo.socketId).emit("get-ice-candidate", candidate);
  146. }
  147. });
  148. // // Handle call-offer events
  149. socket.on("offer", (data: rtcOffer) => {
  150. const { offer, to, sender } = data;
  151. const calledFrom = onlineUsers.get(sender);
  152. const calledTo = onlineUsers.get(to);
  153. if (calledTo && calledFrom) {
  154. // Emit to the recipient's socket ID
  155. socket.to(calledTo.socketId).emit("get-offer", {
  156. offer,
  157. sender: sender,
  158. senderName: calledFrom.userName,
  159. senderImage: calledFrom.image,
  160. });
  161. }
  162. });
  163. // // Handle call-request events
  164. socket.on("call-request", (data: rtcAnswer) => {
  165. const { answer, to } = data;
  166. const calledTo = onlineUsers.get(to);
  167. if (calledTo) {
  168. socket.to(calledTo.socketId).emit("get-answer", answer);
  169. }
  170. });
  171. // // Handle call-accept events
  172. socket.on("call-accept", (data: callRequestAReject) => {
  173. const { to, from } = data;
  174. const calledTo = onlineUsers.get(to);
  175. const calledFrom = onlineUsers.get(from);
  176. if (calledTo && calledFrom) {
  177. activeCalls.set(calledFrom.socketId, {
  178. to: calledTo.socketId,
  179. callTime: new Date(),
  180. });
  181. activeCalls.set(calledTo.socketId, {
  182. from: calledFrom.socketId,
  183. callTime: new Date(),
  184. });
  185. console.log("call-accept", activeCalls);
  186. socket.to(calledTo.socketId).emit("call-accepted");
  187. }
  188. });
  189. // // Handle call-reject events
  190. socket.on("call-reject", async () => {
  191. const user = activeCalls.get(socket.id);
  192. if (user) {
  193. if (user?.from) {
  194. const calleeU = socketToUserId.get(socket.id);
  195. const callerU = socketToUserId.get(user.from);
  196. if (calleeU && callerU) {
  197. const caller = onlineUsers.get(callerU);
  198. const callee = onlineUsers.get(calleeU);
  199. if (caller && callee) {
  200. const meetTime = getSecsFromDates(user.callTime);
  201. const callLog = {
  202. to: callee.userId,
  203. from: caller.userId,
  204. time: meetTime,
  205. };
  206. await saveCallLogs(callLog);
  207. socket.to(caller.socketId).emit("call-rejected");
  208. }
  209. }
  210. }
  211. if (user?.to) {
  212. const callerU = socketToUserId.get(socket.id);
  213. const calleeU = socketToUserId.get(user.to);
  214. if (calleeU && callerU) {
  215. const caller = onlineUsers.get(callerU);
  216. const callee = onlineUsers.get(calleeU);
  217. if (caller && callee) {
  218. const meetTime = getSecsFromDates(user.callTime);
  219. const callLog = {
  220. to: callee.userId,
  221. from: caller.userId,
  222. time: meetTime,
  223. };
  224. await saveCallLogs(callLog);
  225. socket.to(callee.socketId).emit("call-rejected");
  226. }
  227. }
  228. }
  229. const secUser = user?.to || user?.from;
  230. if (secUser) {
  231. activeCalls.delete(socket.id);
  232. activeCalls.delete(secUser);
  233. }
  234. }
  235. });
  236. });
  237. app.use(express.json());
  238. // Define a basic route
  239. app.get("/", (req: Request, res: Response) => {
  240. res.send("WebSocket server is running");
  241. });
  242. // Define a basic route
  243. app.post("/get-onlines", (req: Request, res: Response) => {
  244. const { users }: { users: number[] } = req.body;
  245. const onlineUsersData = users.filter((user: number) =>
  246. onlineUsers.has(String(user))
  247. );
  248. res.json({ users: onlineUsersData });
  249. });
  250. // Start the server on port 3000
  251. const PORT = process.env.PORT || 5007;
  252. httpServer.listen(PORT, () => {
  253. console.log(`Server is running on port ${PORT}`);
  254. });