Merge branch 'main' of github.com:hainatravel/global-sales

dev/supplier-email-drawer
LiaoYijun 6 months ago
commit b2aa2440b3

@ -469,10 +469,10 @@ const messageSlice = (set, get) => ({
? {
...conversationsList[targetIndex],
last_received_time: lastReceivedTime || conversationsList[targetIndex].last_received_time,
unread_msg_count:
Number(targetId) !== Number(currentConversation.sn) && message.sender !== 'me'
? conversationsList[targetIndex].unread_msg_count + 1
: conversationsList[targetIndex].unread_msg_count,
// unread_msg_count:
// Number(targetId) !== Number(currentConversation.sn) && message.sender !== 'me'
// ? conversationsList[targetIndex].unread_msg_count + 1
// : conversationsList[targetIndex].unread_msg_count,
last_message: message,
}
: {
@ -481,7 +481,7 @@ const messageSlice = (set, get) => ({
sn: Number(targetId),
opi_sn: message.opi_sn || currentConversation.opi_sn, // todo: coli sn
last_received_time: dayjs(message.date).add(8, 'hours').format(DATETIME_FORMAT),
unread_msg_count: message.sender === 'me' ? 0 : 1,
unread_msg_count: 0, // message.sender === 'me' ? 0 : 1,
whatsapp_name: message?.senderName || message?.sender || '',
customer_name: message?.senderName || message?.sender || '',
whatsapp_phone_number: message.type === 'email' ? null : message.from,

@ -1,61 +1,14 @@
'use strict';
const generateId = require('../../utils/generateId.util');
const { sessionStore } = require('../../core');
const { objectMapper, pick } = require('../../utils/commons.util');
const { createOutboundMessage, getOutboundMessage } = require('../../services/outbound_messages.service');
const { createOutboundMessage } = require('../../services/outbound_messages.service');
const waEmitter = require('../../core/emitter');
const logger = require('../../utils/logger.util');
const { ctxToSendBuilder, ctxToDB, DbData } = require('../../helper/wai.msg.helper');
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
/**
* @deprecated 即将废弃
*/
const sendText = async ctx => {
const { from, to, msgcontent, content: _content, actionId } = ctx.request.body;
const content = _content || msgcontent.body || '';
if (!from || !content) {
ctx.assert(from, 400, 'From and message are required');
return;
}
const wsToSend = sessionStore.getSession(from);
// console.log('find wsToSend', wsToSend)
if (!wsToSend) {
ctx.assert(wsToSend, 400, 'Session not found'); // 404
return;
}
try {
// wsToSend.sendTextMessage(to, content, actionId).then(({ messageId }) => {
// const messageId = generateId();
const _data = ctx.request.body;
const defaultR = { direction: 'outbound' };
const r1 = pick(_data, ['actionId', 'msgtype', 'externalId']);
r1.id = actionId; // id not null
// r1.wamid = messageId;
r1.msg_status = 'ready';
r1.createTime = Date.now();
const record = objectMapper(_data, { from: 'from', to: 'to' }, false);
const byType = _data.msgtype === 'text' ? { text_body: _data.msgcontent.body, text_preview_url: _data.msgcontent.preview_url } : {};
const toUpsert = { ...defaultR, ...r1, ...record, ...byType, message_origin: JSON.stringify(_data) };
await createOutboundMessage({ ...toUpsert });
// return 'Message sent successfully'; // { wsToSend, ret: 'Message sent successfully' };
// });
// wsToSend.sendTextMessage(to, content, actionId);
waEmitter.emit('request.' + from + '.send.text', { to, content, externalId: actionId });
return 'Message sent successfully'; // { wsToSend, ret: 'Message sent successfully' };
} catch (error) {
console.error('Error sending message:', error);
ctx.assert(null, 500, 'Failed to send message');
}
};
const { ctxToSendBuilder, ctxToDB } = require('../../helper/wai.msg.helper');
const send = async ctx => {
const { msgtype, from, to, msgcontent, content: _content, actionId } = ctx.request.body;
const { msgtype, from, to, msgcontent, content: _content } = ctx.request.body;
const content = _content || msgcontent.body || '';
logger.info('send', msgtype, from, to, content);
if (!from) {
@ -84,5 +37,4 @@ const send = async ctx => {
module.exports = {
send,
sendText,
};

@ -7,9 +7,7 @@ module.exports = Router => {
prefix: `/messages`,
});
router
.post('/send', controller.send)
.post('/:type', controller.sendText);
router.post('/send', controller.send);
return router;
};

@ -10,7 +10,7 @@ const { updateConnection, addCurrentConnection, resetConnection, getConnection }
const { getOutboundMessage, upsertOutboundMessage } = require('../../services/outbound_messages.service');
const { objectMapper, pick } = require('../../utils/commons.util');
const { logger, getUserLogger } = require('../../utils/logger.util');
const { DbData } = require('../../helper/wai.msg.helper');
const { DbData, waiContentToDB, uploadMediaFile } = require('../../helper/wai.msg.helper');
const connectionEventNames = ['connection:connect', 'connection:open', 'connection:close'];
const messageEventNames = ['message:received', 'message:updated'];
@ -169,15 +169,18 @@ const setupMessageHandler = () => {
upsertFields.evt_id = webhookBody.id;
const pusher = { customerProfile_id: waiMessage.customerProfile?.id || '', customerProfile_name: waiMessage.customerProfile?.name || '' };
const record = objectMapper(waiMessage, { from: 'from', to: 'to', status: 'msg_status', type: 'msgtype' }, false);
const contentFields = waiMessage.type === 'text' ? { text_body: waiMessage.text.body } : {};
// const contentFieldsToDB =
// todo: 现在只能收text 消息, 后续再加其他类型
const waiContentFieldsToDB = waiContentToDB(messageData);
if (['image', 'sticker', 'audio', 'video', 'document'].includes(waiMessage.type)) {
// 存储文件
const filePath = messageData[messageData.type].filename;
const webLink = await uploadMediaFile(filePath);
waiContentFieldsToDB.link = webLink;
}
const msgRow = await upsertOutboundMessage(
{ ...timeFields, ...upsertFields, ...pusher, ...contentFields, ...record, ...typeField, message_origin: savedMsg?.message_origin || JSON.stringify(messageData) },
{ ...timeFields, ...upsertFields, ...pusher, ...waiContentFieldsToDB, ...record, ...typeField, message_origin: savedMsg?.message_origin || JSON.stringify(messageData) },
targetUpsert,
);
// console.log('upsert=========================', upsert);
// 把内容加上, 否则前端没显示
await callWebhook(webhookBodyFill(webhookBody, msgRow));
} catch (error) {

@ -22,7 +22,16 @@ const mediaMsg = {
// seconds?: number; // audio
// isAnimated?: boolean; // sticker
// jpegThumbnail?: string; // image, video
imageUrl: msgcontent[msgtype].link, // 25.01.01 版本, 后续更改payload格式 todo:
};
},
waiContentToDB: msg => {
const { type } = msg;
return {
IVADS_link_original: msg[type].link_original,
IVADS_caption: msg[type].caption || '',
IVADS_filename: msg[type].filename || '',
IVADS_mime_type: msg[type].mimetype || '',
IVADS_sha256: msg[type].sha256 || '',
};
},
dataToDB: msg => {
@ -65,10 +74,12 @@ const waiMsgTypeMapped = {
to: msg.to,
externalId: msg.actionId,
text: msg.msgcontent.body,
content: msg.msgcontent.body, // 25.01.01 版本, 后续更改payload格式 todo:
// linkPreview: true, // {}
...(msg.msgcontent.context ? { quoted: { key: msg.msgcontent.context.message_id } } : {}),
}),
waiContentToDB: msg => {
return { text_body: msg.text.body };
},
dataToDB: msg => {
const { msgcontent } = msg;
const record = pick(msg, ['actionId', 'msgtype', 'externalId', 'from', 'to']);
@ -146,6 +157,13 @@ const waiMsgTypeMapped = {
key: msg.msgcontent.context.message_id,
},
}),
waiContentToDB: msg => {
return {
// todo:
reaction_message_id: '',
reaction_emoji: '',
};
},
dataToDB: msg => {
const { msgtype, msgcontent, ...body } = msg;
const record = pick(msg, ['actionId', 'msgtype', 'externalId', 'from', 'to']);
@ -173,6 +191,10 @@ const waiMsgTypeMapped = {
externalId: msg.actionId,
// location: { degreesLatitude: msg.latitude, degreesLongitude: msg.longitude }, // todo:
}),
waiContentToDB: msg => {
// todo:
return {};
},
dataToDB: msg => {
const { msgtype, msgcontent, ...body } = msg;
const record = pick(msg, ['actionId', 'msgtype', 'externalId', 'from', 'to']);
@ -204,6 +226,11 @@ const waiMsgTypeMapped = {
externalId: msg.actionId,
// contacts: { displayName: '', contacts: msg.contacts }, // todo:
}),
waiContentToDB: msg => {
return {
contacts: JSON.stringify(msg.contacts),
};
},
dataToDB: msg => {
const { msgtype, msgcontent, ...body } = msg;
const record = pick(msg, ['actionId', 'msgtype', 'externalId', 'from', 'to']);
@ -268,6 +295,15 @@ const ctxToDB = ctxContent => {
return msgReady;
};
/**
* wai Event Msg data to DB
*/
const waiContentToDB = waiMsg => {
const { waiContentToDB } = waiMsgTypeMapped[waiMsg.type];
const msgReady = waiContentToDB(waiMsg);
return msgReady;
};
/**
* Parse DB Data to UI/API/Webhook
*/
@ -277,8 +313,47 @@ const DbData = row => {
return msgReady;
};
const axios = require('axios');
const FormData = require('form-data');
const fs = require('fs');
const path = require('path');
const PROJECT_ROOT = process.cwd();
/**
* Upload Media File
* * https://p9axztuwd7x8a7.mycht.cn/whatsapp_server/WAFileUpload
* @param {*} filePath
*/
async function uploadMediaFile(filePath) {
const url = 'https://p9axztuwd7x8a7.mycht.cn/whatsapp_server/WAFileUpload';
try {
const pathObject = path.parse(filePath);
const filename = 'wai_' + pathObject.name.replace(/\s/g, '-') + `_${Date.now()}` + pathObject.ext;
const _filePath = path.join(PROJECT_ROOT, filePath);
const formData = new FormData();
formData.append('file', fs.createReadStream(_filePath), filename);
const response = await axios.post(url, formData, {
headers: formData.getHeaders(),
maxBodyLength: Infinity,
maxContentLength: Infinity,
});
const { result, errcode, errmsg } = response.data;
if (errcode !== 0) {
throw new Error(`Upload media file failed: ${errmsg}. ${filePath}`);
}
return errcode === 0 ? result.file_url : '';
} catch (error) {
console.error('Upload failed:', error);
// throw error;
return '';
}
}
module.exports = {
ctxToSendBuilder,
ctxToDB,
waiContentToDB,
DbData,
uploadMediaFile,
};

Loading…
Cancel
Save