mirror of
https://github.com/cheveguerra/whaticket-community.git
synced 2026-04-17 19:37:02 +00:00
maintenance commit
This commit is contained in:
3
backend/.gitignore
vendored
3
backend/.gitignore
vendored
@@ -1 +1,2 @@
|
||||
node_modules
|
||||
node_modules
|
||||
public/*
|
||||
@@ -1,6 +1,9 @@
|
||||
const express = require("express");
|
||||
const path = require("path");
|
||||
const cors = require("cors");
|
||||
const sequelize = require("./util/database");
|
||||
const multer = require("multer");
|
||||
|
||||
const wBot = require("./controllers/wbot");
|
||||
const Contact = require("./models/Contact");
|
||||
const wbotMessageListener = require("./controllers/wbotMessageListener");
|
||||
@@ -11,8 +14,19 @@ const AuthRoutes = require("./routes/auth");
|
||||
|
||||
const app = express();
|
||||
|
||||
const fileStorage = multer.diskStorage({
|
||||
destination: (req, file, cb) => {
|
||||
cb(null, "public");
|
||||
},
|
||||
filename: (req, file, cb) => {
|
||||
cb(null, new Date().getTime() + "-" + file.originalname);
|
||||
},
|
||||
});
|
||||
|
||||
app.use(cors());
|
||||
app.use(express.json());
|
||||
app.use(multer({ storage: fileStorage }).single("media"));
|
||||
app.use("/public", express.static(path.join(__dirname, "public")));
|
||||
|
||||
app.use(messageRoutes);
|
||||
app.use(ContactRoutes);
|
||||
@@ -32,7 +46,18 @@ sequelize
|
||||
const server = app.listen(8080);
|
||||
const io = require("./socket").init(server);
|
||||
io.on("connection", socket => {
|
||||
console.log("Cliente Connected");
|
||||
console.log("Client Connected");
|
||||
socket.on("joinChatBox", contactId => {
|
||||
socket.join(contactId);
|
||||
});
|
||||
|
||||
socket.on("joinNotification", () => {
|
||||
socket.join("notification");
|
||||
});
|
||||
|
||||
socket.on("disconnect", () => {
|
||||
console.log("Client disconnected");
|
||||
});
|
||||
});
|
||||
|
||||
wBot.init();
|
||||
|
||||
@@ -49,7 +49,7 @@ exports.login = async (req, res, next) => {
|
||||
const token = jwt.sign(
|
||||
{ email: loadedUser.email, userId: loadedUser.id },
|
||||
"mysecret",
|
||||
{ expiresIn: "1h" }
|
||||
{ expiresIn: "24h" }
|
||||
);
|
||||
return res
|
||||
.status(200)
|
||||
|
||||
@@ -1,18 +1,32 @@
|
||||
const Contact = require("../models/Contact");
|
||||
const Message = require("../models/Message");
|
||||
// const io = require("../socket");
|
||||
const Sequelize = require("sequelize");
|
||||
|
||||
exports.getContacts = async (req, res) => {
|
||||
// const contacts = await Contact.findAll();
|
||||
const contacts = await Contact.findAll({
|
||||
include: {
|
||||
model: Message,
|
||||
where: {
|
||||
read: false,
|
||||
try {
|
||||
const contacts = await Contact.findAll({
|
||||
include: { model: Message, attributes: [] },
|
||||
attributes: {
|
||||
include: [
|
||||
[
|
||||
Sequelize.literal(`(
|
||||
SELECT COUNT(*)
|
||||
FROM messages AS message
|
||||
WHERE
|
||||
message.contactId = contact.id
|
||||
AND
|
||||
message.read = 0
|
||||
|
||||
)`),
|
||||
"unreadMessages",
|
||||
],
|
||||
],
|
||||
},
|
||||
required: false,
|
||||
},
|
||||
});
|
||||
order: [[Message, "createdAt", "DESC"]],
|
||||
});
|
||||
|
||||
return res.json(contacts);
|
||||
return res.json(contacts);
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,55 +1,69 @@
|
||||
const fs = require("fs");
|
||||
const Message = require("../models/Message");
|
||||
const Contact = require("../models/Contact");
|
||||
const io = require("../socket");
|
||||
|
||||
const wbot = require("./wbot");
|
||||
const { MessageMedia } = require("whatsapp-web.js");
|
||||
|
||||
exports.getContactMessages = async (req, res) => {
|
||||
exports.getContactMessages = async (req, res, next) => {
|
||||
const { contactId } = req.params;
|
||||
const contact = await Contact.findByPk(contactId);
|
||||
|
||||
const contactMessages = await contact.getMessages();
|
||||
try {
|
||||
const contact = await Contact.findByPk(contactId);
|
||||
const contactMessages = await contact.getMessages();
|
||||
|
||||
return res.json(contactMessages);
|
||||
const result = await Message.update(
|
||||
{ read: true },
|
||||
{
|
||||
where: {
|
||||
contactId: contactId,
|
||||
read: false,
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
return res.json(contactMessages);
|
||||
} catch (err) {
|
||||
next(err);
|
||||
}
|
||||
};
|
||||
|
||||
exports.postCreateContactMessage = async (req, res) => {
|
||||
exports.postCreateContactMessage = async (req, res, next) => {
|
||||
const { contactId } = req.params;
|
||||
const message = req.body;
|
||||
const media = req.file;
|
||||
|
||||
const contact = await Contact.findByPk(contactId);
|
||||
try {
|
||||
const contact = await Contact.findByPk(contactId);
|
||||
if (media) {
|
||||
const newMedia = MessageMedia.fromFilePath(req.file.path);
|
||||
message.mediaUrl = req.file.path;
|
||||
if (newMedia.mimetype) {
|
||||
message.mediaType = newMedia.mimetype.split("/")[0];
|
||||
} else {
|
||||
message.mediaType = "other";
|
||||
}
|
||||
|
||||
const newMessage = await contact.createMessage(message);
|
||||
wbot.getWbot().sendMessage(`${contact.number}@c.us`, newMedia);
|
||||
} else {
|
||||
wbot.getWbot().sendMessage(`${contact.number}@c.us`, message.messageBody);
|
||||
}
|
||||
|
||||
if (!newMessage) {
|
||||
return res.status(500).json({ message: "A mensagem não foi criada" });
|
||||
const newMessage = await contact.createMessage(message);
|
||||
if (!newMessage) {
|
||||
const error = new Error("Erro ao inserir a mensagem no banco de dados");
|
||||
error.satusCode = 501;
|
||||
throw error;
|
||||
}
|
||||
|
||||
io.getIO().to(contactId).emit("appMessage", {
|
||||
action: "create",
|
||||
message: newMessage,
|
||||
});
|
||||
|
||||
return res.json({ message: "Mensagem enviada" });
|
||||
} catch (err) {
|
||||
next(err);
|
||||
}
|
||||
|
||||
wbot.getWbot().sendMessage(`${contact.number}@c.us`, message.messageBody);
|
||||
|
||||
io.getIO().emit("appMessage", {
|
||||
action: "create",
|
||||
message: newMessage.dataValues,
|
||||
});
|
||||
|
||||
return res.json(newMessage);
|
||||
};
|
||||
|
||||
exports.postUpdateMessageStatus = async (req, res) => {
|
||||
const { messagesToSetRead } = req.body;
|
||||
|
||||
await Promise.all(
|
||||
messagesToSetRead.map(async message => {
|
||||
await Message.update(
|
||||
{ read: 1 },
|
||||
{
|
||||
where: {
|
||||
id: message.id,
|
||||
},
|
||||
}
|
||||
);
|
||||
})
|
||||
);
|
||||
|
||||
res.json({ message: "Mensagens lidas!" });
|
||||
};
|
||||
|
||||
@@ -1 +1 @@
|
||||
{"WABrowserId":"\"ynZiZqR67F6o3M5nCIE3Ig==\"","WASecretBundle":"{\"key\":\"3kFQ7T0G4sbiCrb3ZwzDKzDdKLo6hObbUfygGby91H0=\",\"encKey\":\"ezpzST8/4752gQLd+Lj+yfZGqwzFqBlkvpelptnJ5dI=\",\"macKey\":\"3kFQ7T0G4sbiCrb3ZwzDKzDdKLo6hObbUfygGby91H0=\"}","WAToken1":"\"9g0Q+hqE6PdVX8yf2m2poDqpN+VB1NDbsSF3bp0xxE0=\"","WAToken2":"\"1@DnfzCyncYsMRZnUA+PnrZfYpux6mUSqrGPAFBgkU8b7NS6mge9SuJ4QDKUvt8HthVmH9mvovbb26zQ==\""}
|
||||
{"WABrowserId":"\"W5pw0Llb60mSeV7WOHnk8A==\"","WASecretBundle":"{\"key\":\"alDLbPjonDFzCh5PEPql9cy59LNh1HFG/AZJVoucuYI=\",\"encKey\":\"FQ1MZ2eIH9hKV4dqFoBYTv1/89aopcMAa4CXgh/9csM=\",\"macKey\":\"alDLbPjonDFzCh5PEPql9cy59LNh1HFG/AZJVoucuYI=\"}","WAToken1":"\"mjiCXmqu33f9L6eQ/8RP/ud+axdbx9y4wDFAqfJD90o=\"","WAToken2":"\"1@o99W6mNitfwQz+tg3dNp4f5/z0mMj3tR/fRgy2wuneqfze+ccCkZ9O8NT15xRlqPwAbgdpT+nJ0krg==\""}
|
||||
@@ -1,38 +1,77 @@
|
||||
const io = require("../socket");
|
||||
const Contact = require("../models/Contact");
|
||||
const path = require("path");
|
||||
const fs = require("fs");
|
||||
|
||||
const wbot = require("./wbot");
|
||||
const { getIO } = require("../socket");
|
||||
const { getWbot } = require("./wbot");
|
||||
|
||||
const wbotMessageListener = () => {
|
||||
wbot.getWbot().on("message", async msg => {
|
||||
getWbot().on("message", async msg => {
|
||||
let newMessage;
|
||||
const msgContact = await msg.getContact();
|
||||
const imageUrl = await msgContact.getProfilePicUrl();
|
||||
try {
|
||||
let contact = await Contact.findOne({
|
||||
where: { number: msgContact.number },
|
||||
});
|
||||
// await contact.update({ imageURL: imageUrl });
|
||||
|
||||
if (!contact) {
|
||||
try {
|
||||
contact = await Contact.create({
|
||||
name: msgContact.number.toString(),
|
||||
name: msgContact.pushname || msgContact.number.toString(),
|
||||
number: msgContact.number,
|
||||
imageUrl: "",
|
||||
imageURL: imageUrl,
|
||||
});
|
||||
io.getIO().emit("contact", {
|
||||
|
||||
contact.dataValues.unreadMessages = 1;
|
||||
|
||||
getIO().emit("contact", {
|
||||
action: "create",
|
||||
contact: contact.dataValues,
|
||||
contact: contact,
|
||||
});
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
}
|
||||
}
|
||||
if (msg.hasMedia) {
|
||||
const media = await msg.downloadMedia();
|
||||
|
||||
const newMessage = await contact.createMessage({
|
||||
messageBody: msg.body,
|
||||
});
|
||||
io.getIO().emit("appMessage", {
|
||||
if (media) {
|
||||
if (!media.filename) {
|
||||
let ext = media.mimetype.split("/")[1].split(";")[0];
|
||||
let aux = Math.random(5).toString();
|
||||
media.filename = aux.split(".")[1] + "." + ext;
|
||||
}
|
||||
|
||||
fs.writeFile(
|
||||
path.join(__dirname, "..", "public", media.filename),
|
||||
media.data,
|
||||
"base64",
|
||||
err => {
|
||||
console.log(err);
|
||||
}
|
||||
);
|
||||
|
||||
newMessage = await contact.createMessage({
|
||||
mediaUrl: path.join("public", media.filename),
|
||||
mediaType: media.mimetype.split("/")[0],
|
||||
messageBody: msg.body || media.filename,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
newMessage = await contact.createMessage({
|
||||
messageBody: msg.body,
|
||||
});
|
||||
}
|
||||
|
||||
getIO().to(contact.id).to("notification").emit("appMessage", {
|
||||
action: "create",
|
||||
message: newMessage.dataValues,
|
||||
message: newMessage,
|
||||
});
|
||||
|
||||
let chat = await msg.getChat();
|
||||
chat.sendSeen();
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ module.exports = (req, res, next) => {
|
||||
const token = req.get("Authorization").split(" ")[1];
|
||||
decodedToken = jwt.verify(token, "mysecret");
|
||||
} catch (err) {
|
||||
err.statusCode = 500;
|
||||
err.statusCode = 401;
|
||||
next(err);
|
||||
}
|
||||
|
||||
|
||||
@@ -5,17 +5,15 @@ const sequelize = require("../util/database");
|
||||
const Message = require("./Message");
|
||||
|
||||
const Contact = sequelize.define("contact", {
|
||||
id: {
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: false,
|
||||
primaryKey: true,
|
||||
autoIncrement: true,
|
||||
},
|
||||
name: { type: Sequelize.STRING(100), allowNull: false },
|
||||
number: { type: Sequelize.STRING(15), allowNull: false },
|
||||
imageURL: { type: Sequelize.STRING(200) },
|
||||
ateraId: Sequelize.INTEGER(),
|
||||
});
|
||||
|
||||
Contact.hasMany(Message);
|
||||
Contact.hasMany(Message, {
|
||||
onDelete: "CASCADE",
|
||||
onUpdate: "RESTRICT",
|
||||
});
|
||||
|
||||
module.exports = Contact;
|
||||
|
||||
@@ -5,6 +5,8 @@ const Message = sequelize.define("message", {
|
||||
userId: { type: Sequelize.INTEGER, defaultValue: 0 },
|
||||
messageBody: { type: Sequelize.STRING(250), allowNull: false },
|
||||
read: { type: Sequelize.BOOLEAN, defaultValue: false },
|
||||
mediaUrl: { type: Sequelize.STRING(250) },
|
||||
mediaType: { type: Sequelize.STRING(250) },
|
||||
});
|
||||
|
||||
module.exports = Message;
|
||||
|
||||
423
backend/package-lock.json
generated
423
backend/package-lock.json
generated
@@ -30,15 +30,19 @@
|
||||
"integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/mime-types": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/mime-types/-/mime-types-2.1.0.tgz",
|
||||
"integrity": "sha1-nKUs2jY/aZxpRmwqbM2q2RPqenM="
|
||||
},
|
||||
"@types/node": {
|
||||
"version": "13.13.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-13.13.5.tgz",
|
||||
"integrity": "sha512-3ySmiBYJPqgjiHA7oEaIo2Rzz0HrOZ7yrNO5HWyaE5q0lQ3BppDZ3N53Miz8bw2I7gh1/zir2MGVZBvpb1zq9g=="
|
||||
"version": "14.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.5.tgz",
|
||||
"integrity": "sha512-90hiq6/VqtQgX8Sp0EzeIsv3r+ellbGj4URKj5j30tLlZvRUpnAe9YbYnjl3pJM93GyXU0tghHhvXHq+5rnCKA=="
|
||||
},
|
||||
"@types/yauzl": {
|
||||
"version": "2.9.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.9.1.tgz",
|
||||
"integrity": "sha512-A1b8SU4D10uoPjwb0lnHmmu8wZhR9d+9o2PKBQT2jU5YPTKsxac6M2qGAdY7VcL+dHHhARVUDmeg0rOrcd9EjA==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"abbrev": {
|
||||
"version": "1.1.1",
|
||||
@@ -106,6 +110,11 @@
|
||||
"picomatch": "^2.0.4"
|
||||
}
|
||||
},
|
||||
"append-field": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz",
|
||||
"integrity": "sha1-HjRA6RXwsSA9I3SOeO3XubW0PlY="
|
||||
},
|
||||
"array-flatten": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
|
||||
@@ -136,6 +145,11 @@
|
||||
"resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz",
|
||||
"integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg="
|
||||
},
|
||||
"base64-js": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz",
|
||||
"integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g=="
|
||||
},
|
||||
"base64id": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz",
|
||||
@@ -160,6 +174,33 @@
|
||||
"integrity": "sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==",
|
||||
"dev": true
|
||||
},
|
||||
"bl": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/bl/-/bl-4.0.2.tgz",
|
||||
"integrity": "sha512-j4OH8f6Qg2bGuWfRiltT2HYGx0e1QcBTrK9KAHNMwMZdQnDZFk0ZSYIpADjYCB3U12nicC5tVJwSIhwOWjb4RQ==",
|
||||
"requires": {
|
||||
"buffer": "^5.5.0",
|
||||
"inherits": "^2.0.4",
|
||||
"readable-stream": "^3.4.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"inherits": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
|
||||
},
|
||||
"readable-stream": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
|
||||
"integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
|
||||
"requires": {
|
||||
"inherits": "^2.0.3",
|
||||
"string_decoder": "^1.1.1",
|
||||
"util-deprecate": "^1.0.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"blob": {
|
||||
"version": "0.0.5",
|
||||
"resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz",
|
||||
@@ -261,6 +302,15 @@
|
||||
"fill-range": "^7.0.1"
|
||||
}
|
||||
},
|
||||
"buffer": {
|
||||
"version": "5.6.0",
|
||||
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz",
|
||||
"integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==",
|
||||
"requires": {
|
||||
"base64-js": "^1.0.2",
|
||||
"ieee754": "^1.1.4"
|
||||
}
|
||||
},
|
||||
"buffer-crc32": {
|
||||
"version": "0.2.13",
|
||||
"resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
|
||||
@@ -276,6 +326,38 @@
|
||||
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
|
||||
"integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A=="
|
||||
},
|
||||
"busboy": {
|
||||
"version": "0.2.14",
|
||||
"resolved": "https://registry.npmjs.org/busboy/-/busboy-0.2.14.tgz",
|
||||
"integrity": "sha1-bCpiLvz0fFe7vh4qnDetNseSVFM=",
|
||||
"requires": {
|
||||
"dicer": "0.2.5",
|
||||
"readable-stream": "1.1.x"
|
||||
},
|
||||
"dependencies": {
|
||||
"isarray": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
|
||||
"integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8="
|
||||
},
|
||||
"readable-stream": {
|
||||
"version": "1.1.14",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
|
||||
"integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
|
||||
"requires": {
|
||||
"core-util-is": "~1.0.0",
|
||||
"inherits": "~2.0.1",
|
||||
"isarray": "0.0.1",
|
||||
"string_decoder": "~0.10.x"
|
||||
}
|
||||
},
|
||||
"string_decoder": {
|
||||
"version": "0.10.31",
|
||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
|
||||
"integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ="
|
||||
}
|
||||
}
|
||||
},
|
||||
"bytes": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
|
||||
@@ -400,6 +482,11 @@
|
||||
"readdirp": "~3.4.0"
|
||||
}
|
||||
},
|
||||
"chownr": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
|
||||
"integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg=="
|
||||
},
|
||||
"ci-info": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz",
|
||||
@@ -626,6 +713,38 @@
|
||||
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
|
||||
"integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
|
||||
},
|
||||
"dicer": {
|
||||
"version": "0.2.5",
|
||||
"resolved": "https://registry.npmjs.org/dicer/-/dicer-0.2.5.tgz",
|
||||
"integrity": "sha1-WZbAhrszIYyBLAkL3cCc0S+stw8=",
|
||||
"requires": {
|
||||
"readable-stream": "1.1.x",
|
||||
"streamsearch": "0.1.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"isarray": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
|
||||
"integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8="
|
||||
},
|
||||
"readable-stream": {
|
||||
"version": "1.1.14",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
|
||||
"integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
|
||||
"requires": {
|
||||
"core-util-is": "~1.0.0",
|
||||
"inherits": "~2.0.1",
|
||||
"isarray": "0.0.1",
|
||||
"string_decoder": "~0.10.x"
|
||||
}
|
||||
},
|
||||
"string_decoder": {
|
||||
"version": "0.10.31",
|
||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
|
||||
"integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ="
|
||||
}
|
||||
}
|
||||
},
|
||||
"dot-prop": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.2.0.tgz",
|
||||
@@ -705,7 +824,6 @@
|
||||
"version": "1.4.4",
|
||||
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
|
||||
"integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"once": "^1.4.0"
|
||||
}
|
||||
@@ -904,19 +1022,12 @@
|
||||
}
|
||||
},
|
||||
"express-validator": {
|
||||
"version": "6.4.1",
|
||||
"resolved": "https://registry.npmjs.org/express-validator/-/express-validator-6.4.1.tgz",
|
||||
"integrity": "sha512-9lVLCv9n735j6LjZwrINKhfv30ek1U4LVy/2jU1j4QotQ8A72Saw63wTu8/zXGZajP3scqf46PJxqquGF340Bg==",
|
||||
"version": "6.5.0",
|
||||
"resolved": "https://registry.npmjs.org/express-validator/-/express-validator-6.5.0.tgz",
|
||||
"integrity": "sha512-kXi99TuVeLWkxO0RtDOSj56T7YR0H5KZZyhtzoPSZ5TffBvrJpZPSp/frYcT/zVoLhH8NXDk+T0LCSeI6TbOGA==",
|
||||
"requires": {
|
||||
"lodash": "^4.17.15",
|
||||
"validator": "^12.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"validator": {
|
||||
"version": "12.2.0",
|
||||
"resolved": "https://registry.npmjs.org/validator/-/validator-12.2.0.tgz",
|
||||
"integrity": "sha512-jJfE/DW6tIK1Ek8nCfNFqt8Wb3nzMoAbocBF6/Icgg1ZFSBpObdnwVY2jQj6qUqzhx5jc71fpvBWyLGO7Xl+nQ=="
|
||||
}
|
||||
"validator": "^13.0.0"
|
||||
}
|
||||
},
|
||||
"ext": {
|
||||
@@ -935,23 +1046,36 @@
|
||||
}
|
||||
},
|
||||
"extract-zip": {
|
||||
"version": "1.7.0",
|
||||
"resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.7.0.tgz",
|
||||
"integrity": "sha512-xoh5G1W/PB0/27lXgMQyIhP5DSY/LhoCsOyZgb+6iMmRtCwVBo55uKaMoEYrDCKQhWvqEip5ZPKAc6eFNyf/MA==",
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.0.tgz",
|
||||
"integrity": "sha512-i42GQ498yibjdvIhivUsRslx608whtGoFIhF26Z7O4MYncBxp8CwalOs1lnHy21A9sIohWO2+uiE4SRtC9JXDg==",
|
||||
"requires": {
|
||||
"concat-stream": "^1.6.2",
|
||||
"debug": "^2.6.9",
|
||||
"mkdirp": "^0.5.4",
|
||||
"@types/yauzl": "^2.9.1",
|
||||
"debug": "^4.1.1",
|
||||
"get-stream": "^5.1.0",
|
||||
"yauzl": "^2.10.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"mkdirp": {
|
||||
"version": "0.5.5",
|
||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
|
||||
"integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
|
||||
"debug": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
|
||||
"integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
|
||||
"requires": {
|
||||
"minimist": "^1.2.5"
|
||||
"ms": "^2.1.1"
|
||||
}
|
||||
},
|
||||
"get-stream": {
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.1.0.tgz",
|
||||
"integrity": "sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw==",
|
||||
"requires": {
|
||||
"pump": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -1004,6 +1128,11 @@
|
||||
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
|
||||
"integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac="
|
||||
},
|
||||
"fs-constants": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
|
||||
"integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow=="
|
||||
},
|
||||
"fs-extra": {
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz",
|
||||
@@ -1178,6 +1307,11 @@
|
||||
"safer-buffer": ">= 2.1.2 < 3"
|
||||
}
|
||||
},
|
||||
"ieee754": {
|
||||
"version": "1.1.13",
|
||||
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz",
|
||||
"integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg=="
|
||||
},
|
||||
"ignore-by-default": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz",
|
||||
@@ -1514,6 +1648,14 @@
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"semver": "^6.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"semver": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
|
||||
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"media-typer": {
|
||||
@@ -1588,15 +1730,20 @@
|
||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
|
||||
"integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw=="
|
||||
},
|
||||
"mkdirp-classic": {
|
||||
"version": "0.5.3",
|
||||
"resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz",
|
||||
"integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A=="
|
||||
},
|
||||
"moment": {
|
||||
"version": "2.25.3",
|
||||
"resolved": "https://registry.npmjs.org/moment/-/moment-2.25.3.tgz",
|
||||
"integrity": "sha512-PuYv0PHxZvzc15Sp8ybUCoQ+xpyPWvjOuK72a5ovzp2LI32rJXOiIfyoFoYvG3s6EwwrdkMyWuRiEHSZRLJNdg=="
|
||||
"version": "2.26.0",
|
||||
"resolved": "https://registry.npmjs.org/moment/-/moment-2.26.0.tgz",
|
||||
"integrity": "sha512-oIixUO+OamkUkwjhAVE18rAMfRJNsNe/Stid/gwHSOfHrOtw9EhAY2AHvdKZ/k/MggcYELFCJz/Sn2pL8b8JMw=="
|
||||
},
|
||||
"moment-timezone": {
|
||||
"version": "0.5.28",
|
||||
"resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.28.tgz",
|
||||
"integrity": "sha512-TDJkZvAyKIVWg5EtVqRzU97w0Rb0YVbfpqyjgu6GwXCAohVRqwZjf4fOzDE6p1Ch98Sro/8hQQi65WDXW5STPw==",
|
||||
"version": "0.5.31",
|
||||
"resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.31.tgz",
|
||||
"integrity": "sha512-+GgHNg8xRhMXfEbv81iDtrVeTcWt0kWmTEY1XQK14dICTXnWJnT0dxdlPspwqF3keKMVPXwayEsk1DI0AA/jdA==",
|
||||
"requires": {
|
||||
"moment": ">= 2.9.0"
|
||||
}
|
||||
@@ -1606,6 +1753,31 @@
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
|
||||
},
|
||||
"multer": {
|
||||
"version": "1.4.2",
|
||||
"resolved": "https://registry.npmjs.org/multer/-/multer-1.4.2.tgz",
|
||||
"integrity": "sha512-xY8pX7V+ybyUpbYMxtjM9KAiD9ixtg5/JkeKUTD6xilfDv0vzzOFcCp4Ljb1UU3tSOM3VTZtKo63OmzOrGi3Cg==",
|
||||
"requires": {
|
||||
"append-field": "^1.0.0",
|
||||
"busboy": "^0.2.11",
|
||||
"concat-stream": "^1.5.2",
|
||||
"mkdirp": "^0.5.1",
|
||||
"object-assign": "^4.1.1",
|
||||
"on-finished": "^2.3.0",
|
||||
"type-is": "^1.6.4",
|
||||
"xtend": "^4.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"mkdirp": {
|
||||
"version": "0.5.5",
|
||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
|
||||
"integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
|
||||
"requires": {
|
||||
"minimist": "^1.2.5"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"mysql2": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/mysql2/-/mysql2-2.1.0.tgz",
|
||||
@@ -1667,9 +1839,9 @@
|
||||
"integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw="
|
||||
},
|
||||
"nodemon": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.3.tgz",
|
||||
"integrity": "sha512-lLQLPS90Lqwc99IHe0U94rDgvjo+G9I4uEIxRG3evSLROcqQ9hwc0AxlSHKS4T1JW/IMj/7N5mthiN58NL/5kw==",
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.4.tgz",
|
||||
"integrity": "sha512-Ltced+hIfTmaS28Zjv1BM552oQ3dbwPqI4+zI0SLgq+wpJhSyqgYude/aZa/3i31VCQWMfXJVxvu86abcam3uQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"chokidar": "^3.2.2",
|
||||
@@ -1698,12 +1870,6 @@
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
|
||||
"dev": true
|
||||
},
|
||||
"semver": {
|
||||
"version": "5.7.1",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
|
||||
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -1810,6 +1976,14 @@
|
||||
"registry-auth-token": "^4.0.0",
|
||||
"registry-url": "^5.0.0",
|
||||
"semver": "^6.2.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"semver": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
|
||||
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"parseqs": {
|
||||
@@ -1905,16 +2079,15 @@
|
||||
"integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM="
|
||||
},
|
||||
"pstree.remy": {
|
||||
"version": "1.1.7",
|
||||
"resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.7.tgz",
|
||||
"integrity": "sha512-xsMgrUwRpuGskEzBFkH8NmTimbZ5PcPup0LA8JJkHIm2IMUbQcpo3yeLNWVrufEYjh8YwtSVh0xz6UeWc5Oh5A==",
|
||||
"version": "1.1.8",
|
||||
"resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz",
|
||||
"integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==",
|
||||
"dev": true
|
||||
},
|
||||
"pump": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
|
||||
"integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"end-of-stream": "^1.1.0",
|
||||
"once": "^1.3.1"
|
||||
@@ -1930,20 +2103,20 @@
|
||||
}
|
||||
},
|
||||
"puppeteer": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-2.1.1.tgz",
|
||||
"integrity": "sha512-LWzaDVQkk1EPiuYeTOj+CZRIjda4k2s5w4MK4xoH2+kgWV/SDlkYHmxatDdtYrciHUKSXTsGgPgPP8ILVdBsxg==",
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-3.1.0.tgz",
|
||||
"integrity": "sha512-jLa9sqdVx0tPnr2FcwAq+8DSjGhSM4YpkwOf3JE22Ycyqm71SW7B5uGfTyMGFoLCmbCozbLZclCjasPb0flTRw==",
|
||||
"requires": {
|
||||
"@types/mime-types": "^2.1.0",
|
||||
"debug": "^4.1.0",
|
||||
"extract-zip": "^1.6.6",
|
||||
"extract-zip": "^2.0.0",
|
||||
"https-proxy-agent": "^4.0.0",
|
||||
"mime": "^2.0.3",
|
||||
"mime-types": "^2.1.25",
|
||||
"progress": "^2.0.1",
|
||||
"proxy-from-env": "^1.0.0",
|
||||
"rimraf": "^2.6.1",
|
||||
"ws": "^6.1.0"
|
||||
"rimraf": "^3.0.2",
|
||||
"tar-fs": "^2.0.0",
|
||||
"unbzip2-stream": "^1.3.3",
|
||||
"ws": "^7.2.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"debug": {
|
||||
@@ -1955,22 +2128,14 @@
|
||||
}
|
||||
},
|
||||
"mime": {
|
||||
"version": "2.4.5",
|
||||
"resolved": "https://registry.npmjs.org/mime/-/mime-2.4.5.tgz",
|
||||
"integrity": "sha512-3hQhEUF027BuxZjQA3s7rIv/7VCQPa27hN9u9g87sEkWaKwQPuXOkVKtOeiyUrnWqTDiOs8Ed2rwg733mB0R5w=="
|
||||
"version": "2.4.6",
|
||||
"resolved": "https://registry.npmjs.org/mime/-/mime-2.4.6.tgz",
|
||||
"integrity": "sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA=="
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||
},
|
||||
"ws": {
|
||||
"version": "6.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz",
|
||||
"integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==",
|
||||
"requires": {
|
||||
"async-limiter": "~1.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -2104,9 +2269,9 @@
|
||||
}
|
||||
},
|
||||
"rimraf": {
|
||||
"version": "2.7.1",
|
||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
|
||||
"integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
|
||||
"integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
|
||||
"requires": {
|
||||
"glob": "^7.1.3"
|
||||
}
|
||||
@@ -2122,9 +2287,10 @@
|
||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
|
||||
},
|
||||
"semver": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
|
||||
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
|
||||
"version": "5.7.1",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
|
||||
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
|
||||
"dev": true
|
||||
},
|
||||
"semver-diff": {
|
||||
"version": "3.1.1",
|
||||
@@ -2133,6 +2299,14 @@
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"semver": "^6.3.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"semver": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
|
||||
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"send": {
|
||||
@@ -2168,9 +2342,9 @@
|
||||
"integrity": "sha1-1WgS4cAXpuTnw+Ojeh2m143TyT4="
|
||||
},
|
||||
"sequelize": {
|
||||
"version": "5.21.8",
|
||||
"resolved": "https://registry.npmjs.org/sequelize/-/sequelize-5.21.8.tgz",
|
||||
"integrity": "sha512-UOxGMJ7eSnProTMWX9wRr0T9TcuW0YedFmU7s+YBZT9/RmfJeANYPdJXjXg4E+Yg+dJl4WWvBEu9r2oe+d/1/Q==",
|
||||
"version": "5.21.11",
|
||||
"resolved": "https://registry.npmjs.org/sequelize/-/sequelize-5.21.11.tgz",
|
||||
"integrity": "sha512-ZJw3Hp+NS7iHcTz4fHlKvIBm4I7xYibYRCP4HhSyMB26xgqFYFOXTaeWbHD2UUwAFaksTLw5ntzfpA9kE33SVA==",
|
||||
"requires": {
|
||||
"bluebird": "^3.5.0",
|
||||
"cls-bluebird": "^2.1.0",
|
||||
@@ -2201,6 +2375,16 @@
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||
},
|
||||
"semver": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
|
||||
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
|
||||
},
|
||||
"validator": {
|
||||
"version": "10.11.0",
|
||||
"resolved": "https://registry.npmjs.org/validator/-/validator-10.11.0.tgz",
|
||||
"integrity": "sha512-X/p3UZerAIsbBfN/IwahhYaBbY68EN/UQBWHtsbXGT5bfrH/p4NQzUCG1kF/rtKaNpnJ7jAu6NGTdSNtyNIXMw=="
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -2390,6 +2574,11 @@
|
||||
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
|
||||
"integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow="
|
||||
},
|
||||
"streamsearch": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz",
|
||||
"integrity": "sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo="
|
||||
},
|
||||
"string-width": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
|
||||
@@ -2438,12 +2627,52 @@
|
||||
"has-flag": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"tar-fs": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.0.tgz",
|
||||
"integrity": "sha512-9uW5iDvrIMCVpvasdFHW0wJPez0K4JnMZtsuIeDI7HyMGJNxmDZDOCQROr7lXyS+iL/QMpj07qcjGYTSdRFXUg==",
|
||||
"requires": {
|
||||
"chownr": "^1.1.1",
|
||||
"mkdirp-classic": "^0.5.2",
|
||||
"pump": "^3.0.0",
|
||||
"tar-stream": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"tar-stream": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.1.2.tgz",
|
||||
"integrity": "sha512-UaF6FoJ32WqALZGOIAApXx+OdxhekNMChu6axLJR85zMMjXKWFGjbIRe+J6P4UnRGg9rAwWvbTT0oI7hD/Un7Q==",
|
||||
"requires": {
|
||||
"bl": "^4.0.1",
|
||||
"end-of-stream": "^1.4.1",
|
||||
"fs-constants": "^1.0.0",
|
||||
"inherits": "^2.0.3",
|
||||
"readable-stream": "^3.1.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"readable-stream": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
|
||||
"integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
|
||||
"requires": {
|
||||
"inherits": "^2.0.3",
|
||||
"string_decoder": "^1.1.1",
|
||||
"util-deprecate": "^1.0.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"term-size": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/term-size/-/term-size-2.2.0.tgz",
|
||||
"integrity": "sha512-a6sumDlzyHVJWb8+YofY4TW112G6p2FCPEAFk+59gIYHv3XHRhm9ltVQ9kli4hNWeQBwSpe8cRN25x0ROunMOw==",
|
||||
"dev": true
|
||||
},
|
||||
"through": {
|
||||
"version": "2.3.8",
|
||||
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
|
||||
"integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU="
|
||||
},
|
||||
"timers-ext": {
|
||||
"version": "0.1.7",
|
||||
"resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.7.tgz",
|
||||
@@ -2545,6 +2774,15 @@
|
||||
"bluebird": "^3.7.2"
|
||||
}
|
||||
},
|
||||
"unbzip2-stream": {
|
||||
"version": "1.4.3",
|
||||
"resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz",
|
||||
"integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==",
|
||||
"requires": {
|
||||
"buffer": "^5.2.1",
|
||||
"through": "^2.3.8"
|
||||
}
|
||||
},
|
||||
"undefsafe": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.3.tgz",
|
||||
@@ -2619,9 +2857,9 @@
|
||||
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A=="
|
||||
},
|
||||
"validator": {
|
||||
"version": "10.11.0",
|
||||
"resolved": "https://registry.npmjs.org/validator/-/validator-10.11.0.tgz",
|
||||
"integrity": "sha512-X/p3UZerAIsbBfN/IwahhYaBbY68EN/UQBWHtsbXGT5bfrH/p4NQzUCG1kF/rtKaNpnJ7jAu6NGTdSNtyNIXMw=="
|
||||
"version": "13.0.0",
|
||||
"resolved": "https://registry.npmjs.org/validator/-/validator-13.0.0.tgz",
|
||||
"integrity": "sha512-anYx5fURbgF04lQV18nEQWZ/3wHGnxiKdG4aL8J+jEDsm98n/sU/bey+tYk6tnGJzm7ioh5FoqrAiQ6m03IgaA=="
|
||||
},
|
||||
"vary": {
|
||||
"version": "1.1.2",
|
||||
@@ -2629,13 +2867,21 @@
|
||||
"integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw="
|
||||
},
|
||||
"whatsapp-web.js": {
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmjs.org/whatsapp-web.js/-/whatsapp-web.js-1.5.1.tgz",
|
||||
"integrity": "sha512-l9/LZ1o6tuXGgeTJIYc9ZVrT3Sa/uHYBUXzgWJf4hBNOzGvFOLLoidEOgWCZXhxHHM6SnCK54QvDDpIeMTv+Lg==",
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/whatsapp-web.js/-/whatsapp-web.js-1.6.0.tgz",
|
||||
"integrity": "sha512-Lr4KG5nA9u18IBGCSVLxwBT1qlJXtLSA83/0efXobQ5j76fVw2I0sIe8KCcMcFnrTr0IIAnnxEqmXcEKnSiaqg==",
|
||||
"requires": {
|
||||
"@pedroslopez/moduleraid": "^4.1.0",
|
||||
"jsqr": "^1.2.0",
|
||||
"puppeteer": "^2.1.1"
|
||||
"jsqr": "^1.3.1",
|
||||
"mime": "^2.4.5",
|
||||
"puppeteer": "^3.0.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"mime": {
|
||||
"version": "2.4.6",
|
||||
"resolved": "https://registry.npmjs.org/mime/-/mime-2.4.6.tgz",
|
||||
"integrity": "sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"which-module": {
|
||||
@@ -2743,6 +2989,11 @@
|
||||
"resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz",
|
||||
"integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4="
|
||||
},
|
||||
"xtend": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
|
||||
"integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ=="
|
||||
},
|
||||
"y18n": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz",
|
||||
|
||||
@@ -18,16 +18,17 @@
|
||||
"bcryptjs": "^2.4.3",
|
||||
"cors": "^2.8.5",
|
||||
"express": "^4.17.1",
|
||||
"express-validator": "^6.4.1",
|
||||
"express-validator": "^6.5.0",
|
||||
"jsonwebtoken": "^8.5.1",
|
||||
"multer": "^1.4.2",
|
||||
"mysql2": "^2.1.0",
|
||||
"qrcode-terminal": "^0.12.0",
|
||||
"sequelize": "^5.21.8",
|
||||
"sequelize": "^5.21.11",
|
||||
"sequelize-cli": "^5.5.1",
|
||||
"socket.io": "^2.3.0",
|
||||
"whatsapp-web.js": "^1.5.1"
|
||||
"whatsapp-web.js": "^1.6.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"nodemon": "^2.0.3"
|
||||
"nodemon": "^2.0.4"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,11 +5,6 @@ const MessangeController = require("../controllers/message");
|
||||
|
||||
const routes = express.Router();
|
||||
|
||||
routes.post(
|
||||
"/messages/setread",
|
||||
isAuth,
|
||||
MessangeController.postUpdateMessageStatus
|
||||
);
|
||||
routes.get(
|
||||
"/messages/:contactId",
|
||||
isAuth,
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
const Sequelize = require("sequelize");
|
||||
|
||||
const sequelize = new Sequelize("econo_whatsbot", "root", "nodecomplete", {
|
||||
define: {
|
||||
charset: "utf8mb4",
|
||||
collate: "utf8mb4_bin",
|
||||
},
|
||||
dialect: "mysql",
|
||||
host: "localhost",
|
||||
logging: false,
|
||||
|
||||
22
frontend/package-lock.json
generated
22
frontend/package-lock.json
generated
@@ -4830,6 +4830,15 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"emoji-mart": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/emoji-mart/-/emoji-mart-3.0.0.tgz",
|
||||
"integrity": "sha512-r5DXyzOLJttdwRYfJmPq/XL3W5tiAE/VsRnS0Hqyn27SqPA/GOYwVUSx50px/dXdJyDSnvmoPbuJ/zzhwSaU4A==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.0.0",
|
||||
"prop-types": "^15.6.0"
|
||||
}
|
||||
},
|
||||
"emoji-regex": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
|
||||
@@ -10811,6 +10820,14 @@
|
||||
"whatwg-fetch": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"react-audio-player": {
|
||||
"version": "0.13.0",
|
||||
"resolved": "https://registry.npmjs.org/react-audio-player/-/react-audio-player-0.13.0.tgz",
|
||||
"integrity": "sha512-ivXIjQMM59Kp6Bat62VkqI5ymhgUOO8XdCsfyqeLJ5E3Hgx+Cqj1zq+x1ltU+xhSp+zW2xEEnyWHOQGdJibNfA==",
|
||||
"requires": {
|
||||
"prop-types": "^15.7.2"
|
||||
}
|
||||
},
|
||||
"react-bootstrap": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/react-bootstrap/-/react-bootstrap-1.0.1.tgz",
|
||||
@@ -11108,6 +11125,11 @@
|
||||
"resolved": "https://registry.npmjs.org/react-loading/-/react-loading-2.0.3.tgz",
|
||||
"integrity": "sha512-Vdqy79zq+bpeWJqC+xjltUjuGApyoItPgL0vgVfcJHhqwU7bAMKzysfGW/ADu6i0z0JiOCRJjo+IkFNkRNbA3A=="
|
||||
},
|
||||
"react-modal-image": {
|
||||
"version": "2.5.0",
|
||||
"resolved": "https://registry.npmjs.org/react-modal-image/-/react-modal-image-2.5.0.tgz",
|
||||
"integrity": "sha512-QucQrgOLmF44CD4EFDLZ9ICrbHEZwztjALgx1GsNmMWZrAtmzDLarG+T1TK2OSE4w1eHfkXtmEhQibjbt0mT2g=="
|
||||
},
|
||||
"react-moment": {
|
||||
"version": "0.9.7",
|
||||
"resolved": "https://registry.npmjs.org/react-moment/-/react-moment-0.9.7.tgz",
|
||||
|
||||
@@ -9,12 +9,15 @@
|
||||
"@testing-library/user-event": "^7.2.1",
|
||||
"axios": "^0.19.2",
|
||||
"bootstrap": "^4.5.0",
|
||||
"emoji-mart": "^3.0.0",
|
||||
"moment": "^2.26.0",
|
||||
"react": "^16.13.1",
|
||||
"react-audio-player": "^0.13.0",
|
||||
"react-bootstrap": "^1.0.1",
|
||||
"react-dom": "^16.13.1",
|
||||
"react-icons": "^3.10.0",
|
||||
"react-loading": "^2.0.3",
|
||||
"react-modal-image": "^2.5.0",
|
||||
"react-moment": "^0.9.7",
|
||||
"react-router-bootstrap": "^0.25.0",
|
||||
"react-router-dom": "^5.2.0",
|
||||
|
||||
@@ -10,6 +10,7 @@ import LogedinNavbar from "../../components/Navbar/LogedinNavbar";
|
||||
import DefaultNavbar from "../../components/Navbar/DefaultNavbar";
|
||||
|
||||
import ChatBox from "../ChatBox/ChatBox";
|
||||
// let socket;
|
||||
|
||||
const Chat = ({ showToast }) => {
|
||||
const token = localStorage.getItem("token");
|
||||
@@ -18,18 +19,28 @@ const Chat = ({ showToast }) => {
|
||||
const [currentPeerContact, setCurrentPeerContact] = useState(null);
|
||||
const [contacts, setContacts] = useState([]);
|
||||
const [displayedContacts, setDisplayedContacts] = useState([]);
|
||||
const [notification, setNotification] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchContacts = async () => {
|
||||
const res = await api.get("/contacts", {
|
||||
headers: { Authorization: "Bearer " + token },
|
||||
});
|
||||
setContacts(res.data);
|
||||
setDisplayedContacts(res.data);
|
||||
try {
|
||||
const res = await api.get("/contacts", {
|
||||
headers: { Authorization: "Bearer " + token },
|
||||
});
|
||||
setContacts(res.data);
|
||||
setDisplayedContacts(res.data);
|
||||
} catch (err) {
|
||||
alert(err.response.data.message);
|
||||
}
|
||||
};
|
||||
fetchContacts();
|
||||
}, [currentPeerContact, token, notification]);
|
||||
|
||||
useEffect(() => {
|
||||
const socket = openSocket("http://localhost:8080");
|
||||
|
||||
socket.emit("joinNotification");
|
||||
|
||||
socket.on("contact", data => {
|
||||
console.log(data);
|
||||
if (data.action === "create") {
|
||||
@@ -37,14 +48,31 @@ const Chat = ({ showToast }) => {
|
||||
}
|
||||
});
|
||||
|
||||
socket.on("appMessage", data => {
|
||||
console.log("recebendo msg");
|
||||
setNotification(prevState => !prevState);
|
||||
// handleUnreadMessages(data.message.contactId);
|
||||
});
|
||||
|
||||
return () => {
|
||||
socket.disconnect();
|
||||
};
|
||||
}, [currentPeerContact, token]);
|
||||
}, [contacts]);
|
||||
|
||||
// const handleUnreadMessages = contactId => {
|
||||
// console.log("Atualizando mensagens n lidas");
|
||||
// console.log(contacts);
|
||||
// let aux = [...contacts];
|
||||
// let contactIndex = aux.findIndex(contact => contact.id === contactId);
|
||||
// aux[contactIndex].unreadMessages++;
|
||||
|
||||
// aux.unshift(aux.splice(contactIndex, 1)[0]);
|
||||
|
||||
// setDisplayedContacts(aux);
|
||||
// };
|
||||
|
||||
const addContact = contact => {
|
||||
setContacts(prevState => [...prevState, contact]);
|
||||
console.log("adicionando contato", contact);
|
||||
setDisplayedContacts(prevState => [...prevState, contact]);
|
||||
};
|
||||
|
||||
@@ -109,16 +137,20 @@ const Chat = ({ showToast }) => {
|
||||
<img
|
||||
className="viewAvatarItem"
|
||||
alt=""
|
||||
src={profileDefaultPic}
|
||||
src={
|
||||
contact.imageURL
|
||||
? contact.imageURL
|
||||
: profileDefaultPic
|
||||
}
|
||||
/>
|
||||
<div className="viewWrapContentItem">
|
||||
<span className="textItem">{contact.name}</span>
|
||||
</div>
|
||||
|
||||
{contact.messages && contact.messages.length > 0 && (
|
||||
{contact.unreadMessages > 0 && (
|
||||
<div className="notificationpragraph">
|
||||
<p className="newmessages">
|
||||
{contact.messages.length}
|
||||
{contact.unreadMessages}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -12,8 +12,8 @@
|
||||
backface-visibility: hidden;
|
||||
border-left: 1px solid #ededed;
|
||||
/* border-right: 5px solid #DFA375; */
|
||||
max-height: 104%;
|
||||
min-height: 104%;
|
||||
max-height: 104.3%;
|
||||
min-height: 104.3%;
|
||||
/* margin-right: 20px; */
|
||||
border-radius: 10px;
|
||||
/* box-shadow: 0 5px 5px #808888; */
|
||||
@@ -67,12 +67,6 @@
|
||||
background-color: #e8e8e8;
|
||||
}
|
||||
|
||||
.teste {
|
||||
border-radius: 10px;
|
||||
box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3);
|
||||
background-color: #e8e8e8;
|
||||
}
|
||||
|
||||
.viewBottom {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
@@ -83,10 +77,14 @@
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
.icOpenGallery {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
margin-left: 10px;
|
||||
.viewMediaBottom {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100px;
|
||||
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
.viewInputGallery {
|
||||
@@ -97,18 +95,59 @@
|
||||
width: 30px;
|
||||
}
|
||||
|
||||
.icOpenSticker {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
margin-left: 5px;
|
||||
margin-right: 5px;
|
||||
.icOpenGallery {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
margin-left: 10px;
|
||||
margin-right: 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.icOpenGallery:hover {
|
||||
opacity: 70%;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
margin-left: 10px;
|
||||
margin-right: 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.icOpenEmojis {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
margin-left: 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.icOpenEmojis:hover {
|
||||
opacity: 70%;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
margin-left: 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.icSend {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
margin-left: 5px;
|
||||
margin-right: 30px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.icSend:hover {
|
||||
opacity: 70%;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
margin-left: 5px;
|
||||
margin-right: 30px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.viewMediaInput {
|
||||
flex: 1;
|
||||
width: 100%;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.viewInput {
|
||||
@@ -132,9 +171,30 @@ input::placeholder {
|
||||
/* View item message */
|
||||
|
||||
.viewItemRight {
|
||||
width: 300px;
|
||||
min-width: 100px;
|
||||
max-width: 600px;
|
||||
height: auto;
|
||||
|
||||
margin-right: 20px;
|
||||
margin-top: 5px;
|
||||
background-color: #dcf8c6;
|
||||
align-self: flex-end;
|
||||
border-top-left-radius: 8px;
|
||||
border-top-right-radius: 8px;
|
||||
border-bottom-left-radius: 8px;
|
||||
border-bottom-right-radius: 0px;
|
||||
padding-left: 20px;
|
||||
padding-right: 20px;
|
||||
padding-top: 10px;
|
||||
padding-bottom: 10px;
|
||||
color: #203152;
|
||||
box-shadow: 0 5px 5px #808888;
|
||||
}
|
||||
|
||||
.viewItemRight2 {
|
||||
width: 300px;
|
||||
padding: 4px;
|
||||
height: auto;
|
||||
background-color: #dcf8c6;
|
||||
align-self: flex-end;
|
||||
margin-right: 20px;
|
||||
@@ -144,27 +204,7 @@ input::placeholder {
|
||||
border-bottom-left-radius: 8px;
|
||||
border-bottom-right-radius: 0px;
|
||||
color: #203152;
|
||||
text-align: left;
|
||||
padding-left: 20px;
|
||||
padding-right: 20px;
|
||||
padding-top: 10px;
|
||||
padding-bottom: 10px;
|
||||
box-shadow: 0 5px 5px #808888;
|
||||
}
|
||||
|
||||
.viewItemRight2 {
|
||||
width: 300px;
|
||||
height: auto;
|
||||
background-color: #e1f3fb;
|
||||
align-self: flex-end;
|
||||
margin-right: 20px;
|
||||
margin-top: 10px;
|
||||
border-top-left-radius: 8px;
|
||||
border-top-right-radius: 8px;
|
||||
border-bottom-left-radius: 8px;
|
||||
border-bottom-right-radius: 0px;
|
||||
color: #203152;
|
||||
text-align: left;
|
||||
/* text-align: left; */
|
||||
box-shadow: 0 5px 5px #808888;
|
||||
}
|
||||
|
||||
@@ -207,10 +247,14 @@ input::placeholder {
|
||||
}
|
||||
|
||||
.viewItemLeft {
|
||||
width: 300px;
|
||||
min-width: 100px;
|
||||
max-width: 600px;
|
||||
height: auto;
|
||||
margin-top: 10px;
|
||||
|
||||
margin-left: 20px;
|
||||
margin-top: 5px;
|
||||
background-color: #ffffff;
|
||||
align-self: flex-start;
|
||||
border-top-left-radius: 8px;
|
||||
border-top-right-radius: 8px;
|
||||
border-bottom-left-radius: 0px;
|
||||
@@ -225,17 +269,22 @@ input::placeholder {
|
||||
|
||||
.viewItemLeft2 {
|
||||
width: 300px;
|
||||
padding: 4px;
|
||||
height: auto;
|
||||
background-color: #203152;
|
||||
margin-left: 10px;
|
||||
margin-top: 10px;
|
||||
background-color: #ffffff;
|
||||
border-top-left-radius: 8px;
|
||||
border-top-right-radius: 8px;
|
||||
border-bottom-left-radius: 0px;
|
||||
border-bottom-right-radius: 8px;
|
||||
color: white;
|
||||
color: #203152;
|
||||
box-shadow: 0 5px 5px #808888;
|
||||
}
|
||||
|
||||
.viewItemLeft3 {
|
||||
margin-left: 10px;
|
||||
margin-top: 10px;
|
||||
width: 300px;
|
||||
height: auto;
|
||||
border-top-left-radius: 8px;
|
||||
@@ -280,7 +329,7 @@ input::placeholder {
|
||||
|
||||
.textContentItem {
|
||||
font-size: 16px;
|
||||
word-break: break-all;
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
|
||||
.viewListContentChat div:last-child {
|
||||
@@ -319,11 +368,9 @@ input::placeholder {
|
||||
/* Stickers */
|
||||
|
||||
.viewStickers {
|
||||
display: block;
|
||||
position: absolute;
|
||||
bottom: 90px;
|
||||
border-top: 1px solid #e8e8e8;
|
||||
height: 100px;
|
||||
align-items: center;
|
||||
justify-content: space-around;
|
||||
overflow-x: scroll;
|
||||
}
|
||||
.viewStickers::-webkit-scrollbar-track {
|
||||
@@ -360,9 +407,3 @@ input::placeholder {
|
||||
color: #808888;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.imgWaveHand {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
@@ -1,25 +1,35 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { Card } from "react-bootstrap";
|
||||
import profileDefaultPic from "../../Images/profile_default.png";
|
||||
import uploadPic from "../../Images/upload.png";
|
||||
import sendPic from "../../Images/send.png";
|
||||
import { FiPaperclip, FiSend, FiX, FiSmile, FiDownload } from "react-icons/fi";
|
||||
import { RiSendPlane2Line } from "react-icons/ri";
|
||||
import "emoji-mart/css/emoji-mart.css";
|
||||
import { Picker } from "emoji-mart";
|
||||
import ModalImage from "react-modal-image";
|
||||
|
||||
import api from "../../util/api";
|
||||
import openSocket from "socket.io-client";
|
||||
import profileDefaultPic from "../../Images/profile_default.png";
|
||||
import ReactAudioPlayer from "react-audio-player";
|
||||
|
||||
import ScrollToBottom from "react-scroll-to-bottom";
|
||||
|
||||
import "react-toastify/dist/ReactToastify.css";
|
||||
import "./ChatBox.css";
|
||||
// let socket;
|
||||
|
||||
const ChatBox = ({ currentPeerContact }) => {
|
||||
const SERVER_URL = "http://localhost:8080/";
|
||||
const contactId = currentPeerContact.id;
|
||||
const unreadMessages = currentPeerContact.messages;
|
||||
const userId = localStorage.getItem("userId");
|
||||
const username = localStorage.getItem("username");
|
||||
const token = localStorage.getItem("token");
|
||||
const mediaInitialState = { preview: "", raw: "", name: "" };
|
||||
|
||||
const [listMessages, setListMessages] = useState([]);
|
||||
const [inputMessage, setInputMessage] = useState("");
|
||||
const [media, setMedia] = useState(mediaInitialState);
|
||||
const [showEmoji, setShowEmoji] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchMessages = async () => {
|
||||
@@ -33,44 +43,88 @@ const ChatBox = ({ currentPeerContact }) => {
|
||||
}
|
||||
};
|
||||
|
||||
const readMesages = async () => {
|
||||
try {
|
||||
await api.post(
|
||||
"/messages/setread",
|
||||
{ messagesToSetRead: unreadMessages },
|
||||
{ headers: { Authorization: "Bearer " + token } }
|
||||
);
|
||||
} catch (err) {
|
||||
alert(err);
|
||||
}
|
||||
};
|
||||
fetchMessages();
|
||||
|
||||
return () => {
|
||||
setInputMessage("");
|
||||
setShowEmoji(false);
|
||||
setMedia({});
|
||||
};
|
||||
}, [contactId, unreadMessages, token]);
|
||||
|
||||
useEffect(() => {
|
||||
const socket = openSocket(SERVER_URL);
|
||||
|
||||
socket.emit("joinChatBox", contactId, () => {});
|
||||
|
||||
const socket = openSocket("http://localhost:8080");
|
||||
socket.on("appMessage", data => {
|
||||
if (data.action === "create") {
|
||||
if (contactId === data.message.contactId) {
|
||||
addMessage(data.message);
|
||||
}
|
||||
addMessage(data.message);
|
||||
}
|
||||
});
|
||||
|
||||
fetchMessages();
|
||||
readMesages();
|
||||
|
||||
return () => {
|
||||
socket.disconnect();
|
||||
};
|
||||
}, [contactId, unreadMessages, token]);
|
||||
}, [contactId]);
|
||||
|
||||
const addMessage = message => {
|
||||
setListMessages(prevState => [...prevState, message]);
|
||||
};
|
||||
|
||||
const handleChangeInput = e => {
|
||||
setInputMessage(e.target.value);
|
||||
};
|
||||
|
||||
const handleAddEmoji = e => {
|
||||
let emoji = e.native;
|
||||
setInputMessage(prevState => prevState + emoji);
|
||||
};
|
||||
|
||||
const handleChangeMedia = e => {
|
||||
if (e.target.files.length) {
|
||||
setMedia({
|
||||
preview: URL.createObjectURL(e.target.files[0]),
|
||||
raw: e.target.files[0],
|
||||
name: e.target.files[0].name,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const handleInputPaste = e => {
|
||||
if (e.clipboardData.files[0]) {
|
||||
setMedia({
|
||||
preview: URL.createObjectURL(e.clipboardData.files[0]),
|
||||
raw: e.clipboardData.files[0],
|
||||
name: e.clipboardData.files[0].name,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const handleUploadMedia = async e => {
|
||||
e.preventDefault();
|
||||
const formData = new FormData();
|
||||
formData.append("media", media.raw);
|
||||
formData.append("userId", userId);
|
||||
formData.append("messageBody", media.name);
|
||||
|
||||
try {
|
||||
await api.post(`/messages/${contactId}`, formData, {
|
||||
headers: { Authorization: "Bearer " + token },
|
||||
});
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
alert(err);
|
||||
}
|
||||
setMedia(mediaInitialState);
|
||||
};
|
||||
|
||||
const handleSendMessage = async () => {
|
||||
if (inputMessage.trim() === "") return;
|
||||
const message = {
|
||||
read: 1,
|
||||
userId: userId,
|
||||
mediaUrl: "",
|
||||
messageBody: `${username}: ${inputMessage.trim()}`,
|
||||
};
|
||||
try {
|
||||
@@ -81,57 +135,194 @@ const ChatBox = ({ currentPeerContact }) => {
|
||||
alert(err);
|
||||
}
|
||||
setInputMessage("");
|
||||
setShowEmoji(false);
|
||||
};
|
||||
|
||||
const addMessage = message => {
|
||||
setListMessages(prevState => [...prevState, message]);
|
||||
const renderMessages = () => {
|
||||
if (listMessages.length > 0) {
|
||||
let viewListMessages = [];
|
||||
listMessages.forEach((message, index) => {
|
||||
if (message.userId === 0) {
|
||||
if (message.mediaUrl && message.mediaType === "image") {
|
||||
viewListMessages.push(
|
||||
<div className="viewItemLeft2" key={message.id}>
|
||||
<ModalImage
|
||||
className="imgItemLeft"
|
||||
smallSrcSet={`${SERVER_URL}${message.mediaUrl}`}
|
||||
medium={`${SERVER_URL}${message.mediaUrl}`}
|
||||
large={`${SERVER_URL}${message.mediaUrl}`}
|
||||
alt=""
|
||||
/>
|
||||
<span className="textContentItem">{message.messageBody}</span>
|
||||
</div>
|
||||
);
|
||||
} else if (message.mediaUrl && message.mediaType === "audio") {
|
||||
viewListMessages.push(
|
||||
<div className="viewItemLeft3" key={message.id}>
|
||||
{message.messageBody}
|
||||
<ReactAudioPlayer
|
||||
src={`${SERVER_URL}${message.mediaUrl}`}
|
||||
controls
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
} else if (message.mediaUrl) {
|
||||
viewListMessages.push(
|
||||
<div className="viewItemLeft" key={message.id}>
|
||||
<a
|
||||
href={`${SERVER_URL}${message.mediaUrl}`}
|
||||
className="textContentItem"
|
||||
>
|
||||
{message.messageBody}
|
||||
<hr></hr>
|
||||
Download <FiDownload size="20" />
|
||||
</a>
|
||||
</div>
|
||||
);
|
||||
} else {
|
||||
viewListMessages.push(
|
||||
<div className="viewItemLeft" key={message.id}>
|
||||
<span className="textContentItem">{message.messageBody}</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
} else {
|
||||
if (message.mediaUrl && message.mediaType === "image") {
|
||||
viewListMessages.push(
|
||||
<div className="viewItemRight2" key={message.id}>
|
||||
<ModalImage
|
||||
className="imgItemLeft"
|
||||
smallSrcSet={`${SERVER_URL}${message.mediaUrl}`}
|
||||
medium={`${SERVER_URL}${message.mediaUrl}`}
|
||||
large={`${SERVER_URL}${message.mediaUrl}`}
|
||||
alt=""
|
||||
/>
|
||||
<span className="textContentItem">{message.messageBody}</span>
|
||||
</div>
|
||||
);
|
||||
} else if (message.mediaUrl && message.mediaType === "audio") {
|
||||
viewListMessages.push(
|
||||
<div className="viewItemRight3" key={message.id}>
|
||||
{message.messageBody}
|
||||
<ReactAudioPlayer
|
||||
src={`${SERVER_URL}${message.mediaUrl}`}
|
||||
controls
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
} else if (message.mediaUrl) {
|
||||
viewListMessages.push(
|
||||
<div className="viewItemRight" key={message.id}>
|
||||
<a
|
||||
href={`${SERVER_URL}${message.mediaUrl}`}
|
||||
className="textContentItem"
|
||||
>
|
||||
{message.messageBody}
|
||||
<hr></hr>
|
||||
Download <FiDownload size="20" />
|
||||
</a>
|
||||
</div>
|
||||
);
|
||||
} else {
|
||||
viewListMessages.push(
|
||||
<div className="viewItemRight" key={message.id}>
|
||||
<span className="textContentItem ">{message.messageBody}</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
return viewListMessages;
|
||||
} else {
|
||||
return (
|
||||
<div className="viewWrapSayHi">
|
||||
<span className="textSayHi">Diga olá para o seu novo contato</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Card className="viewChatBoard">
|
||||
<div className="headerChatBoard">
|
||||
<img className="viewAvatarItem" src={profileDefaultPic} alt="" />
|
||||
<img
|
||||
className="viewAvatarItem"
|
||||
src={currentPeerContact.imageURL || profileDefaultPic}
|
||||
alt=""
|
||||
/>
|
||||
<span className="textHeaderChatBoard">
|
||||
<p style={{ fontSize: "20px" }}>{currentPeerContact.name}</p>
|
||||
</span>
|
||||
<div className="aboutme">
|
||||
<span>
|
||||
<p>Status do contato</p>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<ScrollToBottom className="viewListContentChat">
|
||||
<div className="viewListContentChat">
|
||||
{listMessages.map((message, index) =>
|
||||
message.userId === 0 ? (
|
||||
<div className="viewItemLeft" key={message.id}>
|
||||
<span className="textContentItem">{message.messageBody}</span>
|
||||
</div>
|
||||
) : (
|
||||
<div className="viewItemRight" key={message.id}>
|
||||
<span className="textContentItem">{message.messageBody}</span>
|
||||
</div>
|
||||
)
|
||||
)}
|
||||
</div>
|
||||
<div className="viewListContentChat">{renderMessages()}</div>
|
||||
</ScrollToBottom>
|
||||
<div className="viewBottom">
|
||||
<img className="icOpenGallery" src={uploadPic} alt="" />
|
||||
<input
|
||||
// ref={input => input && input.focus()}
|
||||
name="inputMessage"
|
||||
className="viewInput"
|
||||
placeholder="mensagem"
|
||||
value={inputMessage}
|
||||
onChange={handleChangeInput}
|
||||
onKeyPress={e => {
|
||||
if (e.key === "Enter") {
|
||||
handleSendMessage();
|
||||
}
|
||||
}}
|
||||
></input>
|
||||
<img
|
||||
className="icSend"
|
||||
src={sendPic}
|
||||
alt=""
|
||||
onClick={handleSendMessage}
|
||||
/>
|
||||
</div>
|
||||
{media.preview ? (
|
||||
<div className="viewMediaBottom">
|
||||
<FiX
|
||||
color="gray"
|
||||
className="icOpenGallery"
|
||||
onClick={e => setMedia(mediaInitialState)}
|
||||
/>
|
||||
<span className="viewMediaInput">
|
||||
{media.name}
|
||||
{/* <img src={media.preview} alt=""></img> */}
|
||||
</span>
|
||||
<RiSendPlane2Line
|
||||
color="gray"
|
||||
className="icSend"
|
||||
onClick={handleUploadMedia}
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<div className="viewBottom">
|
||||
<div>
|
||||
{showEmoji ? (
|
||||
<div className="viewStickers">
|
||||
<Picker onSelect={handleAddEmoji} />
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
<FiSmile
|
||||
color="gray"
|
||||
className="icOpenEmojis"
|
||||
onClick={e => setShowEmoji(prevState => !prevState)}
|
||||
/>
|
||||
<label htmlFor="upload-button">
|
||||
<FiPaperclip color="gray" className="icOpenGallery" />
|
||||
</label>
|
||||
<input
|
||||
type="file"
|
||||
id="upload-button"
|
||||
style={{ display: "none" }}
|
||||
onChange={handleChangeMedia}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<input
|
||||
// ref={input => inputMessage && inputMessage.focus()}
|
||||
name="inputMessage"
|
||||
autoComplete="off"
|
||||
className="viewInput"
|
||||
placeholder="Digite uma mensagem"
|
||||
onPaste={handleInputPaste}
|
||||
value={inputMessage}
|
||||
onChange={handleChangeInput}
|
||||
onKeyPress={e => {
|
||||
if (e.key === "Enter") {
|
||||
handleSendMessage();
|
||||
}
|
||||
}}
|
||||
/>
|
||||
|
||||
<FiSend color="gray" className="icSend" onClick={handleSendMessage} />
|
||||
</div>
|
||||
)}
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user