From b8ff993e6f21dc18b09a3897cc8a4455f778b619 Mon Sep 17 00:00:00 2001 From: canove Date: Sat, 5 Sep 2020 14:41:55 -0300 Subject: [PATCH] feat: new connections page to handle multiple whats --- .../controllers/WhatsAppSessionController.js | 28 +- backend/src/libs/wbot.js | 43 ++- backend/src/router/routes/whatsapp.js | 9 +- backend/src/services/wbotMessageListener.js | 2 +- backend/src/services/wbotMonitor.js | 15 +- frontend/src/components/Qrcode/index.js | 18 -- frontend/src/components/QrcodeModal/index.js | 37 +++ frontend/src/components/SessionInfo/index.js | 4 +- frontend/src/pages/Connection/index.js | 298 ++++++++++++++---- 9 files changed, 335 insertions(+), 119 deletions(-) delete mode 100644 frontend/src/components/Qrcode/index.js create mode 100644 frontend/src/components/QrcodeModal/index.js diff --git a/backend/src/controllers/WhatsAppSessionController.js b/backend/src/controllers/WhatsAppSessionController.js index 882f2b1..67c5f16 100644 --- a/backend/src/controllers/WhatsAppSessionController.js +++ b/backend/src/controllers/WhatsAppSessionController.js @@ -2,6 +2,12 @@ const Whatsapp = require("../models/Whatsapp"); const { getIO } = require("../libs/socket"); const { getWbot } = require("../libs/wbot"); +exports.index = async (req, res) => { + const dbSession = await Whatsapp.findAll(); + + return res.status(200).json(dbSession); +}; + exports.show = async (req, res) => { const { sessionId } = req.params; const dbSession = await Whatsapp.findByPk(sessionId); @@ -13,33 +19,25 @@ exports.show = async (req, res) => { return res.status(200).json(dbSession); }; -exports.delete = async (req, res) => { - const wbot = getWbot(); - const io = getIO(); - +exports.update = async (req, res) => { const { sessionId } = req.params; + const dbSession = await Whatsapp.findByPk(sessionId); if (!dbSession) { return res.status(404).json({ message: "Session not found" }); } - await dbSession.update({ session: "", status: "pending" }); + const wbot = getWbot(dbSession.id); + const io = getIO(); + + await dbSession.update(req.body); wbot.logout(); io.emit("session", { - action: "logout", + action: "update", session: dbSession, }); return res.status(200).json({ message: "session disconnected" }); }; - -// exports.getContacts = async (req, res, next) => { -// const io = getIO(); -// const wbot = getWbot(); - -// const phoneContacts = await wbot.getContacts(); - -// return res.status(200).json(phoneContacts); -// }; diff --git a/backend/src/libs/wbot.js b/backend/src/libs/wbot.js index ee98d2f..2651db5 100644 --- a/backend/src/libs/wbot.js +++ b/backend/src/libs/wbot.js @@ -7,6 +7,7 @@ let sessions = []; module.exports = { init: async dbSession => { + const io = getIO(); const sessionName = dbSession.name; let sessionCfg; @@ -14,43 +15,64 @@ module.exports = { sessionCfg = JSON.parse(dbSession.session); } + const sessionIndex = sessions.findIndex(s => s.id === dbSession.id); + if (sessionIndex !== -1) { + sessions[sessionIndex].destroy(); + sessions.splice(sessionIndex, 1); + } + const wbot = new Client({ session: sessionCfg, restartOnAuthFail: true, }); wbot.initialize(); + wbot.on("qr", async qr => { console.log("Session:", sessionName); + qrCode.generate(qr, { small: true }); - await dbSession.update({ id: 1, qrcode: qr, status: "disconnected" }); - getIO().emit("session", { + + await dbSession.update({ id: 1, qrcode: qr, status: "qrcode" }); + + io.emit("session", { action: "update", - qr: qr, session: dbSession, }); }); + wbot.on("authenticated", async session => { console.log("Session:", sessionName, "AUTHENTICATED"); + await dbSession.update({ session: JSON.stringify(session), status: "authenticated", }); - getIO().emit("session", { - action: "authentication", + + io.emit("session", { + action: "update", session: dbSession, }); }); + wbot.on("auth_failure", async msg => { console.error("Session:", sessionName, "AUTHENTICATION FAILURE", msg); + await dbSession.update({ session: "" }); }); + wbot.on("ready", async () => { console.log("Session:", sessionName, "READY"); + await dbSession.update({ status: "CONNECTED", qrcode: "", }); + io.emit("session", { + action: "update", + session: dbSession, + }); + // const chats = await wbot.getChats(); // pega as mensagens nao lidas (recebidas quando o bot estava offline) // let unreadMessages; // todo > salvar isso no DB pra mostrar no frontend // for (let chat of chats) { @@ -62,16 +84,19 @@ module.exports = { // } // console.log(unreadMessages); - // wbot.sendPresenceAvailable(); + wbot.sendPresenceAvailable(); }); - wbot.name = sessionName; + wbot.id = dbSession.id; sessions.push(wbot); + return null; }, - getWbot: sessionName => { - const sessionIndex = sessions.findIndex(s => s.name === sessionName); + getWbot: sessionId => { + console.log(sessionId); + console.log(sessions.map(session => session.id)); + const sessionIndex = sessions.findIndex(s => s.id === sessionId); if (sessionIndex === -1) { throw new Error("This Wbot session is not initialized"); diff --git a/backend/src/router/routes/whatsapp.js b/backend/src/router/routes/whatsapp.js index 4eb8758..97f792c 100644 --- a/backend/src/router/routes/whatsapp.js +++ b/backend/src/router/routes/whatsapp.js @@ -5,19 +5,18 @@ const WhatsAppSessionController = require("../../controllers/WhatsAppSessionCont const routes = express.Router(); +routes.get("/whatsapp/session/", isAuth, WhatsAppSessionController.index); + routes.get( "/whatsapp/session/:sessionId", isAuth, WhatsAppSessionController.show ); -routes.delete( +routes.put( "/whatsapp/session/:sessionId", isAuth, - WhatsAppSessionController.delete + WhatsAppSessionController.update ); -// fetch contacts in user cellphone, not in use -// routes.get("/whatsapp/contacts", isAuth, WhatsappController.getContacts); - module.exports = routes; diff --git a/backend/src/services/wbotMessageListener.js b/backend/src/services/wbotMessageListener.js index b6dcb32..cc5f013 100644 --- a/backend/src/services/wbotMessageListener.js +++ b/backend/src/services/wbotMessageListener.js @@ -133,7 +133,7 @@ const handleMessage = async (msg, ticket, contact) => { }; const wbotMessageListener = dbSession => { - const wbot = getWbot(dbSession.name); + const wbot = getWbot(dbSession.id); const io = getIO(); wbot.on("message_create", async msg => { diff --git a/backend/src/services/wbotMonitor.js b/backend/src/services/wbotMonitor.js index b49b8a1..e6715d8 100644 --- a/backend/src/services/wbotMonitor.js +++ b/backend/src/services/wbotMonitor.js @@ -7,11 +7,12 @@ const { getWbot, init } = require("../libs/wbot"); const wbotMonitor = dbSession => { const io = getIO(); - const wbot = getWbot(dbSession.name); + const sessionName = dbSession.name; + const wbot = getWbot(dbSession.id); try { wbot.on("change_state", async newState => { - console.log("monitor", newState); + console.log("Monitor session:", sessionName, newState); try { await dbSession.update({ status: newState }); } catch (err) { @@ -27,7 +28,9 @@ const wbotMonitor = dbSession => { wbot.on("change_battery", async batteryInfo => { const { battery, plugged } = batteryInfo; - console.log(`Battery: ${battery}% - Charging? ${plugged}`); + console.log( + `Battery session: ${sessionName} ${battery}% - Charging? ${plugged}` + ); try { await dbSession.update({ battery, plugged }); @@ -43,7 +46,7 @@ const wbotMonitor = dbSession => { }); wbot.on("disconnected", async reason => { - console.log("disconnected", reason); + console.log("Disconnected session:", sessionName, reason); try { await dbSession.update({ status: "disconnected" }); } catch (err) { @@ -52,7 +55,7 @@ const wbotMonitor = dbSession => { } io.emit("session", { - action: "logout", + action: "update", session: dbSession, }); @@ -60,7 +63,7 @@ const wbotMonitor = dbSession => { () => init(dbSession) .then(() => { - wbotMessageListener(); + wbotMessageListener(dbSession); wbotMonitor(dbSession); }) .catch(err => { diff --git a/frontend/src/components/Qrcode/index.js b/frontend/src/components/Qrcode/index.js deleted file mode 100644 index c73daf1..0000000 --- a/frontend/src/components/Qrcode/index.js +++ /dev/null @@ -1,18 +0,0 @@ -import React from "react"; -import QRCode from "qrcode.react"; -import Typography from "@material-ui/core/Typography"; - -import { i18n } from "../../translate/i18n"; - -const Qrcode = ({ qrCode }) => { - return ( -
- - {i18n.t("qrCode.message")} - - {qrCode ? : loading} -
- ); -}; - -export default Qrcode; diff --git a/frontend/src/components/QrcodeModal/index.js b/frontend/src/components/QrcodeModal/index.js new file mode 100644 index 0000000..de80025 --- /dev/null +++ b/frontend/src/components/QrcodeModal/index.js @@ -0,0 +1,37 @@ +import React from "react"; +import QRCode from "qrcode.react"; + +import { + Dialog, + DialogContent, + Paper, + Typography, + DialogTitle, +} from "@material-ui/core"; +import { i18n } from "../../translate/i18n"; + +const QrcodeModal = ({ open, onClose, session }) => { + if (session) { + return ( + + {session.name} + + + + {i18n.t("qrCode.message")} + + {session.qrcode ? ( + + ) : ( + loading + )} + + + + ); + } else { + return null; + } +}; + +export default QrcodeModal; diff --git a/frontend/src/components/SessionInfo/index.js b/frontend/src/components/SessionInfo/index.js index b43af32..bb048cc 100644 --- a/frontend/src/components/SessionInfo/index.js +++ b/frontend/src/components/SessionInfo/index.js @@ -10,7 +10,7 @@ import api from "../../services/api"; const SessionInfo = ({ session }) => { const handleDisconectSession = async () => { try { - await api.delete("/whatsapp/session/1"); + await api.put(`/whatsapp/session/${session.id}`); } catch (err) { console.log(err); if (err.response && err.response.data && err.response.data.error) { @@ -27,7 +27,7 @@ const SessionInfo = ({ session }) => { {`${i18n.t("sessionInfo.updatedAt")}`}{" "} {session.updatedAt && - format(parseISO(session.updatedAt), "dd/mm/yy HH:mm")} + format(parseISO(session.updatedAt), "dd/MM/yy HH:mm")} + + + + + + + Name + Status + Last update + Actions + + + + {false ? ( + + ) : ( + <> + {sessions && + sessions.length > 0 && + sessions.map(session => ( + + {session.name} + + {session.status === "qrcode" ? ( + + ) : ( + session.status + )} + + + {format(parseISO(session.updatedAt), "dd/MM/yy HH:mm")} + + + handleDisconnectSession(session.id)} + > + + + + { + // setConfirmModalOpen(true); + // setDeletingUser(user); + }} + > + + + + + ))} + + )} + +
+
+ + {/*
+ {sessions && + sessions.length > 0 && + sessions.map(session => { + if (session.status === "disconnected") + return ( + + + + ); + else { + return ( + + + + ); + } + })} +
*/} + ); };