Skip to content

Commit

Permalink
Contacts (vcard) done the right way. Fix #38 #88
Browse files Browse the repository at this point in the history
  • Loading branch information
allgood committed Jul 22, 2024
1 parent 9289de5 commit e492d17
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 61 deletions.
24 changes: 19 additions & 5 deletions backend/src/services/WbotServices/wbotMessageListener.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,21 +147,35 @@ export const getBodyMessage = (msg: proto.IWebMessageInfo): string | null => {
viewOnceMessage: getBodyButton(msg) || msg.message?.listResponseMessage?.singleSelectReply?.selectedRowId,
viewOnceMessageV2: msg.message?.viewOnceMessageV2?.message?.imageMessage?.caption || "",
stickerMessage: "sticker",
contactMessage: msg.message?.contactMessage?.vcard,
contactsArrayMessage: "varios contatos",
contactMessage:
msg.message?.contactMessage?.vcard &&
JSON.stringify(
{
ticketzvCard: [
{
displayName: msg.message.contactMessage.displayName,
vcard: msg.message.contactMessage.vcard
}
]
}),
contactsArrayMessage: msg.message?.contactsArrayMessage &&
JSON.stringify(
{
ticketzvCard: msg.message.contactsArrayMessage.contacts
}),
// locationMessage: `Latitude: ${msg.message.locationMessage?.degreesLatitude} - Longitude: ${msg.message.locationMessage?.degreesLongitude}`,
locationMessage: msgLocation(
msg.message?.locationMessage?.jpegThumbnail,
msg.message?.locationMessage?.degreesLatitude,
msg.message?.locationMessage?.degreesLongitude
),
liveLocationMessage: `Latitude: ${msg.message.liveLocationMessage?.degreesLatitude} - Longitude: ${msg.message.liveLocationMessage?.degreesLongitude}`,
liveLocationMessage: `Latitude: ${msg.message?.liveLocationMessage?.degreesLatitude} - Longitude: ${msg.message?.liveLocationMessage?.degreesLongitude}`,
documentMessage: msg.message?.documentMessage?.title,
documentWithCaptionMessage: msg.message?.documentWithCaptionMessage?.message?.documentMessage?.caption,
audioMessage: "Áudio",
listMessage: getBodyButton(msg) || msg.message.listResponseMessage?.title,
listResponseMessage: msg.message?.listResponseMessage?.singleSelectReply?.selectedRowId,
reactionMessage: msg.message.reactionMessage?.text || "reaction",
reactionMessage: msg.message?.reactionMessage?.text || "reaction",
};

