diff --git a/backend/src/controllers/ContactController.ts b/backend/src/controllers/ContactController.ts index 1b194a1..af0ad0a 100644 --- a/backend/src/controllers/ContactController.ts +++ b/backend/src/controllers/ContactController.ts @@ -124,22 +124,13 @@ export const store = async (req: Request, res: Response): Promise => { newContact.number = addStartPhoneNumber(newContact.number); - const validNumber = await CheckIsValidContact(newContact.number); - - // const validNumber: any = await CheckContactNumber(newContact.number) + const validNumber = await CheckIsValidContact(newContact.number); if (!validNumber) { throw new AppError("ERR_WAPP_CHECK_CONTACT"); } - const profilePicUrl = await GetProfilePicUrl(validNumber); - - console.log("xxxxxxxxxxx profilePicUrl: ", profilePicUrl); - - // console.log(`newContact.name: ${newContact.name}\n - // newContact.number: ${newContact.number}\n - // newContact.email: ${newContact.email}\n - // newContact.extraInfo: ${newContact.extraInfo}`) + const profilePicUrl = await GetProfilePicUrl(validNumber); let name = newContact.name; let number = validNumber; diff --git a/backend/src/controllers/WhatsAppController.ts b/backend/src/controllers/WhatsAppController.ts index c71d883..ca61d34 100644 --- a/backend/src/controllers/WhatsAppController.ts +++ b/backend/src/controllers/WhatsAppController.ts @@ -421,13 +421,14 @@ export const update = async ( return res.status(200).json({ message: invalidPhoneName }); } - const { urlApi, isOfficial, phoneNumberId, wabaId } = whatsappData; + const { urlApi, isOfficial, phoneNumberId, number, wabaId } = whatsappData; const invalid = checkWhatsAppData({ urlApi, isOfficial, phoneNumberId, - wabaId + wabaId, + number }); if (invalid) { @@ -572,5 +573,5 @@ const checkWhatsAppData = ({ return { message: "Phone number is required!" }; } else if (!isOfficial && (!urlApi || urlApi.trim() == "")) { return { message: "urlApi is required!" }; - } + } }; diff --git a/backend/src/helpers/GetDefaultWhatsApp.ts b/backend/src/helpers/GetDefaultWhatsApp.ts index 5c1033f..c19757a 100644 --- a/backend/src/helpers/GetDefaultWhatsApp.ts +++ b/backend/src/helpers/GetDefaultWhatsApp.ts @@ -6,27 +6,26 @@ import UserQueue from "../models/UserQueue"; import { Op, where } from "sequelize"; -import wbotByUserQueue from "../helpers/GetWbotByUserQueue"; +import wbotByUserQueue from "../helpers/GetWbotByUserQueue"; import { WhatsIndex } from "./LoadBalanceWhatsSameQueue"; interface Request { userId?: string | number; queueId?: string | number; + ignoreNoWhatsappFound?: boolean } - -//const GetDefaultWhatsApp = async (userId?: string | number): Promise => { - + const GetDefaultWhatsApp = async ({ userId, - queueId -}: Request): Promise => { - // test del + queueId, + ignoreNoWhatsappFound = false +}: Request): Promise => { let defaultWhatsapp = await Whatsapp.findOne({ where: { isDefault: true } }); - if (!defaultWhatsapp) { + if (!defaultWhatsapp && !ignoreNoWhatsappFound) { if (userId) { let whatsapps = await wbotByUserQueue({ userId, queueId }); @@ -56,17 +55,16 @@ const GetDefaultWhatsApp = async ({ } } else { defaultWhatsapp = await Whatsapp.findOne({ - where: { status: "CONNECTED" } + where: { status: "CONNECTED", isOfficial: false } }); } - } + } - if (!defaultWhatsapp) { + if (!defaultWhatsapp && !ignoreNoWhatsappFound) { throw new AppError("ERR_NO_DEF_WAPP_FOUND"); } - return defaultWhatsapp; - // + return defaultWhatsapp; }; export default GetDefaultWhatsApp; diff --git a/backend/src/services/TicketServices/FindOrCreateTicketServiceBot.ts b/backend/src/services/TicketServices/FindOrCreateTicketServiceBot.ts index 47d6d9f..38d7f6b 100644 --- a/backend/src/services/TicketServices/FindOrCreateTicketServiceBot.ts +++ b/backend/src/services/TicketServices/FindOrCreateTicketServiceBot.ts @@ -29,7 +29,8 @@ const FindOrCreateTicketServiceBot = async ( } }); - const { queues, greetingMessage } = await ShowWhatsAppService(whatsappId); + const { queues, greetingMessage, phoneNumberId } = + await ShowWhatsAppService(whatsappId); //Habilitar esse caso queira usar o bot @@ -102,12 +103,13 @@ const FindOrCreateTicketServiceBot = async ( } ticket = await Ticket.create({ - contactId: groupContact ? groupContact.id : contact.id, - status: status, - userId: botInfo.userIdBot, - isGroup: !!groupContact, - unreadMessages, - whatsappId + contactId: groupContact ? groupContact.id : contact.id, + status: status, + userId: botInfo.userIdBot, + isGroup: !!groupContact, + unreadMessages, + whatsappId, + phoneNumberId }); console.log('yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy') diff --git a/backend/src/services/WbotServices/CheckIsValidContact.ts b/backend/src/services/WbotServices/CheckIsValidContact.ts index 4596f67..8060739 100644 --- a/backend/src/services/WbotServices/CheckIsValidContact.ts +++ b/backend/src/services/WbotServices/CheckIsValidContact.ts @@ -1,27 +1,54 @@ +import axios from "axios"; import AppError from "../../errors/AppError"; import endPointQuery from "../../helpers/EndPointQuery"; import GetDefaultWhatsApp from "../../helpers/GetDefaultWhatsApp"; import { getWbot } from "../../libs/wbot"; -const CheckIsValidContact = async (number: string, ignoreThrow?:boolean): Promise => { +const CheckIsValidContact = async ( + number: string, + ignoreThrow?: boolean +): Promise => { + const defaultWhatsapp = await GetDefaultWhatsApp({ + ignoreNoWhatsappFound: true + }); - const defaultWhatsapp = await GetDefaultWhatsApp({}); + let isValidNumber; - const wbot_url = await getWbot(defaultWhatsapp.id); + if (defaultWhatsapp) { + const wbot_url = await getWbot(defaultWhatsapp.id); - const isValidNumber = await endPointQuery(`${wbot_url}/api/validate`, { mobile: `${number}`, }) + let { data } = await endPointQuery(`${wbot_url}/api/validate`, { + mobile: `${number}` + }); - if(ignoreThrow) return isValidNumber?.data?.number; - - // console.log('isValidNumber.data.number: ', isValidNumber.data.number) + if (data?.isValid) { + isValidNumber = data; + } + } try { + if (!isValidNumber) { + + const { data } = await axios.post( + `${process.env.WHATS_NUMBER_VALIDATOR_URL}/api/validate`, + { mobile: number }, + { + headers: { + "Content-Type": "application/json" + } + } + ); - // const isValidNumber = await wbot.isRegisteredUser(`${number}@c.us`); + isValidNumber = data; + } + + if (ignoreThrow) return isValidNumber?.number; - if (!isValidNumber || isValidNumber && !isValidNumber.data.isValid) { + if (!isValidNumber || (isValidNumber && !isValidNumber.isValid)) { throw new AppError("invalidNumber"); } + + if (isValidNumber && isValidNumber?.isValid) return isValidNumber.number; } catch (err: any) { if (err.message === "invalidNumber") { throw new AppError("ERR_WAPP_INVALID_CONTACT"); @@ -29,10 +56,6 @@ const CheckIsValidContact = async (number: string, ignoreThrow?:boolean): Promis throw new AppError("ERR_WAPP_CHECK_CONTACT"); } - - if (isValidNumber && isValidNumber.data.isValid) - return isValidNumber.data.number - }; export default CheckIsValidContact; diff --git a/backend/src/services/WbotServices/GetProfilePicUrl.ts b/backend/src/services/WbotServices/GetProfilePicUrl.ts index 82be7d2..0fc3ea7 100644 --- a/backend/src/services/WbotServices/GetProfilePicUrl.ts +++ b/backend/src/services/WbotServices/GetProfilePicUrl.ts @@ -1,23 +1,47 @@ +import axios from "axios"; import endPointQuery from "../../helpers/EndPointQuery"; import GetDefaultWhatsApp from "../../helpers/GetDefaultWhatsApp"; import { getWbot } from "../../libs/wbot"; const GetProfilePicUrl = async (number: string): Promise => { + const defaultWhatsapp = await GetDefaultWhatsApp({ + ignoreNoWhatsappFound: true + }); + + let profilePicUrl; - const defaultWhatsapp = await GetDefaultWhatsApp({}); + if (defaultWhatsapp) { + const wbot_url = await getWbot(defaultWhatsapp.id); - const wbot_url = await getWbot(defaultWhatsapp.id); + const {data} = await endPointQuery(`${wbot_url}/api/GetProfilePicUrl`, { + number: `${number}` + }); - let profilePicUrl = await endPointQuery(`${wbot_url}/api/GetProfilePicUrl`, { number: `${number}`, }) - - console.log('profilePicUrl.data.data: ', profilePicUrl.data.data) - - if (profilePicUrl && profilePicUrl.data.data) { - return profilePicUrl.data.data; + if (data?.data) { + profilePicUrl = data.data; + } } + + try { + if (!profilePicUrl) { + const { data } = await axios.post( + `${process.env.WHATS_NUMBER_VALIDATOR_URL}/api/GetProfilePicUrl`, + { number }, + { + headers: { + "Content-Type": "application/json" + } + } + ); + profilePicUrl = data?.data; + } + + if (profilePicUrl) { + return profilePicUrl; + } + } catch (error) {} - return null - + return null; }; export default GetProfilePicUrl; diff --git a/frontend/src/components/ContactModal/index.js b/frontend/src/components/ContactModal/index.js index d67f01c..5b4d924 100644 --- a/frontend/src/components/ContactModal/index.js +++ b/frontend/src/components/ContactModal/index.js @@ -1,26 +1,26 @@ -import React, { useState, useEffect, useRef } from "react"; +import React, { useState, useEffect, useRef } from "react" -import * as Yup from "yup"; -import { Formik, FieldArray, Form, Field } from "formik"; -import { toast } from "react-toastify"; +import * as Yup from "yup" +import { Formik, FieldArray, Form, Field } from "formik" +import { toast } from "react-toastify" -import { makeStyles } from "@material-ui/core/styles"; -import { green } from "@material-ui/core/colors"; -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"; -import Typography from "@material-ui/core/Typography"; -import IconButton from "@material-ui/core/IconButton"; -import DeleteOutlineIcon from "@material-ui/icons/DeleteOutline"; -import CircularProgress from "@material-ui/core/CircularProgress"; +import { makeStyles } from "@material-ui/core/styles" +import { green } from "@material-ui/core/colors" +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" +import Typography from "@material-ui/core/Typography" +import IconButton from "@material-ui/core/IconButton" +import DeleteOutlineIcon from "@material-ui/icons/DeleteOutline" +import CircularProgress from "@material-ui/core/CircularProgress" -import { i18n } from "../../translate/i18n"; +import { i18n } from "../../translate/i18n" -import api from "../../services/api"; -import toastError from "../../errors/toastError"; +import api from "../../services/api" +import toastError from "../../errors/toastError" const useStyles = makeStyles(theme => ({ root: { @@ -50,7 +50,7 @@ const useStyles = makeStyles(theme => ({ marginTop: -12, marginLeft: -12, }, -})); +})) const ContactSchema = Yup.object().shape({ name: Yup.string() @@ -60,75 +60,77 @@ const ContactSchema = Yup.object().shape({ number: Yup.string().min(8, "Too Short!").max(50, "Too Long!"), email: Yup.string().min(2, "Too Short!") - .max(50, "Too Long!"), + .max(50, "Too Long!"), // email: Yup.string().email("Invalid email"), -}); +}) const ContactModal = ({ open, onClose, contactId, initialValues, onSave }) => { - const classes = useStyles(); - const isMounted = useRef(true); + const classes = useStyles() + const isMounted = useRef(true) const initialState = { name: "", number: "", email: "", useDialogflow: true, - }; + } - const [contact, setContact] = useState(initialState); + const [contact, setContact] = useState(initialState) + const [isSaving, setSaving] = useState(false) useEffect(() => { return () => { - isMounted.current = false; - }; - }, []); + isMounted.current = false + } + }, []) useEffect(() => { const fetchContact = async () => { if (initialValues) { setContact(prevState => { - return { ...prevState, ...initialValues }; - }); + return { ...prevState, ...initialValues } + }) } - if (!contactId) return; + if (!contactId) return try { - const { data } = await api.get(`/contacts/${contactId}`); + const { data } = await api.get(`/contacts/${contactId}`) if (isMounted.current) { - setContact(data); + setContact(data) } } catch (err) { - toastError(err); + toastError(err) } - }; + } - fetchContact(); - }, [contactId, open, initialValues]); + fetchContact() + }, [contactId, open, initialValues]) const handleClose = () => { - onClose(); - setContact(initialState); - }; + onClose() + setContact(initialState) + } const handleSaveContact = async values => { - try { + try { if (contactId) { - await api.put(`/contacts/${contactId}`, values); - handleClose(); + await api.put(`/contacts/${contactId}`, values) + handleClose() } else { - const { data } = await api.post("/contacts", values); + const { data } = await api.post("/contacts", values) if (onSave) { - onSave(data); + onSave(data) } - handleClose(); + handleClose() } - toast.success(i18n.t("contactModal.success")); + toast.success(i18n.t("contactModal.success")) + setSaving(false) } catch (err) { - toastError(err); + toastError(err) } - }; + } return (
@@ -143,10 +145,11 @@ const ContactModal = ({ open, onClose, contactId, initialValues, onSave }) => { enableReinitialize={true} validationSchema={ContactSchema} onSubmit={(values, actions) => { + setSaving(true) setTimeout(() => { - handleSaveContact(values); - actions.setSubmitting(false); - }, 400); + handleSaveContact(values) + actions.setSubmitting(false) + }, 400) }} > {({ values, errors, touched, isSubmitting }) => ( @@ -256,14 +259,14 @@ const ContactModal = ({ open, onClose, contactId, initialValues, onSave }) => {
- ); -}; + ) +} -export default ContactModal; +export default ContactModal diff --git a/frontend/src/components/WhatsAppModal/index.js b/frontend/src/components/WhatsAppModal/index.js index 0ee0533..8e8bbae 100644 --- a/frontend/src/components/WhatsAppModal/index.js +++ b/frontend/src/components/WhatsAppModal/index.js @@ -87,7 +87,7 @@ const WhatsAppModal = ({ open, onClose, whatsAppId, whatsAppOfficial }) => { if (!whatsAppId) return try { - const { data } = await api.get(`whatsapp/${whatsAppId}`) + const { data } = await api.get(`whatsapp/${whatsAppId}`) setWhatsApp(data) setIsOfficial(data?.isOfficial)