AnonSec Team
Server IP : 72.167.149.90  /  Your IP : 216.73.216.228
Web Server : Apache
System : Linux server.zoomride.app 4.18.0-553.158.1.el8_10.x86_64 #1 SMP Wed Aug 26 03:18:33 EDT 2026 x86_64
User : zoomride2022 ( 1001)
PHP Version : 8.3.33
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : ON
Directory (0750) :  /home/zoomride2022/public_html/backend.survo.app/

[  Home  ][  C0mmand  ][  Upload File  ]

Current File : /home/zoomride2022/public_html/backend.survo.app/socket.js
///import model
const Customer = require("./models/customer.model");
const Provider = require("./models/provider.model");
const Agency = require("./models/agency.model");
const ChatTopic = require("./models/chatTopic.model");
const Chat = require("./models/chat.model");
const CallHistory = require("./models/callHistory.model");

//private key
const admin = require("./util/privateKey");

//moment
const moment = require("moment");

//mongoose
const mongoose = require("mongoose");

io.on("connection", async (socket) => {
  console.log("Socket Connection done Client ID: ", socket.id);
  console.log("socket.connected:                 ", socket.connected);
  console.log("Current rooms:                    ", socket.rooms);
  console.log("socket.handshake.query:           ", socket.handshake.query);

  const { globalRoom } = socket.handshake.query;
  console.log("globalRoom", globalRoom);

  const id = globalRoom && globalRoom.split(":")[1];
  console.log("socket connected with userId:   ", id);

  socket.join(globalRoom);

  if (globalRoom) {
    const customer = await Customer.findById(id);
    if (customer) {
      customer.isOnline = true;
      await customer.save();
    } else {
      const provider = await Provider.findById(id);
      if (provider) {
        provider.isOnline = true;
        await provider.save();
      } else {
        console.log("Check if Agency is available");

        const agency = await Agency.findById(id);
        if (agency) {
          agency.isOnline = true;
          await agency.save();
        }
      }
    }
  }

  //chat
  socket.on("message", async (data) => {
    console.log("data in message =====================================  ", data);

    let senderPromise, receiverPromise;

    if (data?.senderRole === "customer") {
      senderPromise = Customer.findById(data?.senderId);
    } else if (data?.senderRole === "agency") {
      senderPromise = Agency.findById(data?.senderId);
    } else if (data?.senderRole === "provider") {
      senderPromise = Provider.findById(data?.senderId);
    }

    if (data?.receiverRole === "provider") {
      receiverPromise = Provider.findById(data?.receiverId);
    } else if (data?.receiverRole === "agency") {
      receiverPromise = Agency.findById(data?.receiverId);
    } else if (data?.receiverRole === "customer") {
      receiverPromise = Customer.findById(data?.receiverId);
    }

    const [sender, receiver] = await Promise.all([senderPromise, receiverPromise]);

    let chatTopic;
    const foundChatTopic = await ChatTopic.findOne({
      $or: [{ $and: [{ senderId: sender?._id }, { receiverId: receiver?._id }] }, { $and: [{ senderId: receiver?._id }, { receiverId: sender?._id }] }],
    });

    chatTopic = foundChatTopic;

    if (!chatTopic) {
      chatTopic = new ChatTopic();
      chatTopic.senderId = sender?._id;
      chatTopic.receiverId = receiver?._id;
    }

    if (chatTopic && Number(data?.messageType) == 1) {
      const chat = new Chat();

      chat.senderId = data?.senderId;
      chat.messageType = 1;
      chat.message = data?.message;
      chat.image = "";
      chat.audio = "";
      chat.chatTopic = chatTopic._id;
      chat.date = new Date().toLocaleString("en-US", { timeZone: "Asia/Kolkata" });

      chatTopic.chat = chat._id;

      await Promise.all([chat.save(), chatTopic.save()]);

      io.in("globalRoom:" + data?.senderId.toString()).emit("message", data);
      io.in("globalRoom:" + data?.receiverId.toString()).emit("message", data);

      const [socket1, socket2] = await Promise.all([io.in("globalRoom:" + data?.senderId.toString()).fetchSockets(), io.in("globalRoom:" + data?.receiverId.toString()).fetchSockets()]);

      if (!receiver.isBlock && receiver.fcmToken !== null) {
        const adminPromise = await admin;

        const payload = {
          token: receiver.fcmToken,
          notification: {
            title: "💬 New Message Received!",
            body: "📩 You have a new message. Tap to check it out! 🚀",
          },
          data: {
            type: "CHAT_MESSAGE",
          },
        };

        adminPromise
          .messaging()
          .send(payload)
          .then((response) => {
            console.log("Successfully sent with response: ", response);
          })
          .catch((error) => {
            console.log("Error sending message:      ", error);
          });
      }
    } else {
      console.log("other messageType");

      io.in("globalRoom:" + data?.senderId.toString()).emit("message", data);
      io.in("globalRoom:" + data?.receiverId.toString()).emit("message", data);
    }
  });

  socket.on("messageRead", async (data) => {
    try {
      console.log("Data in messageRead event:", data);

      const updated = await Chat.findOneAndUpdate({ _id: new mongoose.Types.ObjectId(data.messageId) }, { $set: { isRead: true } }, { new: true });

      if (!updated) {
        console.log(`No message found with ID ${data.messageId}`);
      } else {
        console.log(`Updated isRead to true for message with ID: ${updated._id}`);
      }
    } catch (error) {
      console.error("Error updating messages:", error);
    }
  });

  //audio call
  socket.on("audioCallInitiated", async (data) => {
    console.log("audioCallInitiated data ==============================", data);

    let callerModel, receiverModel;

    if (data.role === "customer") {
      callerModel = Customer;
      if (data.receiverRole === "provider") {
        receiverModel = Provider;
      } else if (data.receiverRole === "agency") {
        receiverModel = Agency;
      } else {
        io.in("globalRoom:" + data?.callerId).emit("audioCallInitiated", { message: "Invalid receiver role for customer." });
        return;
      }
    } else if (data.role === "provider") {
      callerModel = Provider;
      if (data.receiverRole === "agency") {
        receiverModel = Agency;
      } else if (data.receiverRole === "customer") {
        receiverModel = Customer;
      } else {
        io.in("globalRoom:" + data?.callerId).emit("audioCallInitiated", { message: "Invalid receiver role for provider." });
        return;
      }
    } else if (data.role === "agency") {
      callerModel = Agency;
      if (data.receiverRole === "customer") {
        receiverModel = Customer;
      } else if (data.receiverRole === "provider") {
        receiverModel = Provider;
      } else {
        io.in("globalRoom:" + data?.callerId).emit("audioCallInitiated", { message: "Invalid receiver role for agency." });
        return;
      }
    } else {
      io.in("globalRoom:" + data?.callerId).emit("audioCallInitiated", { message: "Invalid caller role." });
      return;
    }

    const [caller, receiver] = await Promise.all([callerModel.findById(data?.callerId), receiverModel.findById(data?.receiverId)]);

    if (!caller) {
      io.in("globalRoom:" + caller._id.toString()).emit("audioCallInitiated", { message: "caller does not found." });
      return;
    }

    if (caller.isBlock) {
      io.in("globalRoom:" + caller._id.toString()).emit("audioCallInitiated", { message: "Oops! Caller busy with someone else.", isBlock: true });
      return;
    }

    if ((caller.isBusy && caller.callId) || caller.isBusy || caller.callId) {
      io.in("globalRoom:" + caller._id.toString()).emit("audioCallInitiated", { message: "Oops ! caller busy with someone else.", isBusy: true });
      return;
    }

    if (!receiver) {
      io.in("globalRoom:" + caller._id.toString()).emit("audioCallInitiated", { message: "receiver does not found." });
      return;
    }

    if (receiver.isBlock) {
      io.in("globalRoom:" + caller._id.toString()).emit("audioCallInitiated", { message: "receiver blocked by the admin.", isBlock: true });
      return;
    }

    if (!receiver.isOnline) {
      io.in("globalRoom:" + caller._id.toString()).emit("audioCallInitiated", "Oops ! receiver is not online.");
      return;
    }

    if ((receiver.isBusy && receiver.callId) || receiver.isBusy || receiver.callId) {
      io.in("globalRoom:" + caller._id.toString()).emit("audioCallInitiated", { message: "Oops ! receiver busy with someone else.", isBusy: true });
      return;
    }

    console.log("receiver.isBusy in audioCallInitiated", receiver.isBusy, "receiver.callId in audioCallInitiated", receiver.callId);
    console.log("caller.isBusy in audioCallInitiated", caller.isBusy, "caller.callId in audioCallInitiated", caller.callId);

    if (!receiver.isBusy && receiver.callId === null) {
      console.log("Receiver is free then emited");

      const callHistory = new CallHistory();
      callHistory.callerId = caller._id;
      callHistory.receiverId = receiver._id;
      callHistory.callId = callHistory._id.toString();
      callHistory.callStartTime = moment(new Date()).format("HH:mm:ss");
      callHistory.date = new Date().toLocaleString("en-US", { timeZone: "Asia/Kolkata" });

      await Promise.all([
        callHistory.save(),
        callerModel.findOneAndUpdate({ _id: callHistory.callerId }, { $set: { isBusy: true, callId: callHistory._id } }, { new: true }),
        receiverModel.findOneAndUpdate({ _id: callHistory.receiverId }, { $set: { isBusy: true, callId: callHistory._id } }, { new: true }),
      ]);

      const dataOfVideoCall = {
        isBusy: false,
        callerId: caller._id,
        receiverId: receiver._id,
        callerImage: caller.profileImage,
        receiverImage: receiver.profileImage,
        callId: callHistory._id,
        role: data?.role,
        callerName: data?.callerName,
        receiverName: data?.receiverName,
        receiverRole: data?.receiverRole,
      };

      io.in("globalRoom:" + receiver._id.toString()).emit("incomingAudioCall", dataOfVideoCall);
      io.in("globalRoom:" + caller._id.toString()).emit("audioCallInitiated", dataOfVideoCall); //for data emit to caller
    } else {
      console.log("Condition not met");
      io.in("globalRoom:" + caller._id.toString()).emit("audioCallInitiated", { message: "Oops ! receiver busy with someone else.", isBusy: true });
      return;
    }
  });

  //when accept OR decline the call
  socket.on("audioCallResponse", async (data) => {
    console.log("audioCallResponse data ==============================", data);

    const callerIdRoom = "globalRoom:" + data.callerId;
    const receiverIdRoom = "globalRoom:" + data.receiverId;

    let callerModel, receiverModel;

    if (data.role === "customer") {
      callerModel = Customer;
      if (data.receiverRole === "provider") {
        receiverModel = Provider;
      } else if (data.receiverRole === "agency") {
        receiverModel = Agency;
      } else {
        io.in("globalRoom:" + data?.callerId).emit("audioCallInitiated", { message: "Invalid receiver role for customer." });
        return;
      }
    } else if (data.role === "provider") {
      callerModel = Provider;
      if (data.receiverRole === "agency") {
        receiverModel = Agency;
      } else if (data.receiverRole === "customer") {
        receiverModel = Customer;
      } else {
        io.in("globalRoom:" + data?.callerId).emit("audioCallInitiated", { message: "Invalid receiver role for provider." });
        return;
      }
    } else if (data.role === "agency") {
      callerModel = Agency;
      if (data.receiverRole === "customer") {
        receiverModel = Customer;
      } else if (data.receiverRole === "provider") {
        receiverModel = Provider;
      } else {
        io.in("globalRoom:" + data?.callerId).emit("audioCallInitiated", { message: "Invalid receiver role for agency." });
        return;
      }
    } else {
      io.in("globalRoom:" + data?.callerId).emit("audioCallInitiated", { message: "Invalid caller role." });
      return;
    }

    const [caller, receiver, callHistory] = await Promise.all([callerModel.findById(data?.callerId), receiverModel.findById(data?.receiverId), CallHistory.findById(data.callId)]);

    if (!data.isAccept) {
      console.log("Audio call declined:", data.isAccept);

      io.in(callerIdRoom).emit("audioCallResponse", data);
      io.in(receiverIdRoom).emit("audioCallResponse", data);

      let chatTopic;
      chatTopic = await ChatTopic.findOne({
        $or: [
          {
            $and: [{ senderId: caller._id }, { receiverId: receiver._id }],
          },
          {
            $and: [{ senderId: receiver._id }, { receiverId: caller._id }],
          },
        ],
      });

      const chat = new Chat();

      if (!chatTopic) {
        chatTopic = new ChatTopic();
        chatTopic.chat = chat._id;
        chatTopic.senderId = caller._id;
        chatTopic.receiverId = receiver._id;
      }

      chat.chatTopic = chatTopic._id;
      chat.senderId = data.callerId;
      chat.messageType = 4;
      chat.message = "📞 Audio Call";
      chat.callType = 2; // 2.declined
      chat.callId = data?.callId;
      chat.isRead = true;
      chat.date = new Date().toLocaleString();

      chatTopic.chat = chat._id;

      callHistory.callEndTime = moment().format("HH:mm:ss");

      const date1 = moment(callHistory.callStartTime, "HH:mm:ss");
      const date2 = moment(callHistory.callEndTime, "HH:mm:ss");
      const timeDifference = date2.diff(date1);
      const duration = moment.duration(timeDifference);
      const durationTime = moment.utc(duration.asMilliseconds()).format("HH:mm:ss");

      callHistory.callConnect = false;
      callHistory.duration = durationTime;

      const [callerUpdate, receiverUpdate] = await Promise.all([
        callerModel.findOneAndUpdate({ _id: caller._id }, { $set: { isBusy: false, callId: null } }, { new: true }),
        receiverModel.findOneAndUpdate({ _id: receiver._id }, { $set: { isBusy: false, callId: null } }, { new: true }),
        chat.save(),
        chatTopic.save(),
        callHistory.save(),
      ]);

      console.log("callerUpdate modified in callCancel: ", callerUpdate?.isBusy, callerUpdate?.callId);
      console.log("Receiver updated after declining audio call:", receiverUpdate?.isBusy, receiverUpdate?.callId);
    } else {
      console.log("Audio call accepted:", data.isAccept);

      const [socket1, socket2] = await Promise.all([io.in(callerIdRoom).fetchSockets(), io.in(receiverIdRoom).fetchSockets()]);

      console.log("receiver.callId ========================", receiver?.callId);

      if (receiver.callId === data?.callId) {
        console.log("Joining caller and receiver to audio call room.");

        const initialRoomState = io.sockets.adapter.rooms.get(data.callId);
        console.log("Sockets in audio call room before joining:", initialRoomState);

        socket1?.length ? socket1[0].join(data.callId) : console.log("socket1 not able to emit");
        socket2?.length ? socket2[0].join(data.callId) : console.log("socket2 not able to emit");

        io.in(data.callId.toString()).emit("audioCallResponse", data);

        const finalRoomState = io.sockets.adapter.rooms.get(data.callId.toString());
        console.log("Sockets in audio call room after joining:", finalRoomState);

        let chatTopic;
        chatTopic = await ChatTopic.findOne({
          $or: [
            {
              $and: [{ senderId: caller._id }, { receiverId: receiver._id }],
            },
            {
              $and: [{ senderId: receiver._id }, { receiverId: caller._id }],
            },
          ],
        });

        const chat = new Chat();

        if (!chatTopic) {
          chatTopic = new ChatTopic();

          chatTopic.chat = chat._id;
          chatTopic.senderId = caller._id;
          chatTopic.receiverId = receiver._id;
        }

        chat.chatTopic = chatTopic._id;
        chat.senderId = data.callerId;
        chat.messageType = 4;
        chat.message = "📞 Audio Call";
        chat.callType = 1; //1.received
        chat.callId = data.callId;
        chat.date = new Date().toLocaleString();

        chatTopic.chat = chat._id;

        await Promise.all([
          chat.save(),
          chatTopic.save(),
          CallHistory.findOneAndUpdate(
            { _id: callHistory._id },
            {
              $set: {
                callConnect: true,
                callStartTime: moment().format("HH:mm:ss"),
              },
            },
            { new: true }
          ),
        ]);

        console.log("Receiver is available, audio call accepted.");
      } else {
        console.log("Audio call ID mismatch, emitting call cancellation to receiver.");

        io.in("globalRoom:" + receiverIdRoom).emit("audioCallCancellation", data);
      }
    }
  });

  //when caller cut the call
  socket.on("callCancel", async (data) => {
    console.log("data in callCancel ================", data);

    io.in("globalRoom:" + data?.callerId).emit("callCancel", data);
    io.in("globalRoom:" + data?.receiverId).emit("callCancel", data);

    let callerModel, receiverModel;

    if (data.role === "customer") {
      callerModel = Customer;
      if (data.receiverRole === "provider") {
        receiverModel = Provider;
      } else if (data.receiverRole === "agency") {
        receiverModel = Agency;
      } else {
        io.in("globalRoom:" + data?.callerId).emit("audioCallInitiated", { message: "Invalid receiver role for customer." });
        return;
      }
    } else if (data.role === "provider") {
      callerModel = Provider;
      if (data.receiverRole === "agency") {
        receiverModel = Agency;
      } else if (data.receiverRole === "customer") {
        receiverModel = Customer;
      } else {
        io.in("globalRoom:" + data?.callerId).emit("audioCallInitiated", { message: "Invalid receiver role for provider." });
        return;
      }
    } else if (data.role === "agency") {
      callerModel = Agency;
      if (data.receiverRole === "customer") {
        receiverModel = Customer;
      } else if (data.receiverRole === "provider") {
        receiverModel = Provider;
      } else {
        io.in("globalRoom:" + data?.callerId).emit("audioCallInitiated", { message: "Invalid receiver role for agency." });
        return;
      }
    } else {
      io.in("globalRoom:" + data?.callerId).emit("audioCallInitiated", { message: "Invalid caller role." });
      return;
    }

    const [caller, receiver, callHistory] = await Promise.all([callerModel.findById(data?.callerId), receiverModel.findById(data?.receiverId), CallHistory.findById(data.callId)]);

    callHistory.callEndTime = moment().format("HH:mm:ss");

    const date1 = moment(callHistory.callStartTime, "HH:mm:ss");
    const date2 = moment(callHistory.callEndTime, "HH:mm:ss");
    const timeDifference = date2.diff(date1);
    const duration = moment.duration(timeDifference);
    const durationTime = moment.utc(duration.asMilliseconds()).format("HH:mm:ss");

    callHistory.callConnect = false;
    callHistory.duration = durationTime;

    if (callHistory) {
      const [callerUpdate, receiverUpdate] = await Promise.all([
        callerModel.findOneAndUpdate({ _id: caller?._id }, { $set: { isBusy: false, callId: null } }, { new: true }),
        receiverModel.findOneAndUpdate({ _id: receiver?._id }, { $set: { isBusy: false, callId: null } }, { new: true }),
        callHistory.save(),
      ]);

      console.log("callerUpdate modified in callCancel: ", callerUpdate.isBusy, callerUpdate.callId);
      console.log("receiverUpdate modified in callCancel: ", receiverUpdate.isBusy, receiverUpdate.callId);
    }

    let chatTopic;
    chatTopic = await ChatTopic.findOne({
      $or: [
        {
          $and: [{ senderUserId: caller._id }, { receiverUserId: receiver._id }],
        },
        {
          $and: [{ senderUserId: receiver._id }, { receiverUserId: caller._id }],
        },
      ],
    });

    const chat = new Chat();

    if (!chatTopic) {
      chatTopic = new ChatTopic();

      chatTopic.chat = chat._id;
      chatTopic.senderId = caller._id;
      chatTopic.receiverId = receiver._id;
      await chatTopic.save();
    }

    chat.chatTopic = chatTopic._id;
    chat.callId = callHistory._id;
    chat.senderUserId = callHistory.callerId;
    chat.messageType = 4;
    chat.message = "📞 Audio Call";
    chat.callType = 3; //3.missedCall
    chat.date = new Date().toLocaleString();
    chat.isRead = true;

    chatTopic.chat = chat._id;

    await Promise.all([chat.save(), chatTopic.save()]);

    if (!receiver.isBlock && receiver.fcmToken !== null) {
      const adminPromise = await admin;

      const payload = {
        token: receiver.fcmToken,
        notification: {
          title: "📞 Missed Call Alert!",
          body: "🔔 You have a missed call. Call back when you're available! ⏳",
        },
      };

      adminPromise
        .messaging()
        .send(payload)
        .then((response) => {
          console.log("Successfully sent with response: ", response);
        })
        .catch((error) => {
          console.log("Error sending message:      ", error);
        });
    }
  });

  //when call connect between both users (receiver or caller cut the call)
  socket.on("callDisconnect", async (data) => {
    console.log("data in callDisconnect ====================", data);

    const xyz = io.sockets.adapter.rooms.get(data?.callId);
    console.log("socket connected in callDisconnect before ====================================: ", xyz);

    io.to(data?.callId.toString()).emit("callDisconnect", data); //callId join in globalRoom when both users join in call at that time
    io.socketsLeave(data?.callId.toString());

    const abc = io.sockets.adapter.rooms.get(data?.callId.toString());
    console.log("socket connected in callDisconnect after ====================================: ", abc);

    let callerModel, receiverModel;

    if (data.role === "customer") {
      callerModel = Customer;
      if (data.receiverRole === "provider") {
        receiverModel = Provider;
      } else if (data.receiverRole === "agency") {
        receiverModel = Agency;
      } else {
        io.in("globalRoom:" + data?.callerId).emit("audioCallInitiated", { message: "Invalid receiver role for customer." });
        return;
      }
    } else if (data.role === "provider") {
      callerModel = Provider;
      if (data.receiverRole === "agency") {
        receiverModel = Agency;
      } else if (data.receiverRole === "customer") {
        receiverModel = Customer;
      } else {
        io.in("globalRoom:" + data?.callerId).emit("audioCallInitiated", { message: "Invalid receiver role for provider." });
        return;
      }
    } else if (data.role === "agency") {
      callerModel = Agency;
      if (data.receiverRole === "customer") {
        receiverModel = Customer;
      } else if (data.receiverRole === "provider") {
        receiverModel = Provider;
      } else {
        io.in("globalRoom:" + data?.callerId).emit("audioCallInitiated", { message: "Invalid receiver role for agency." });
        return;
      }
    } else {
      io.in("globalRoom:" + data?.callerId).emit("audioCallInitiated", { message: "Invalid caller role." });
      return;
    }

    const [callHistory, caller, receiver] = await Promise.all([CallHistory.findById(data.callId), callerModel.findById(data?.callerId), receiverModel.findById(data?.receiverId)]);

    callHistory.callEndTime = moment().format("HH:mm:ss");

    const date1 = moment(callHistory.callStartTime, "HH:mm:ss");
    const date2 = moment(callHistory.callEndTime, "HH:mm:ss");
    const timeDifference = date2.diff(date1);
    const duration = moment.duration(timeDifference);
    const durationTime = moment.utc(duration.asMilliseconds()).format("HH:mm:ss");

    callHistory.callConnect = false;
    callHistory.duration = durationTime;

    if (callHistory) {
      console.log("callHistory in callDisconnect ============", callHistory);

      const [callerUpdate, receiverUpdate] = await Promise.all([
        callerModel.findOneAndUpdate({ _id: caller?._id }, { $set: { isBusy: false, callId: null } }, { new: true }),
        receiverModel.findOneAndUpdate({ _id: receiver?._id }, { $set: { isBusy: false, callId: null } }, { new: true }),
        Chat.findOneAndUpdate(
          { callId: callHistory._id },
          {
            $set: {
              callDuration: durationTime,
              messageType: 4,
              callType: 1, //1.received
              isRead: true,
            },
          },
          { new: true }
        ),
        callHistory.save(),
      ]);

      console.log("callerUpdate modified in callDisconnect:   ", callerUpdate?.isBusy, callerUpdate?.callId);
      console.log("receiverUpdate modified in callDisconnect: ", receiverUpdate?.isBusy, receiverUpdate?.callId);
    }
  });

  socket.on("disconnect", async (reason) => {
    console.log(`socket disconnect ===============`, id, socket?.id, reason);

    if (globalRoom) {
      const sockets = await io.in(globalRoom).fetchSockets();

      if (sockets.length === 0) {
        const userId = new mongoose.Types.ObjectId(id);

        const [customer, provider, agency] = await Promise.all([Customer.findById(userId), Provider.findById(userId), Agency.findById(userId)]);

        if (customer) {
          console.log("Customer disconnect:", customer._id, customer.name);

          const customerUpdate = await Customer.findOneAndUpdate({ _id: userId }, { $set: { isOnline: false, isBusy: false, callId: null } }, { new: true });
          console.log("Customer Update in disconnect:", customerUpdate.isOnline, customerUpdate.isBusy, customerUpdate.callId);

          if (customer.callId) {
            const callId = new mongoose.Types.ObjectId(customer.callId);
            console.log("Customer callId in disconnect:", callId);

            io.socketsLeave(customer.callId.toString());

            const [updatedCustomer, callHistory] = await Promise.all([
              Customer.findOneAndUpdate({ _id: userId }, { $set: { isOnline: false, isBusy: false, callId: null } }, { new: true }),
              CallHistory.findById(callId),
            ]);

            console.log("Updated customer in disconnect:", updatedCustomer.isOnline, updatedCustomer.isBusy, updatedCustomer.callId);

            if (callHistory) {
              console.log("callHistory in disconnect:", callHistory._id);

              callHistory.callEndTime = moment().format("HH:mm:ss");

              const startTime = moment(callHistory.callStartTime, "HH:mm:ss");
              const endTime = moment(callHistory.callEndTime, "HH:mm:ss");
              const duration = moment.duration(endTime.diff(startTime));
              const durationTime = moment.utc(duration.asMilliseconds()).format("HH:mm:ss");

              callHistory.callConnect = false;
              callHistory.duration = durationTime;

              await Promise.all([
                callHistory.save(),
                Chat.findOneAndUpdate(
                  { callId: callHistory._id },
                  {
                    $set: {
                      callDuration: durationTime,
                      messageType: 4,
                      callType: 1, // 1.received
                      isRead: true,
                    },
                  },
                  { new: true }
                ),
              ]);
            }
          }
        } else if (provider) {
          console.log("Provider disconnect:", provider._id, provider.name);

          const providerUpdate = await Provider.findOneAndUpdate({ _id: userId }, { $set: { isOnline: false, isBusy: false, callId: null } }, { new: true });
          console.log("Provider Update in disconnect:", providerUpdate.isOnline, providerUpdate.isBusy, providerUpdate.callId);

          if (provider.callId) {
            const callId = new mongoose.Types.ObjectId(provider.callId);
            console.log("Provider callId in disconnect:", callId);

            io.socketsLeave(provider.callId.toString());

            const [updatedProvider, callHistory] = await Promise.all([
              Provider.findOneAndUpdate({ _id: userId }, { $set: { isOnline: false, isBusy: false, callId: null } }, { new: true }),
              CallHistory.findById(callId),
            ]);

            console.log("Updated provider in disconnect:", updatedProvider.isOnline, updatedProvider.isBusy, updatedProvider.callId);

            if (callHistory) {
              console.log("callHistory in disconnect:", callHistory._id);

              callHistory.callEndTime = moment().format("HH:mm:ss");

              const startTime = moment(callHistory.callStartTime, "HH:mm:ss");
              const endTime = moment(callHistory.callEndTime, "HH:mm:ss");
              const duration = moment.duration(endTime.diff(startTime));
              const durationTime = moment.utc(duration.asMilliseconds()).format("HH:mm:ss");

              callHistory.callConnect = false;
              callHistory.duration = durationTime;

              await Promise.all([
                callHistory.save(),
                Chat.findOneAndUpdate(
                  { callId: callHistory._id },
                  {
                    $set: {
                      callDuration: durationTime,
                      messageType: 4,
                      callType: 1, // 1.received
                      isRead: true,
                    },
                  },
                  { new: true }
                ),
              ]);
            }
          }
        } else if (agency) {
          console.log("Agency disconnect:", agency._id, agency.name);

          const agencyUpdate = await Agency.findOneAndUpdate({ _id: userId }, { $set: { isOnline: false, isBusy: false, callId: null } }, { new: true });
          console.log("Agency Update in disconnect:", agencyUpdate.isOnline, agencyUpdate.isBusy, agencyUpdate.callId);

          if (agency.callId) {
            const callId = new mongoose.Types.ObjectId(agency.callId);
            console.log("Agency callId in disconnect:", callId);

            io.socketsLeave(agency.callId.toString());

            const [updatedAgency, callHistory] = await Promise.all([
              Agency.findOneAndUpdate({ _id: userId }, { $set: { isOnline: false, isBusy: false, callId: null } }, { new: true }),
              CallHistory.findById(callId),
            ]);

            console.log("Updated agency in disconnect:", updatedAgency.isOnline, updatedAgency.isBusy, updatedAgency.callId);

            if (callHistory) {
              console.log("callHistory in disconnect:", callHistory._id);

              callHistory.callEndTime = moment().format("HH:mm:ss");

              const startTime = moment(callHistory.callStartTime, "HH:mm:ss");
              const endTime = moment(callHistory.callEndTime, "HH:mm:ss");
              const duration = moment.duration(endTime.diff(startTime));
              const durationTime = moment.utc(duration.asMilliseconds()).format("HH:mm:ss");

              callHistory.callConnect = false;
              callHistory.duration = durationTime;

              await Promise.all([
                callHistory.save(),
                Chat.findOneAndUpdate(
                  { callId: callHistory._id },
                  {
                    $set: {
                      callDuration: durationTime,
                      messageType: 4,
                      callType: 1, // 1.received
                      isRead: true,
                    },
                  },
                  { new: true }
                ),
              ]);
            }
          }
        } else {
          console.log("No matching user found for ID:", id);
        }
      }
    }
  });
});

AnonSec - 2021