migration to WSL

This commit is contained in:
canove
2020-06-24 09:40:51 -03:00
parent 0270ae09e6
commit c60c0f44fc
47 changed files with 17939 additions and 17696 deletions

14
.vscode/launch.json vendored Normal file
View File

@@ -0,0 +1,14 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Launch Program",
"program": "${workspaceFolder}\\backend\\app.js"
}
]
}

View File

@@ -1,4 +1,5 @@
NODE_ENV=development NODE_ENV=development
HOST=localhost
PORT=8080 PORT=8080
DB_HOST= DB_HOST=

View File

@@ -37,7 +37,7 @@ app.use(WhatsRoutes);
app.use("/auth", AuthRoutes); app.use("/auth", AuthRoutes);
app.use((error, req, res, next) => { app.use((error, req, res, next) => {
console.log(error); // console.log(error);
const status = error.statusCode || 500; const status = error.statusCode || 500;
const message = error.message; const message = error.message;
const data = error.data; const data = error.data;

View File

@@ -1,6 +1,8 @@
const Contact = require("../models/Contact"); const Contact = require("../models/Contact");
const Message = require("../models/Message"); const Message = require("../models/Message");
const Sequelize = require("sequelize"); const Sequelize = require("sequelize");
const { getIO } = require("../socket");
const { getWbot } = require("./wbot");
exports.getContacts = async (req, res) => { exports.getContacts = async (req, res) => {
const { searchParam } = req.query; const { searchParam } = req.query;
@@ -44,3 +46,30 @@ exports.getContacts = async (req, res) => {
console.log(err); console.log(err);
} }
}; };
exports.createContact = async (req, res, next) => {
const wbot = getWbot();
const io = getIO();
const { number, name } = req.body;
try {
const res = await wbot.isRegisteredUser(`55${number}@c.us`);
if (!res) {
const error = new Error("O número informado não é um Whatsapp Válido");
error.statusCode = 422;
throw error;
}
const profilePicUrl = await wbot.getProfilePicUrl(`55${number}@c.us`);
const contact = await Contact.create({
name,
number: `55${number}`,
profilePicUrl,
});
res.status(200).json(contact);
} catch (err) {
next(err);
}
};

View File

@@ -24,7 +24,7 @@ const setMessagesAsRead = async contactId => {
const error = new Error( const error = new Error(
"Erro ao definir as mensagens como lidas no banco de dados" "Erro ao definir as mensagens como lidas no banco de dados"
); );
error.satusCode = 501; error.statusCode = 501;
throw error; throw error;
} }
@@ -61,7 +61,7 @@ exports.getContactMessages = async (req, res, next) => {
const contact = await Contact.findByPk(contactId); const contact = await Contact.findByPk(contactId);
if (!contact) { if (!contact) {
const error = new Error("Erro ao localizar o contato no banco de dados"); const error = new Error("Erro ao localizar o contato no banco de dados");
error.satusCode = 501; error.statusCode = 501;
throw error; throw error;
} }
@@ -131,7 +131,7 @@ exports.postCreateContactMessage = async (req, res, next) => {
const newMessage = await contact.createMessage(message); const newMessage = await contact.createMessage(message);
if (!newMessage) { if (!newMessage) {
const error = new Error("Erro ao inserir a mensagem no banco de dados"); const error = new Error("Erro ao inserir a mensagem no banco de dados");
error.satusCode = 501; error.statusCode = 501;
throw error; throw error;
} }

View File

@@ -26,7 +26,7 @@ const wbotMessageListener = () => {
}); });
if (contact) { if (contact) {
await contact.update({ imageURL: imageUrl }); await contact.update({ profilePicUrl: imageUrl });
} }
if (!contact) { if (!contact) {
@@ -34,7 +34,7 @@ const wbotMessageListener = () => {
contact = await Contact.create({ contact = await Contact.create({
name: msgContact.pushname || msgContact.number.toString(), name: msgContact.pushname || msgContact.number.toString(),
number: msgContact.number, number: msgContact.number,
imageURL: imageUrl, profilePicUrl: imageUrl,
}); });
} catch (err) { } catch (err) {
console.log(err); console.log(err);
@@ -113,7 +113,7 @@ const wbotMessageListener = () => {
const error = new Error( const error = new Error(
"Erro ao alterar o ack da mensagem no banco de dados" "Erro ao alterar o ack da mensagem no banco de dados"
); );
error.satusCode = 501; error.statusCode = 501;
throw error; throw error;
} }
await messageToUpdate.update({ ack: ack }); await messageToUpdate.update({ ack: ack });

View File

@@ -1,4 +1,6 @@
const Whatsapp = require("../models/Whatsapp"); const Whatsapp = require("../models/Whatsapp");
const { getIO } = require("../socket");
const { getWbot, init } = require("./wbot");
exports.getSession = async (req, res, next) => { exports.getSession = async (req, res, next) => {
try { try {
@@ -13,3 +15,16 @@ exports.getSession = async (req, res, next) => {
next(err); next(err);
} }
}; };
exports.getContacts = async (req, res, next) => {
const io = getIO();
const wbot = getWbot();
try {
const phoneContacts = await wbot.getContacts();
return res.status(200).json(phoneContacts);
} catch (err) {
next(err);
}
};

View File

@@ -5,6 +5,7 @@ module.exports = (req, res, next) => {
try { try {
const [, token] = req.get("Authorization").split(" "); const [, token] = req.get("Authorization").split(" ");
decodedToken = jwt.verify(token, "mysecret"); decodedToken = jwt.verify(token, "mysecret");
req.userId = decodedToken.userId;
} catch (err) { } catch (err) {
err.statusCode = 401; err.statusCode = 401;
err.message = "invalidToken"; err.message = "invalidToken";
@@ -17,6 +18,5 @@ module.exports = (req, res, next) => {
next(error); next(error);
} }
req.userId = decodedToken.userId;
next(); next();
}; };

View File

@@ -7,7 +7,7 @@ const Message = require("./Message");
const Contact = sequelize.define("contact", { const Contact = sequelize.define("contact", {
name: { type: Sequelize.STRING(100), allowNull: false }, name: { type: Sequelize.STRING(100), allowNull: false },
number: { type: Sequelize.STRING(15), allowNull: false }, number: { type: Sequelize.STRING(15), allowNull: false },
imageURL: { type: Sequelize.STRING(200) }, profilePicUrl: { type: Sequelize.STRING(200) },
lastMessage: { type: Sequelize.TEXT }, lastMessage: { type: Sequelize.TEXT },
}); });

View File

@@ -2,6 +2,7 @@ const express = require("express");
const { body } = require("express-validator"); const { body } = require("express-validator");
const User = require("../models/User"); const User = require("../models/User");
const authController = require("../controllers/auth"); const authController = require("../controllers/auth");
const isAuth = require("../middleware/is-auth");
const routes = express.Router(); const routes = express.Router();
@@ -27,4 +28,8 @@ routes.put(
routes.post("/login", authController.login); routes.post("/login", authController.login);
routes.get("/check", isAuth, (req, res) => {
res.status(200).json({ authenticated: true });
});
module.exports = routes; module.exports = routes;

View File

@@ -8,4 +8,6 @@ const routes = express.Router();
routes.get("/contacts", isAuth, ContactController.getContacts); routes.get("/contacts", isAuth, ContactController.getContacts);
// routes.post(ContactController.postCreateContact); // routes.post(ContactController.postCreateContact);
routes.post("/contacts", isAuth, ContactController.createContact);
module.exports = routes; module.exports = routes;

View File

@@ -12,4 +12,11 @@ routes.get("/whatsapp/session", isAuth, WhatsappController.getSession);
// WhatsappController.postCreateContactMessage // WhatsappController.postCreateContactMessage
// ); // );
routes.get("/whatsapp/contacts", isAuth, WhatsappController.getContacts);
// routes.post(
// "/messages/:contactId",
// isAuth,
// WhatsappController.postCreateContactMessage
// );
module.exports = routes; module.exports = routes;

View File

@@ -15,9 +15,29 @@ const useAuth = () => {
api.defaults.headers.Authorization = `Bearer ${JSON.parse(token)}`; api.defaults.headers.Authorization = `Bearer ${JSON.parse(token)}`;
setIsAuth(true); setIsAuth(true);
} }
const checkAuth = async () => {
if (
history.location.pathname === "/login" ||
history.location.pathname === "/signup"
) {
setLoading(false);
setLoading(false); return;
}, []); }
try {
const res = await api.get("/auth/check");
if (res.status === 200) {
setIsAuth(true);
setLoading(false);
}
} catch (err) {
setLoading(false);
setIsAuth(false);
alert("Erro de autenticação. Por favor, faça login novamente");
}
};
checkAuth();
}, [history.location.pathname]);
const handleLogin = async (e, user) => { const handleLogin = async (e, user) => {
e.preventDefault(); e.preventDefault();

View File

@@ -0,0 +1,72 @@
import React, { useState } from "react";
import Button from "@material-ui/core/Button";
import TextField from "@material-ui/core/TextField";
import Dialog from "@material-ui/core/Dialog";
import DialogActions from "@material-ui/core/DialogActions";
import DialogContent from "@material-ui/core/DialogContent";
import DialogTitle from "@material-ui/core/DialogTitle";
const AddContactModal = ({ modalOpen, setModalOpen, handleAddContact }) => {
const initialState = { name: "", number: "" };
const [contact, setContact] = useState(initialState);
const handleClose = () => {
setModalOpen(false);
};
const handleChangeInput = e => {
setContact({ ...contact, [e.target.name]: e.target.value });
};
return (
<div>
<Dialog
open={modalOpen}
onClose={handleClose}
aria-labelledby="form-dialog-title"
>
<DialogTitle id="form-dialog-title">Adicionar contato</DialogTitle>
<DialogContent>
<TextField
autoComplete="false"
autoFocus
margin="dense"
name="number"
id="contactNumber"
label="Número"
type="text"
value={contact.number}
onChange={handleChangeInput}
fullWidth
/>
<TextField
margin="dense"
name="name"
id="contactName"
label="Nome do contato"
type="text"
value={contact.name}
onChange={handleChangeInput}
fullWidth
/>
</DialogContent>
<DialogActions>
<Button onClick={handleClose} color="primary">
Cancelar
</Button>
<Button
onClick={e => {
handleAddContact(contact);
setContact(initialState);
}}
color="primary"
>
Adicionar
</Button>
</DialogActions>
</Dialog>
</div>
);
};
export default AddContactModal;

View File

@@ -16,10 +16,13 @@ import ListItemText from "@material-ui/core/ListItemText";
import ListItemAvatar from "@material-ui/core/ListItemAvatar"; import ListItemAvatar from "@material-ui/core/ListItemAvatar";
import Typography from "@material-ui/core/Typography"; import Typography from "@material-ui/core/Typography";
import Avatar from "@material-ui/core/Avatar"; import Avatar from "@material-ui/core/Avatar";
import AddIcon from "@material-ui/icons/Add";
import Divider from "@material-ui/core/Divider"; import Divider from "@material-ui/core/Divider";
import Badge from "@material-ui/core/Badge"; import Badge from "@material-ui/core/Badge";
import SearchIcon from "@material-ui/icons/Search"; import SearchIcon from "@material-ui/icons/Search";
import InputBase from "@material-ui/core/InputBase"; import InputBase from "@material-ui/core/InputBase";
import Fab from "@material-ui/core/Fab";
import AddContactModal from "../AddContact/AddContactModal";
import ContactsHeader from "../ContactsHeader/ContactsHeader"; import ContactsHeader from "../ContactsHeader/ContactsHeader";
@@ -118,6 +121,14 @@ const useStyles = makeStyles(theme => ({
marginTop: 12, marginTop: 12,
// marginLeft: -12, // marginLeft: -12,
}, },
fabButton: {
position: "absolute",
zIndex: 1,
bottom: 20,
left: 0,
right: 0,
margin: "0 auto",
},
})); }));
const ContactsList = () => { const ContactsList = () => {
@@ -128,6 +139,8 @@ const ContactsList = () => {
const [loading, setLoading] = useState(); const [loading, setLoading] = useState();
const [searchParam, setSearchParam] = useState(""); const [searchParam, setSearchParam] = useState("");
const [modalOpen, setModalOpen] = useState(false);
const history = useHistory(); const history = useHistory();
useEffect(() => { useEffect(() => {
@@ -209,7 +222,7 @@ const ContactsList = () => {
body: `${data.message.messageBody} - ${moment(new Date()) body: `${data.message.messageBody} - ${moment(new Date())
.tz("America/Sao_Paulo") .tz("America/Sao_Paulo")
.format("DD/MM/YY - HH:mm")}`, .format("DD/MM/YY - HH:mm")}`,
icon: data.contact.imageURL, icon: data.contact.profilePicUrl,
}; };
new Notification(`Mensagem de ${data.contact.name}`, options); new Notification(`Mensagem de ${data.contact.name}`, options);
document.getElementById("sound").play(); document.getElementById("sound").play();
@@ -234,9 +247,34 @@ const ContactsList = () => {
setSearchParam(e.target.value.toLowerCase()); setSearchParam(e.target.value.toLowerCase());
}; };
const handleShowContactModal = e => {
setModalOpen(true);
};
const handleAddContact = async contact => {
try {
const res = await api.post("/contacts", contact);
setContacts(prevState => [res.data, ...prevState]);
setModalOpen(false);
console.log(res.data);
} catch (err) {
if (err.response.status === 422) {
console.log("deu erro", err.response);
alert(err.response.data.message);
} else {
alert(err);
}
}
};
return ( return (
<div className={classes.contactsWrapper}> <div className={classes.contactsWrapper}>
<ContactsHeader /> <ContactsHeader />
<AddContactModal
setModalOpen={setModalOpen}
modalOpen={modalOpen}
handleAddContact={handleAddContact}
/>
<Paper variant="outlined" square className={classes.contactsSearchBox}> <Paper variant="outlined" square className={classes.contactsSearchBox}>
<div className={classes.serachInputWrapper}> <div className={classes.serachInputWrapper}>
<SearchIcon className={classes.searchIcon} /> <SearchIcon className={classes.searchIcon} />
@@ -260,7 +298,9 @@ const ContactsList = () => {
<ListItemAvatar> <ListItemAvatar>
<Avatar <Avatar
src={ src={
contact.imageURL ? contact.imageURL : profileDefaultPic contact.profilePicUrl
? contact.profilePicUrl
: profileDefaultPic
} }
></Avatar> ></Avatar>
</ListItemAvatar> </ListItemAvatar>
@@ -320,6 +360,14 @@ const ContactsList = () => {
<CircularProgress className={classes.circleLoading} /> <CircularProgress className={classes.circleLoading} />
</div> </div>
) : null} ) : null}
<Fab
color="secondary"
aria-label="add"
className={classes.fabButton}
onClick={handleShowContactModal}
>
<AddIcon />
</Fab>
</Paper> </Paper>
<audio id="sound" preload="auto"> <audio id="sound" preload="auto">
<source src={require("../../../../util/sound.mp3")} type="audio/mpeg" /> <source src={require("../../../../util/sound.mp3")} type="audio/mpeg" />

View File

@@ -299,7 +299,7 @@ const MessagesList = () => {
}; };
const scrollToBottom = () => { const scrollToBottom = () => {
if (lastMessageRef) { if (lastMessageRef.current) {
lastMessageRef.current.scrollIntoView({}); lastMessageRef.current.scrollIntoView({});
} }
}; };
@@ -449,11 +449,11 @@ const MessagesList = () => {
return ( return (
<div className={classes.mainWrapper}> <div className={classes.mainWrapper}>
<Card variant="outlined" square className={classes.messagesHeader}> <Card variant="outlined" square className={classes.messagesHeader}>
{!loading ? ( {contact.name ? (
<CardHeader <CardHeader
titleTypographyProps={{ noWrap: true }} titleTypographyProps={{ noWrap: true }}
subheaderTypographyProps={{ noWrap: true }} subheaderTypographyProps={{ noWrap: true }}
avatar={<Avatar alt="contact_image" src={contact.imageURL} />} avatar={<Avatar alt="contact_image" src={contact.profilePicUrl} />}
title={contact.name} title={contact.name}
subheader="Contact Status" subheader="Contact Status"
/> />

View File

@@ -9,11 +9,27 @@ import Profile from "./pages/Profile/Profile";
import Signup from "./pages/Signup/Signup"; import Signup from "./pages/Signup/Signup";
import Login from "./pages/Login/Login"; import Login from "./pages/Login/Login";
import WhatsAuth from "./pages/WhatsAuth/WhatsAuth"; import WhatsAuth from "./pages/WhatsAuth/WhatsAuth";
import Backdrop from "@material-ui/core/Backdrop";
import CircularProgress from "@material-ui/core/CircularProgress";
import { makeStyles } from "@material-ui/core/styles";
const useStyles = makeStyles(theme => ({
backdrop: {
zIndex: theme.zIndex.drawer + 1,
color: "#fff",
},
}));
const PrivateRoute = ({ component: Component, ...rest }) => { const PrivateRoute = ({ component: Component, ...rest }) => {
const classes = useStyles();
const { isAuth, loading } = useContext(AuthContext); const { isAuth, loading } = useContext(AuthContext);
if (loading) return <h1>Loading...</h1>; if (loading)
return (
<Backdrop className={classes.backdrop} open={loading}>
<CircularProgress color="inherit" />
</Backdrop>
);
return ( return (
<Route <Route
@@ -32,9 +48,15 @@ const PrivateRoute = ({ component: Component, ...rest }) => {
}; };
const PublicRoute = ({ component: Component, ...rest }) => { const PublicRoute = ({ component: Component, ...rest }) => {
const classes = useStyles();
const { isAuth, loading } = useContext(AuthContext); const { isAuth, loading } = useContext(AuthContext);
if (loading) return <h1>Loading...</h1>; if (loading)
return (
<Backdrop className={classes.backdrop} open={loading}>
<CircularProgress color="inherit" />
</Backdrop>
);
return ( return (
<Route <Route

View File

@@ -0,0 +1,4 @@
[ZoneTransfer]
ZoneId=3
ReferrerUrl=https://notificationsounds.com/message-tones/juntos-607
HostUrl=https://notificationsounds.com/message-tones/juntos-607/download/mp3

View File

@@ -0,0 +1,4 @@
[ZoneTransfer]
ZoneId=3
ReferrerUrl=https://notificationsounds.com/message-tones/juntos-607
HostUrl=https://notificationsounds.com/message-tones/juntos-607/download/ogg