mirror of
https://github.com/cheveguerra/whaticket-community.git
synced 2026-04-21 21:29:25 +00:00
migration to WSL
This commit is contained in:
14
.vscode/launch.json
vendored
Normal file
14
.vscode/launch.json
vendored
Normal 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"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
NODE_ENV=development
|
||||
HOST=localhost
|
||||
PORT=8080
|
||||
|
||||
DB_HOST=
|
||||
|
||||
@@ -37,7 +37,7 @@ app.use(WhatsRoutes);
|
||||
app.use("/auth", AuthRoutes);
|
||||
|
||||
app.use((error, req, res, next) => {
|
||||
console.log(error);
|
||||
// console.log(error);
|
||||
const status = error.statusCode || 500;
|
||||
const message = error.message;
|
||||
const data = error.data;
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
const Contact = require("../models/Contact");
|
||||
const Message = require("../models/Message");
|
||||
const Sequelize = require("sequelize");
|
||||
const { getIO } = require("../socket");
|
||||
const { getWbot } = require("./wbot");
|
||||
|
||||
exports.getContacts = async (req, res) => {
|
||||
const { searchParam } = req.query;
|
||||
@@ -44,3 +46,30 @@ exports.getContacts = async (req, res) => {
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -24,7 +24,7 @@ const setMessagesAsRead = async contactId => {
|
||||
const error = new Error(
|
||||
"Erro ao definir as mensagens como lidas no banco de dados"
|
||||
);
|
||||
error.satusCode = 501;
|
||||
error.statusCode = 501;
|
||||
throw error;
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ exports.getContactMessages = async (req, res, next) => {
|
||||
const contact = await Contact.findByPk(contactId);
|
||||
if (!contact) {
|
||||
const error = new Error("Erro ao localizar o contato no banco de dados");
|
||||
error.satusCode = 501;
|
||||
error.statusCode = 501;
|
||||
throw error;
|
||||
}
|
||||
|
||||
@@ -131,7 +131,7 @@ exports.postCreateContactMessage = async (req, res, next) => {
|
||||
const newMessage = await contact.createMessage(message);
|
||||
if (!newMessage) {
|
||||
const error = new Error("Erro ao inserir a mensagem no banco de dados");
|
||||
error.satusCode = 501;
|
||||
error.statusCode = 501;
|
||||
throw error;
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ const wbotMessageListener = () => {
|
||||
});
|
||||
|
||||
if (contact) {
|
||||
await contact.update({ imageURL: imageUrl });
|
||||
await contact.update({ profilePicUrl: imageUrl });
|
||||
}
|
||||
|
||||
if (!contact) {
|
||||
@@ -34,7 +34,7 @@ const wbotMessageListener = () => {
|
||||
contact = await Contact.create({
|
||||
name: msgContact.pushname || msgContact.number.toString(),
|
||||
number: msgContact.number,
|
||||
imageURL: imageUrl,
|
||||
profilePicUrl: imageUrl,
|
||||
});
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
@@ -113,7 +113,7 @@ const wbotMessageListener = () => {
|
||||
const error = new Error(
|
||||
"Erro ao alterar o ack da mensagem no banco de dados"
|
||||
);
|
||||
error.satusCode = 501;
|
||||
error.statusCode = 501;
|
||||
throw error;
|
||||
}
|
||||
await messageToUpdate.update({ ack: ack });
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
const Whatsapp = require("../models/Whatsapp");
|
||||
const { getIO } = require("../socket");
|
||||
const { getWbot, init } = require("./wbot");
|
||||
|
||||
exports.getSession = async (req, res, next) => {
|
||||
try {
|
||||
@@ -13,3 +15,16 @@ exports.getSession = async (req, res, next) => {
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -5,6 +5,7 @@ module.exports = (req, res, next) => {
|
||||
try {
|
||||
const [, token] = req.get("Authorization").split(" ");
|
||||
decodedToken = jwt.verify(token, "mysecret");
|
||||
req.userId = decodedToken.userId;
|
||||
} catch (err) {
|
||||
err.statusCode = 401;
|
||||
err.message = "invalidToken";
|
||||
@@ -17,6 +18,5 @@ module.exports = (req, res, next) => {
|
||||
next(error);
|
||||
}
|
||||
|
||||
req.userId = decodedToken.userId;
|
||||
next();
|
||||
};
|
||||
|
||||
@@ -7,7 +7,7 @@ const Message = require("./Message");
|
||||
const Contact = sequelize.define("contact", {
|
||||
name: { type: Sequelize.STRING(100), allowNull: false },
|
||||
number: { type: Sequelize.STRING(15), allowNull: false },
|
||||
imageURL: { type: Sequelize.STRING(200) },
|
||||
profilePicUrl: { type: Sequelize.STRING(200) },
|
||||
lastMessage: { type: Sequelize.TEXT },
|
||||
});
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ const express = require("express");
|
||||
const { body } = require("express-validator");
|
||||
const User = require("../models/User");
|
||||
const authController = require("../controllers/auth");
|
||||
const isAuth = require("../middleware/is-auth");
|
||||
|
||||
const routes = express.Router();
|
||||
|
||||
@@ -27,4 +28,8 @@ routes.put(
|
||||
|
||||
routes.post("/login", authController.login);
|
||||
|
||||
routes.get("/check", isAuth, (req, res) => {
|
||||
res.status(200).json({ authenticated: true });
|
||||
});
|
||||
|
||||
module.exports = routes;
|
||||
|
||||
@@ -8,4 +8,6 @@ const routes = express.Router();
|
||||
routes.get("/contacts", isAuth, ContactController.getContacts);
|
||||
// routes.post(ContactController.postCreateContact);
|
||||
|
||||
routes.post("/contacts", isAuth, ContactController.createContact);
|
||||
|
||||
module.exports = routes;
|
||||
|
||||
@@ -12,4 +12,11 @@ routes.get("/whatsapp/session", isAuth, WhatsappController.getSession);
|
||||
// WhatsappController.postCreateContactMessage
|
||||
// );
|
||||
|
||||
routes.get("/whatsapp/contacts", isAuth, WhatsappController.getContacts);
|
||||
// routes.post(
|
||||
// "/messages/:contactId",
|
||||
// isAuth,
|
||||
// WhatsappController.postCreateContactMessage
|
||||
// );
|
||||
|
||||
module.exports = routes;
|
||||
|
||||
@@ -15,9 +15,29 @@ const useAuth = () => {
|
||||
api.defaults.headers.Authorization = `Bearer ${JSON.parse(token)}`;
|
||||
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) => {
|
||||
e.preventDefault();
|
||||
|
||||
@@ -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;
|
||||
@@ -16,10 +16,13 @@ import ListItemText from "@material-ui/core/ListItemText";
|
||||
import ListItemAvatar from "@material-ui/core/ListItemAvatar";
|
||||
import Typography from "@material-ui/core/Typography";
|
||||
import Avatar from "@material-ui/core/Avatar";
|
||||
import AddIcon from "@material-ui/icons/Add";
|
||||
import Divider from "@material-ui/core/Divider";
|
||||
import Badge from "@material-ui/core/Badge";
|
||||
import SearchIcon from "@material-ui/icons/Search";
|
||||
import InputBase from "@material-ui/core/InputBase";
|
||||
import Fab from "@material-ui/core/Fab";
|
||||
import AddContactModal from "../AddContact/AddContactModal";
|
||||
|
||||
import ContactsHeader from "../ContactsHeader/ContactsHeader";
|
||||
|
||||
@@ -118,6 +121,14 @@ const useStyles = makeStyles(theme => ({
|
||||
marginTop: 12,
|
||||
// marginLeft: -12,
|
||||
},
|
||||
fabButton: {
|
||||
position: "absolute",
|
||||
zIndex: 1,
|
||||
bottom: 20,
|
||||
left: 0,
|
||||
right: 0,
|
||||
margin: "0 auto",
|
||||
},
|
||||
}));
|
||||
|
||||
const ContactsList = () => {
|
||||
@@ -128,6 +139,8 @@ const ContactsList = () => {
|
||||
const [loading, setLoading] = useState();
|
||||
const [searchParam, setSearchParam] = useState("");
|
||||
|
||||
const [modalOpen, setModalOpen] = useState(false);
|
||||
|
||||
const history = useHistory();
|
||||
|
||||
useEffect(() => {
|
||||
@@ -209,7 +222,7 @@ const ContactsList = () => {
|
||||
body: `${data.message.messageBody} - ${moment(new Date())
|
||||
.tz("America/Sao_Paulo")
|
||||
.format("DD/MM/YY - HH:mm")}`,
|
||||
icon: data.contact.imageURL,
|
||||
icon: data.contact.profilePicUrl,
|
||||
};
|
||||
new Notification(`Mensagem de ${data.contact.name}`, options);
|
||||
document.getElementById("sound").play();
|
||||
@@ -234,9 +247,34 @@ const ContactsList = () => {
|
||||
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 (
|
||||
<div className={classes.contactsWrapper}>
|
||||
<ContactsHeader />
|
||||
<AddContactModal
|
||||
setModalOpen={setModalOpen}
|
||||
modalOpen={modalOpen}
|
||||
handleAddContact={handleAddContact}
|
||||
/>
|
||||
<Paper variant="outlined" square className={classes.contactsSearchBox}>
|
||||
<div className={classes.serachInputWrapper}>
|
||||
<SearchIcon className={classes.searchIcon} />
|
||||
@@ -260,7 +298,9 @@ const ContactsList = () => {
|
||||
<ListItemAvatar>
|
||||
<Avatar
|
||||
src={
|
||||
contact.imageURL ? contact.imageURL : profileDefaultPic
|
||||
contact.profilePicUrl
|
||||
? contact.profilePicUrl
|
||||
: profileDefaultPic
|
||||
}
|
||||
></Avatar>
|
||||
</ListItemAvatar>
|
||||
@@ -320,6 +360,14 @@ const ContactsList = () => {
|
||||
<CircularProgress className={classes.circleLoading} />
|
||||
</div>
|
||||
) : null}
|
||||
<Fab
|
||||
color="secondary"
|
||||
aria-label="add"
|
||||
className={classes.fabButton}
|
||||
onClick={handleShowContactModal}
|
||||
>
|
||||
<AddIcon />
|
||||
</Fab>
|
||||
</Paper>
|
||||
<audio id="sound" preload="auto">
|
||||
<source src={require("../../../../util/sound.mp3")} type="audio/mpeg" />
|
||||
|
||||
@@ -299,7 +299,7 @@ const MessagesList = () => {
|
||||
};
|
||||
|
||||
const scrollToBottom = () => {
|
||||
if (lastMessageRef) {
|
||||
if (lastMessageRef.current) {
|
||||
lastMessageRef.current.scrollIntoView({});
|
||||
}
|
||||
};
|
||||
@@ -449,11 +449,11 @@ const MessagesList = () => {
|
||||
return (
|
||||
<div className={classes.mainWrapper}>
|
||||
<Card variant="outlined" square className={classes.messagesHeader}>
|
||||
{!loading ? (
|
||||
{contact.name ? (
|
||||
<CardHeader
|
||||
titleTypographyProps={{ noWrap: true }}
|
||||
subheaderTypographyProps={{ noWrap: true }}
|
||||
avatar={<Avatar alt="contact_image" src={contact.imageURL} />}
|
||||
avatar={<Avatar alt="contact_image" src={contact.profilePicUrl} />}
|
||||
title={contact.name}
|
||||
subheader="Contact Status"
|
||||
/>
|
||||
|
||||
@@ -9,11 +9,27 @@ import Profile from "./pages/Profile/Profile";
|
||||
import Signup from "./pages/Signup/Signup";
|
||||
import Login from "./pages/Login/Login";
|
||||
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 classes = useStyles();
|
||||
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 (
|
||||
<Route
|
||||
@@ -32,9 +48,15 @@ const PrivateRoute = ({ component: Component, ...rest }) => {
|
||||
};
|
||||
|
||||
const PublicRoute = ({ component: Component, ...rest }) => {
|
||||
const classes = useStyles();
|
||||
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 (
|
||||
<Route
|
||||
|
||||
4
frontend/src/util/sound.mp3:Zone.Identifier
Normal file
4
frontend/src/util/sound.mp3:Zone.Identifier
Normal 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
|
||||
4
frontend/src/util/sound.ogg:Zone.Identifier
Normal file
4
frontend/src/util/sound.ogg:Zone.Identifier
Normal 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
|
||||
Reference in New Issue
Block a user