const objKey = Object.keys(types).find(key => key === type);
Expand All @@ -177,7 +191,7 @@ export const getBodyMessage = (msg: proto.IWebMessageInfo): string | null => {
} catch (error) {
Sentry.setExtra("Error getTypeMessage", { msg, BodyMsg: msg.message });
Sentry.captureException(error);
console.log(error);
logger.error({error, msg}, `getBodyMessage: error: ${error?.message}`);
return null;
}
};
Expand Down
1 change: 1 addition & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
"use-sound": "^2.0.1",
"uuid": "^9.0.1",
"validations-br": "^1.4.0",
"vcard-parser": "^1.0.0",
"yup": "^1.4.0"
},
"scripts": {
Expand Down
156 changes: 101 additions & 55 deletions frontend/src/components/MessagesList/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@ import api from "../../services/api";
import toastError from "../../errors/toastError";
import { SocketContext } from "../../context/Socket/SocketContext";
import { i18n } from "../../translate/i18n";

import vCard from "vcard-parser";
import { generateColor } from "../../helpers/colorGenerator";
import { getInitials } from "../../helpers/getInitials";

const useStyles = makeStyles((theme) => ({
messagesListWrapper: {
Expand Down Expand Up @@ -796,66 +798,110 @@ const MessagesList = ({ ticket, ticketId, isGroup }) => {
);
};

const formatVCardN = (n) => {
return(
(n[3] ? n[3] + " " : "") +
(n[1] ? n[1] + " " : "") +
(n[2] ? n[2] + " " : "") +
(n[0] ? n[0] + " " : "") +
(n[4] ? n[4] + " " : "")
);
}

const isVCard = (message) => {
return message.includes('BEGIN:VCARD');
return message.startsWith('{"ticketzvCard":');
};

const vCard = (message) => {
const name = message?.substring(message.indexOf("\nN:;") + 4, message.indexOf(";;;"));
const telLine = message?.substring(message.indexOf("\nTEL;") + 5);
const description = telLine.substring(telLine.indexOf(":") + 1, telLine.indexOf("\n"));
return (
<div>
<div style={{ display: 'flex', flexDirection: 'row', alignItems: 'center', marginTop: 20, marginBottom: 20 }}>
<Avatar style={{ marginRight: 10, marginLeft: 20, width: 60, height: 60 }} />
<div style={{ width: 350 }}>
<div>
<Typography
noWrap
component="h4"
variant="body2"
color="textPrimary"
style={{ fontWeight: '700' }}
>
{name}
</Typography>
</div>
const renderVCard = (vcardJson) => {
const cardArray = JSON.parse(vcardJson)?.ticketzvCard;

if (!cardArray || !Array.isArray(cardArray)) {
return <div>Invalid VCARD data</div>;
}

return cardArray.map((item) => {
const message = item?.vcard;
if (!message) {
return <></>;
}
const parsedVCard = vCard.parse(message);
console.debug("vCard data:", { message , parsedVCard });

const name =
parsedVCard['X-WA-BIZ-NAME']?.[0]?.value ||
parsedVCard.fn?.[0]?.value ||
formatVCardN(parsedVCard.n?.[0]?.value);
const description =
parsedVCard['X-WA-BIZ-DESCRIPTION']?.[0]?.value || ""
const number = parsedVCard?.tel?.[0]?.value;
const metaNumber = parsedVCard?.tel?.[0]?.meta?.waid?.[0] || number || "unknown";

return (
<div>
<div style={{ display: 'flex', flexDirection: 'row', alignItems: 'center', marginTop: 20, marginBottom: 20 }}>
<Avatar style={{ backgroundColor: generateColor(metaNumber), marginRight: 10, marginLeft: 20, width: 60, height: 60, color: "white", fontWeight: "bold" }}>{ getInitials(name)}</Avatar>
<div style={{ width: 350 }}>
<Typography
component="span"
variant="body2"
color="textPrimary"
style={{ display: 'flex' }}
>
{description}
</Typography>
<div>
<Typography
noWrap
component="h4"
variant="body2"
color="textPrimary"
style={{ fontWeight: '700' }}
>
{name}
</Typography>
</div>

<div style={{ width: 350 }}>
<Typography
component="span"
variant="body2"
color="textPrimary"
style={{ display: 'flex' }}
>
{description}
</Typography>
</div>

<div style={{ width: 350 }}>
<Typography
component="span"
variant="body2"
color="textPrimary"
style={{ display: 'flex' }}
>
{number}
</Typography>
</div>

</div>
</div>

</div>
<div style={{
width: '100%', display: 'none',
justifyContent: 'center',
alignItems: 'center',
marginTop: 20,
borderWidth: '1px 0 0 0',
borderTopColor: '#bdbdbd',
borderStyle: 'solid',
padding: 8
}}>
<Typography
noWrap
component="h4"
variant="body2"
color="textPrimary"
style={{ fontWeight: '700', color: '#2c9ce7' }}
>
Conversar
</Typography>
</div>
</div>
<div style={{
width: '100%', display: 'none',
justifyContent: 'center',
alignItems: 'center',
marginTop: 20,
borderWidth: '1px 0 0 0',
borderTopColor: '#bdbdbd',
borderStyle: 'solid',
padding: 8
}}>
<Typography
noWrap
component="h4"
variant="body2"
color="textPrimary"
style={{ fontWeight: '700', color: '#2c9ce7' }}
>
Conversar
</Typography>
</div>
</div>
)
)

});
};

const messageLocation = (message, createdAt) => {
Expand Down Expand Up @@ -914,7 +960,7 @@ const MessagesList = ({ ticket, ticketId, isGroup }) => {
className={[clsx(classes.textContentItem, {
[classes.textContentItemEdited]: message.isEdited
}), { marginRight: 0 }]}>
{vCard(message.body)}
{renderVCard(message.body)}
</div>

:
Expand Down Expand Up @@ -985,7 +1031,7 @@ const MessagesList = ({ ticket, ticketId, isGroup }) => {
:
isVCard(message.body) ?
<div className={[classes.textContentItem]}>
{vCard(message.body)}
{renderVCard(message.body)}
</div>

:
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/TicketListItemCustom/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -530,7 +530,7 @@ const TicketListItemCustom = ({ ticket, setTabOpen }) => {
</span>
) : (
<>
{ticket.lastMessage.includes('data:image/png;base64') ? <MarkdownWrapper> Localização</MarkdownWrapper> : <MarkdownWrapper>{ticket.lastMessage}</MarkdownWrapper>}
{ticket.lastMessage?.includes('data:image/png;base64') ? <MarkdownWrapper> Localização</MarkdownWrapper> : <MarkdownWrapper>{ticket.lastMessage.startsWith('{"ticketzvCard"') ? "🪪" : ticket.lastMessage}</MarkdownWrapper>}
</>
)}
</Typography>
Expand Down

0 comments on commit e492d17

Please sign in to comment.