From cb3ba0925213990c0698f782dcce216d75729ae3 Mon Sep 17 00:00:00 2001 From: canove Date: Sun, 20 Sep 2020 14:06:20 -0300 Subject: [PATCH] migrated wbot initialization to typescript --- backend/src/@types/WAWebJS.d.ts | 5 + backend/src/@types/express.d.ts | 6 +- backend/src/@types/qrcode-terminal.d.ts | 1 + backend/src/libs/wbot.js | 110 ---------- backend/src/libs/wbot.ts | 107 +++++++++ backend/src/server.ts | 34 +-- .../WbotServices/wbotMessageListener.js | 206 ++++++++++++++++++ .../{ => WbotServices}/wbotMonitor.js | 0 backend/src/services/wbotMessageListener.js | 206 ------------------ backend/yarn-error.log | 53 ++++- 10 files changed, 383 insertions(+), 345 deletions(-) create mode 100644 backend/src/@types/WAWebJS.d.ts create mode 100644 backend/src/@types/qrcode-terminal.d.ts delete mode 100644 backend/src/libs/wbot.js create mode 100644 backend/src/libs/wbot.ts create mode 100644 backend/src/services/WbotServices/wbotMessageListener.js rename backend/src/services/{ => WbotServices}/wbotMonitor.js (100%) delete mode 100644 backend/src/services/wbotMessageListener.js diff --git a/backend/src/@types/WAWebJS.d.ts b/backend/src/@types/WAWebJS.d.ts new file mode 100644 index 0000000..0d17ab2 --- /dev/null +++ b/backend/src/@types/WAWebJS.d.ts @@ -0,0 +1,5 @@ +declare namespace WAWebJS { + export interface ClientInfo { + meuId: number; + } +} diff --git a/backend/src/@types/express.d.ts b/backend/src/@types/express.d.ts index 204f2e0..3315ef3 100644 --- a/backend/src/@types/express.d.ts +++ b/backend/src/@types/express.d.ts @@ -1,5 +1,5 @@ declare namespace Express { - export interface Request { - user: { id: string; profile: string }; - } + export interface Request { + user: { id: string; profile: string }; + } } diff --git a/backend/src/@types/qrcode-terminal.d.ts b/backend/src/@types/qrcode-terminal.d.ts new file mode 100644 index 0000000..3b59fed --- /dev/null +++ b/backend/src/@types/qrcode-terminal.d.ts @@ -0,0 +1 @@ +declare module "qrcode-terminal"; diff --git a/backend/src/libs/wbot.js b/backend/src/libs/wbot.js deleted file mode 100644 index 6ba443d..0000000 --- a/backend/src/libs/wbot.js +++ /dev/null @@ -1,110 +0,0 @@ -const qrCode = require("qrcode-terminal"); -const { Client } = require("whatsapp-web.js"); -const Whatsapp = require("../models/Whatsapp"); -const { getIO } = require("../libs/socket"); - -let sessions = []; - -module.exports = { - initWbot: async whatsapp => { - try { - const io = getIO(); - const sessionName = whatsapp.name; - let sessionCfg; - - if (whatsapp && whatsapp.session) { - sessionCfg = JSON.parse(whatsapp.session); - } - - const sessionIndex = sessions.findIndex(s => s.id === whatsapp.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 whatsapp.update({ qrcode: qr, status: "qrcode" }); - - io.emit("whatsappSession", { - action: "update", - session: whatsapp - }); - }); - - wbot.on("authenticated", async session => { - console.log("Session:", sessionName, "AUTHENTICATED"); - - await whatsapp.update({ - session: JSON.stringify(session), - status: "authenticated" - }); - - io.emit("whatsappSession", { - action: "update", - session: whatsapp - }); - }); - - wbot.on("auth_failure", async msg => { - console.error("Session:", sessionName, "AUTHENTICATION FAILURE", msg); - - await whatsapp.update({ session: "" }); - }); - - wbot.on("ready", async () => { - console.log("Session:", sessionName, "READY"); - - await whatsapp.update({ - status: "CONNECTED", - qrcode: "" - }); - - io.emit("whatsappSession", { - action: "update", - session: whatsapp - }); - - wbot.sendPresenceAvailable(); - }); - - wbot.id = whatsapp.id; - sessions.push(wbot); - } catch (err) { - console.log(err); - } - - return null; - }, - - getWbot: whatsappId => { - const sessionIndex = sessions.findIndex(s => s.id === whatsappId); - - if (sessionIndex === -1) { - console.log("This Wbot session is not initialized"); - return null; - } - return sessions[sessionIndex]; - }, - - removeWbot: whatsappId => { - try { - const sessionIndex = sessions.findIndex(s => s.id === whatsappId); - if (sessionIndex !== -1) { - sessions[sessionIndex].destroy(); - sessions.splice(sessionIndex, 1); - } - } catch (err) { - console.log(err); - } - } -}; diff --git a/backend/src/libs/wbot.ts b/backend/src/libs/wbot.ts new file mode 100644 index 0000000..4cbf5dd --- /dev/null +++ b/backend/src/libs/wbot.ts @@ -0,0 +1,107 @@ +import qrCode from "qrcode-terminal"; +import { Client } from "whatsapp-web.js"; +import { getIO } from "./socket"; +import Whatsapp from "../models/Whatsapp"; + +const sessions: Client[] = []; + +export const initWbot = async (whatsapp: Whatsapp): Promise => { + console.log("starting"); + try { + const io = getIO(); + const sessionName = whatsapp.name; + let sessionCfg; + + if (whatsapp && whatsapp.session) { + sessionCfg = JSON.parse(whatsapp.session); + } + + const sessionIndex = sessions.findIndex(s => s.id === whatsapp.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 whatsapp.update({ qrcode: qr, status: "qrcode" }); + + io.emit("whatsappSession", { + action: "update", + session: whatsapp + }); + }); + + wbot.on("authenticated", async session => { + console.log("Session:", sessionName, "AUTHENTICATED"); + + await whatsapp.update({ + session: JSON.stringify(session), + status: "authenticated" + }); + + io.emit("whatsappSession", { + action: "update", + session: whatsapp + }); + }); + + wbot.on("auth_failure", async msg => { + console.error("Session:", sessionName, "AUTHENTICATION FAILURE", msg); + + await whatsapp.update({ session: "" }); + }); + + wbot.on("ready", async () => { + console.log("Session:", sessionName, "READY"); + + await whatsapp.update({ + status: "CONNECTED", + qrcode: "" + }); + + io.emit("whatsappSession", { + action: "update", + session: whatsapp + }); + + wbot.sendPresenceAvailable(); + }); + + wbot.id = whatsapp.id; + sessions.push(wbot); + } catch (err) { + console.log(err); + } +}; + +export const getWbot = (whatsappId: number): Client | null => { + const sessionIndex = sessions.findIndex(s => s.id === whatsappId); + + if (sessionIndex === -1) { + console.log("This Wbot session is not initialized"); + return null; + } + return sessions[sessionIndex]; +}; + +export const removeWbot = (whatsappId: number): void => { + try { + const sessionIndex = sessions.findIndex(s => s.id === whatsappId); + if (sessionIndex !== -1) { + sessions[sessionIndex].destroy(); + sessions.splice(sessionIndex, 1); + } + } catch (err) { + console.log(err); + } +}; diff --git a/backend/src/server.ts b/backend/src/server.ts index 93519f2..e16dcfd 100644 --- a/backend/src/server.ts +++ b/backend/src/server.ts @@ -11,13 +11,13 @@ import AppError from "./errors/AppError"; import routes from "./routes"; import { initIO } from "./libs/socket"; import "./database"; +import { initWbot } from "./libs/wbot"; // import path from "path"; -// const { initWbot } = require("./libs/wbot"); // const wbotMessageListener = require("./services/wbotMessageListener"); // const wbotMonitor = require("./services/wbotMonitor"); -// const Whatsapp = require("./models/Whatsapp"); +import Whatsapp from "./models/Whatsapp"; Sentry.init({ dsn: process.env.SENTRY_DSN }); @@ -62,21 +62,21 @@ io.on("connection", socket => { }); }); -// const startWhatsAppSessions = async () => { -// const whatsapps = await Whatsapp.findAll(); - -// if (whatsapps.length > 0) { -// whatsapps.forEach(whatsapp => { -// initWbot(whatsapp) -// .then(() => { -// wbotMessageListener(whatsapp); -// wbotMonitor(whatsapp); -// }) -// .catch(err => console.log(err)); -// }); -// } -// }; -// startWhatsAppSessions(); +const startWhatsAppSessions = async () => { + const whatsapps = await Whatsapp.findAll(); + if (whatsapps.length > 0) { + whatsapps.forEach(whatsapp => { + initWbot(whatsapp) + .then(() => { + console.log("initialized!!"); + // wbotMessageListener(whatsapp); + // wbotMonitor(whatsapp); + }) + .catch(err => console.log(err)); + }); + } +}; +startWhatsAppSessions(); // app.use(Sentry.Handlers.errorHandler()); diff --git a/backend/src/services/WbotServices/wbotMessageListener.js b/backend/src/services/WbotServices/wbotMessageListener.js new file mode 100644 index 0000000..d8e6755 --- /dev/null +++ b/backend/src/services/WbotServices/wbotMessageListener.js @@ -0,0 +1,206 @@ +const path = require("path"); +const fs = require("fs"); +const { Op } = require("sequelize"); +const { subHours } = require("date-fns"); +const Sentry = require("@sentry/node"); + +const Contact = require("../models/Contact"); +const Ticket = require("../models/Ticket"); +const Message = require("../models/Message"); +const Whatsapp = require("../models/Whatsapp"); + +const { getIO } = require("../libs/socket"); +const { getWbot, initWbot } = require("../libs/wbot"); + +const verifyContact = async (msgContact, profilePicUrl) => { + let contact = await Contact.findOne({ + where: { number: msgContact.number } + }); + + if (contact) { + await contact.update({ profilePicUrl: profilePicUrl }); + } else { + contact = await Contact.create({ + name: msgContact.pushname || msgContact.number.toString(), + number: msgContact.number, + profilePicUrl: profilePicUrl + }); + } + + return contact; +}; + +const verifyTicket = async (contact, whatsappId) => { + let ticket = await Ticket.findOne({ + where: { + status: { + [Op.or]: ["open", "pending"] + }, + contactId: contact.id + } + }); + + if (!ticket) { + ticket = await Ticket.findOne({ + where: { + createdAt: { [Op.between]: [subHours(new Date(), 2), new Date()] }, + contactId: contact.id + }, + order: [["createdAt", "DESC"]] + }); + + if (ticket) { + await ticket.update({ status: "pending", userId: null }); + } + } + + if (!ticket) { + ticket = await Ticket.create({ + contactId: contact.id, + status: "pending", + whatsappId + }); + } + + return ticket; +}; + +const handlMedia = async (msg, ticket) => { + const media = await msg.downloadMedia(); + let newMessage; + console.log("criando midia"); + if (media) { + if (!media.filename) { + let ext = media.mimetype.split("/")[1].split(";")[0]; + media.filename = `${new Date().getTime()}.${ext}`; + } + + fs.writeFile( + path.join(__dirname, "..", "..", "public", media.filename), + media.data, + "base64", + err => { + console.log(err); + } + ); + + newMessage = await ticket.createMessage({ + id: msg.id.id, + body: msg.body || media.filename, + fromMe: msg.fromMe, + mediaUrl: media.filename, + mediaType: media.mimetype.split("/")[0] + }); + await ticket.update({ lastMessage: msg.body || media.filename }); + } + + return newMessage; +}; + +const handleMessage = async (msg, ticket, contact) => { + const io = getIO(); + let newMessage; + + if (msg.hasMedia) { + newMessage = await handlMedia(msg, ticket); + } else { + newMessage = await ticket.createMessage({ + id: msg.id.id, + body: msg.body, + fromMe: msg.fromMe + }); + await ticket.update({ lastMessage: msg.body }); + } + + const serializedMessage = { + ...newMessage.dataValues, + mediaUrl: `${ + newMessage.mediaUrl + ? `${process.env.BACKEND_URL}:${process.env.PROXY_PORT}/public/${newMessage.mediaUrl}` + : "" + }` + }; + + const serializaedTicket = { + ...ticket.dataValues, + contact: contact + }; + + io.to(ticket.id).to("notification").emit("appMessage", { + action: "create", + message: serializedMessage, + ticket: serializaedTicket, + contact: contact + }); +}; + +const wbotMessageListener = whatsapp => { + const whatsappId = whatsapp.id; + const wbot = getWbot(whatsappId); + const io = getIO(); + + wbot.on("message_create", async msg => { + // console.log(msg); + + if ( + msg.from === "status@broadcast" || + msg.type === "location" || + msg.type === "call_log" || + msg.author != null // Ignore Group Messages + ) { + return; + } + + try { + let msgContact; + + if (msg.fromMe) { + msgContact = await wbot.getContactById(msg.to); + } else { + msgContact = await msg.getContact(); + } + + const profilePicUrl = await msgContact.getProfilePicUrl(); + const contact = await verifyContact(msgContact, profilePicUrl); + const ticket = await verifyTicket(contact, whatsappId); + + //return if message was already created by messageController + if (msg.fromMe) { + const alreadyExists = await Message.findOne({ + where: { id: msg.id.id } + }); + + if (alreadyExists) { + return; + } + } + + await handleMessage(msg, ticket, contact); + } catch (err) { + Sentry.captureException(err); + console.log(err); + } + }); + + wbot.on("message_ack", async (msg, ack) => { + try { + const messageToUpdate = await Message.findOne({ + where: { id: msg.id.id } + }); + if (!messageToUpdate) { + return; + } + await messageToUpdate.update({ ack: ack }); + + io.to(messageToUpdate.ticketId).emit("appMessage", { + action: "update", + message: messageToUpdate + }); + } catch (err) { + Sentry.captureException(err); + console.log(err); + } + }); +}; + +module.exports = wbotMessageListener; diff --git a/backend/src/services/wbotMonitor.js b/backend/src/services/WbotServices/wbotMonitor.js similarity index 100% rename from backend/src/services/wbotMonitor.js rename to backend/src/services/WbotServices/wbotMonitor.js diff --git a/backend/src/services/wbotMessageListener.js b/backend/src/services/wbotMessageListener.js deleted file mode 100644 index aed420d..0000000 --- a/backend/src/services/wbotMessageListener.js +++ /dev/null @@ -1,206 +0,0 @@ -const path = require("path"); -const fs = require("fs"); -const { Op } = require("sequelize"); -const { subHours } = require("date-fns"); -const Sentry = require("@sentry/node"); - -const Contact = require("../models/Contact"); -const Ticket = require("../models/Ticket"); -const Message = require("../models/Message"); -const Whatsapp = require("../models/Whatsapp"); - -const { getIO } = require("../libs/socket"); -const { getWbot, initWbot } = require("../libs/wbot"); - -const verifyContact = async (msgContact, profilePicUrl) => { - let contact = await Contact.findOne({ - where: { number: msgContact.number }, - }); - - if (contact) { - await contact.update({ profilePicUrl: profilePicUrl }); - } else { - contact = await Contact.create({ - name: msgContact.pushname || msgContact.number.toString(), - number: msgContact.number, - profilePicUrl: profilePicUrl, - }); - } - - return contact; -}; - -const verifyTicket = async (contact, whatsappId) => { - let ticket = await Ticket.findOne({ - where: { - status: { - [Op.or]: ["open", "pending"], - }, - contactId: contact.id, - }, - }); - - if (!ticket) { - ticket = await Ticket.findOne({ - where: { - createdAt: { [Op.between]: [subHours(new Date(), 2), new Date()] }, - contactId: contact.id, - }, - order: [["createdAt", "DESC"]], - }); - - if (ticket) { - await ticket.update({ status: "pending", userId: null }); - } - } - - if (!ticket) { - ticket = await Ticket.create({ - contactId: contact.id, - status: "pending", - whatsappId, - }); - } - - return ticket; -}; - -const handlMedia = async (msg, ticket) => { - const media = await msg.downloadMedia(); - let newMessage; - console.log("criando midia"); - if (media) { - if (!media.filename) { - let ext = media.mimetype.split("/")[1].split(";")[0]; - media.filename = `${new Date().getTime()}.${ext}`; - } - - fs.writeFile( - path.join(__dirname, "..", "..", "public", media.filename), - media.data, - "base64", - err => { - console.log(err); - } - ); - - newMessage = await ticket.createMessage({ - id: msg.id.id, - body: msg.body || media.filename, - fromMe: msg.fromMe, - mediaUrl: media.filename, - mediaType: media.mimetype.split("/")[0], - }); - await ticket.update({ lastMessage: msg.body || media.filename }); - } - - return newMessage; -}; - -const handleMessage = async (msg, ticket, contact) => { - const io = getIO(); - let newMessage; - - if (msg.hasMedia) { - newMessage = await handlMedia(msg, ticket); - } else { - newMessage = await ticket.createMessage({ - id: msg.id.id, - body: msg.body, - fromMe: msg.fromMe, - }); - await ticket.update({ lastMessage: msg.body }); - } - - const serializedMessage = { - ...newMessage.dataValues, - mediaUrl: `${ - newMessage.mediaUrl - ? `${process.env.BACKEND_URL}:${process.env.PROXY_PORT}/public/${newMessage.mediaUrl}` - : "" - }`, - }; - - const serializaedTicket = { - ...ticket.dataValues, - contact: contact, - }; - - io.to(ticket.id).to("notification").emit("appMessage", { - action: "create", - message: serializedMessage, - ticket: serializaedTicket, - contact: contact, - }); -}; - -const wbotMessageListener = whatsapp => { - const whatsappId = whatsapp.id; - const wbot = getWbot(whatsappId); - const io = getIO(); - - wbot.on("message_create", async msg => { - // console.log(msg); - - if ( - msg.from === "status@broadcast" || - msg.type === "location" || - msg.type === "call_log" || - msg.author != null // Ignore Group Messages - ) { - return; - } - - try { - let msgContact; - - if (msg.fromMe) { - msgContact = await wbot.getContactById(msg.to); - } else { - msgContact = await msg.getContact(); - } - - const profilePicUrl = await msgContact.getProfilePicUrl(); - const contact = await verifyContact(msgContact, profilePicUrl); - const ticket = await verifyTicket(contact, whatsappId); - - //return if message was already created by messageController - if (msg.fromMe) { - const alreadyExists = await Message.findOne({ - where: { id: msg.id.id }, - }); - - if (alreadyExists) { - return; - } - } - - await handleMessage(msg, ticket, contact); - } catch (err) { - Sentry.captureException(err); - console.log(err); - } - }); - - wbot.on("message_ack", async (msg, ack) => { - try { - const messageToUpdate = await Message.findOne({ - where: { id: msg.id.id }, - }); - if (!messageToUpdate) { - return; - } - await messageToUpdate.update({ ack: ack }); - - io.to(messageToUpdate.ticketId).emit("appMessage", { - action: "update", - message: messageToUpdate, - }); - } catch (err) { - Sentry.captureException(err); - console.log(err); - } - }); -}; - -module.exports = wbotMessageListener; diff --git a/backend/yarn-error.log b/backend/yarn-error.log index 5674f65..ff7a8d9 100644 --- a/backend/yarn-error.log +++ b/backend/yarn-error.log @@ -1,8 +1,8 @@ Arguments: - /usr/bin/node /usr/share/yarn/bin/yarn.js sequelize db:migrate + /usr/bin/node /usr/share/yarn/bin/yarn.js add -D @types/qrcode-terminal PATH: - /home/canove/.vscode-server/bin/a0479759d6e9ea56afa657e454193f72aef85bd0/bin:/home/canove/.zinit/polaris/sbin:/home/canove/.zinit/polaris/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/mnt/c/Windows/system32:/mnt/c/Windows:/mnt/c/Windows/System32/Wbem:/mnt/c/Windows/System32/WindowsPowerShell/v1.0/:/mnt/c/Windows/System32/OpenSSH/:/mnt/c/ProgramData/chocolatey/bin:/mnt/c/Program Files/Microsoft VS Code/bin:/mnt/c/Program Files (x86)/GNU/GnuPG/pub:/mnt/c/Users/cassio/AppData/Local/Microsoft/WindowsApps:/mnt/c/Users/cassio/AppData/Local/GitHubDesktop/bin + /home/canove/.vscode-server/bin/58bb7b2331731bf72587010e943852e13e6fd3cf/bin:/home/canove/.zinit/polaris/sbin:/home/canove/.zinit/polaris/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/mnt/c/Windows/system32:/mnt/c/Windows:/mnt/c/Windows/System32/Wbem:/mnt/c/Windows/System32/WindowsPowerShell/v1.0/:/mnt/c/Windows/System32/OpenSSH/:/mnt/c/ProgramData/chocolatey/bin:/mnt/c/Program Files/Microsoft VS Code/bin:/mnt/c/Program Files (x86)/GNU/GnuPG/pub:/mnt/c/Users/cassio/AppData/Local/Microsoft/WindowsApps:/mnt/c/Users/cassio/AppData/Local/GitHubDesktop/bin Yarn version: 1.22.4 @@ -14,12 +14,17 @@ Platform: linux x64 Trace: - SyntaxError: /home/canove/code_learn/econowhats/backend/package.json: Unexpected token / in JSON at position 222 - at JSON.parse () - at /usr/share/yarn/lib/cli.js:1625:59 - at Generator.next () - at step (/usr/share/yarn/lib/cli.js:310:30) - at /usr/share/yarn/lib/cli.js:321:13 + Error: https://registry.yarnpkg.com/@types%2fqrcode-terminal: Not found + at Request.params.callback [as _callback] (/usr/share/yarn/lib/cli.js:66987:18) + at Request.self.callback (/usr/share/yarn/lib/cli.js:140748:22) + at Request.emit (events.js:315:20) + at Request. (/usr/share/yarn/lib/cli.js:141720:10) + at Request.emit (events.js:315:20) + at IncomingMessage. (/usr/share/yarn/lib/cli.js:141642:12) + at Object.onceWrapper (events.js:421:28) + at IncomingMessage.emit (events.js:327:22) + at endReadableNT (_stream_readable.js:1221:12) + at processTicksAndRejections (internal/process/task_queues.js:84:21) npm manifest: { @@ -29,8 +34,8 @@ npm manifest: "main": "index.js", "scripts": { "build": "tsc", + "start": "nodemon dist/server.js", "dev:server": "ts-node-dev --respawn --transpile-only --ignore node_modules src/server.ts" - // "sequelize": "ts-node-dev ./node_modules/.bin/sequelize" }, "author": "", "license": "MIT", @@ -55,11 +60,14 @@ npm manifest: "yup": "^0.29.3" }, "devDependencies": { + "@types/bcryptjs": "^2.4.2", "@types/bluebird": "^3.5.32", "@types/cors": "^2.8.7", "@types/express": "^4.17.8", + "@types/jsonwebtoken": "^8.5.0", "@types/multer": "^1.4.4", "@types/node": "^14.10.1", + "@types/socket.io": "^2.1.11", "@types/validator": "^13.1.0", "@types/yup": "^0.29.7", "@typescript-eslint/eslint-plugin": "^4.1.0", @@ -235,6 +243,11 @@ Lockfile: dependencies: defer-to-connect "^1.0.1" + "@types/bcryptjs@^2.4.2": + version "2.4.2" + resolved "https://registry.yarnpkg.com/@types/bcryptjs/-/bcryptjs-2.4.2.tgz#e3530eac9dd136bfdfb0e43df2c4c5ce1f77dfae" + integrity sha512-LiMQ6EOPob/4yUL66SZzu6Yh77cbzJFYll+ZfaPiPPFswtIlA/Fs1MzdKYA7JApHU49zQTbJGX3PDmCpIdDBRQ== + "@types/bluebird@^3.5.32": version "3.5.32" resolved "https://registry.yarnpkg.com/@types/bluebird/-/bluebird-3.5.32.tgz#381e7b59e39f010d20bbf7e044e48f5caf1ab620" @@ -267,6 +280,13 @@ Lockfile: dependencies: "@types/express" "*" + "@types/engine.io@*": + version "3.1.4" + resolved "https://registry.yarnpkg.com/@types/engine.io/-/engine.io-3.1.4.tgz#3d9472711d179daa7c95c051e50ad411e18a9bdc" + integrity sha512-98rXVukLD6/ozrQ2O80NAlWDGA4INg+tqsEReWJldqyi2fulC9V7Use/n28SWgROXKm6003ycWV4gZHoF8GA6w== + dependencies: + "@types/node" "*" + "@types/express-serve-static-core@*": version "4.17.12" resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.12.tgz#9a487da757425e4f267e7d1c5720226af7f89591" @@ -296,6 +316,13 @@ Lockfile: resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4= + "@types/jsonwebtoken@^8.5.0": + version "8.5.0" + resolved "https://registry.yarnpkg.com/@types/jsonwebtoken/-/jsonwebtoken-8.5.0.tgz#2531d5e300803aa63279b232c014acf780c981c5" + integrity sha512-9bVao7LvyorRGZCw0VmH/dr7Og+NdjYSsKAxB43OQoComFbBgsEpoR9JW6+qSq/ogwVBg8GI2MfAlk4SYI4OLg== + dependencies: + "@types/node" "*" + "@types/mime@*": version "2.0.3" resolved "https://registry.yarnpkg.com/@types/mime/-/mime-2.0.3.tgz#c893b73721db73699943bfc3653b1deb7faa4a3a" @@ -336,6 +363,14 @@ Lockfile: "@types/express-serve-static-core" "*" "@types/mime" "*" + "@types/socket.io@^2.1.11": + version "2.1.11" + resolved "https://registry.yarnpkg.com/@types/socket.io/-/socket.io-2.1.11.tgz#e0d6759880e5f9818d5297a3328b36641bae996b" + integrity sha512-bVprmqPhJMLb9ZCm8g0Xy8kwBFRbnanOWSxzWkDkkIwxTvud5tKMfAJymXX6LQbizUKCS1yima7JM4BeLqjNqA== + dependencies: + "@types/engine.io" "*" + "@types/node" "*" + "@types/strip-bom@^3.0.0": version "3.0.0" resolved "https://registry.yarnpkg.com/@types/strip-bom/-/strip-bom-3.0.0.tgz#14a8ec3956c2e81edb7520790aecf21c290aebd2"