const request = require("request")
const fetch = require("node-fetch");
var EMAIL_REGEX_PATTERN =
/^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
const socketURL = "https://ebl-api-h7duexlbuq-el.a.run.app/func/gzLWpRYwbW5l";
exports = {
onContactCreateCallback: function (payload) {
createContactEvent(payload);
},
onContactUpdateCallback: function (payload) {
let changes = payload.data.changes.model_changes;
if (payload.data.contact.is_deleted) {
updateContactEvents(payload, "delete_contact");
} else if (changes.contact_status_id != undefined) {
updateContactEvents(payload, "change_stage");
} else if (changes.tags !== undefined) {
updateContactEvents(payload, "change_tag");
} else {
updateContactEvents(payload, "change_lead");
}
},
onDealCreateCallback: function (payload) {
dealEvent(payload, "new_deal");
},
onDealUpdateCallback: function (payload) {
let changes = payload.data.changes.model_changes;
if (payload.data.deal.is_deleted) {
dealEvent(payload, "delete_deal");
} else if (changes.deal_stage_id !== undefined) {
dealEvent(payload, "deal_stage");
} else if (changes.tags !== undefined) {
dealEvent(payload, "change_deal_tag");
} else {
dealEvent(payload, "update_deal");
}
},
onAppointmentCreateCallback: function (payload) {
taskAndAppointementEvent(payload, "appointment");
},
onTaskCreateCallback: function (payload) {
taskAndAppointementEvent(payload, "task");
},
onAppInstallCallback: function (payload) {
const companyInfo = {
account_info: payload?.iparams?.account_info,
event: payload?.event,
account_id: payload?.account_id,
domain: payload?.domain,
fs_api_key: payload?.iparams?.fs_api_key,
msg_auth: payload?.iparams?.msg_auth,
region: payload?.region,
};
appInstalled(companyInfo);
},
onAppUninstallCallback: function (payload) {
const companyInfo = {
account_info: payload?.iparams?.account_info,
event: payload?.event,
account_id: payload?.account_id,
domain: payload?.domain,
fs_api_key: payload?.iparams?.fs_api_key,
msg_auth: payload?.iparams?.msg_auth,
region: payload?.region,
};
appUninstalled(companyInfo);
},
};
async function postApiData(url, data) {
try {
const response = await fetch(url, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(data),
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const json = await response.json();
return json;
} catch (error) {
console.error("Error:", error);
}
}
function appInstalled(payload) {
const api = postApiData(socketURL, payload);
api.then(
(res) => {
if (res.success) {
renderData();
}
},
(err) => {
renderData(err);
}
);
}
function appUninstalled(payload) {
const api = postApiData(socketURL, payload);
api.then(
(res) => {
if (res.success) {
renderData();
}
},
(err) => {
renderData(err);
}
);
}
function taskAndAppointementEvent(payload, eventType) {
// dumpPayload(payload);
if (eventType === "task") {
payload.iparams.allEvents.forEach((event) => {
for (const [key, value] of Object.entries(event)) {
if (key === "sales") {
handleSalesActivities(payload, value, eventType);
}
}
});
} else if (eventType === "appointment") {
payload.iparams.allEvents.forEach((event) => {
for (const [key, value] of Object.entries(event)) {
if (key === "sales") {
handleSalesActivities(payload, value, eventType);
}
}
});
}
}
function dealEvent(payload, eventType) {
if (eventType === "new_deal") {
payload.iparams.allEvents.forEach((event) => {
for (const [key, value] of Object.entries(event)) {
if (key !== eventType) return;
handleDealEvent(payload, value, "new_deal", "deal");
}
});
} else if (eventType === "delete_deal") {
payload.iparams.allEvents.forEach((event) => {
for (const [key, value] of Object.entries(event)) {
if (key !== eventType) return;
handleDealEvent(payload, value, eventType, "deal");
}
});
} else if (eventType === "update_deal") {
const changesKey = Object.keys(payload.data.changes.model_changes);
payload.iparams.allEvents.forEach((event) => {
for (const [key, value] of Object.entries(event)) {
if (key !== eventType) return;
let triggerUpdateForFields = value.selected_fields;
for (let i = 0; i <= triggerUpdateForFields.length; i++) {
if (changesKey.includes(triggerUpdateForFields[i])) {
handleDealEvent(payload, value, eventType, "deal");
break;
}
}
}
});
} else if (eventType === "deal_stage") {
const changesObject = payload.data.changes.model_changes;
payload.iparams.allEvents.forEach((event) => {
for (const [key, value] of Object.entries(event)) {
if (key !== eventType) return;
let triggerUpdateForFields = value.selected_ids;
for (let i = 0; i <= triggerUpdateForFields.length; i++) {
if (
changesObject?.["deal_stage_id"]?.includes(
+triggerUpdateForFields[i]
)
) {
handleDealEvent(payload, value, eventType, "deal");
break;
}
}
}
});
} else if (eventType === "change_deal_tag") {
const changesObject = payload.data.changes.model_changes;
payload.iparams.allEvents.forEach((event) => {
for (const [key, value] of Object.entries(event)) {
if (key !== eventType) return;
// const addedTags = changesObject?.tags?.added
// ? changesObject?.tags?.["added"]?.map((tag) => tag.name.toLowerCase())
// : [];
const addedTags = changesObject?.tags?.["added"]?.map((tag) =>
tag.name.toLowerCase()
);
let allTags = [...addedTags];
let triggerUpdateForFields = value.selected_fields.map((field) =>
field.toLowerCase()
);
for (let i = 0; i <= triggerUpdateForFields.length; i++) {
if (allTags.includes(triggerUpdateForFields[i])) {
handleDealEvent(payload, value, eventType, "deal");
break;
}
}
}
});
}
}
function createContactEvent(payload) {
payload.iparams.allEvents.forEach((event) => {
for (const [key, value] of Object.entries(event)) {
if (key === "signup")
handleContact(payload, value, "signup", "contact", null);
}
});
}
function updateContactEvents(payload, updateType) {
console.log('payload', updateType)
const changeModel = Object.keys(payload.data.changes.model_changes);
const changesObject = payload.data.changes.model_changes;
if (updateType === "change_lead") {
payload.iparams.allEvents.forEach((event) => {
for (const [key, value] of Object.entries(event)) {
if (key !== "change_lead") return;
let triggerUpdateForFields = value.selected_fields;
for (let i = 0; i <= triggerUpdateForFields.length; i++) {
if (changeModel.includes(triggerUpdateForFields[i])) {
handleContact(payload, value, updateType, "contact", "update");
break;
}
}
}
});
} else if (updateType === "change_tag") {
payload.iparams.allEvents.forEach((event) => {
for (const [key, value] of Object.entries(event)) {
if (key !== updateType) return;
// const addedTags = changesObject?.tags?.added
// ? changesObject?.tags?.["added"]?.map((tag) => tag.name.toLowerCase())
// : [];
const addedTags = changesObject?.tags?.["added"]?.map((tag) =>
tag.name.toLowerCase()
);
let allTags = [...addedTags];
let triggerUpdateForFields = value.selected_fields.map((field) =>
field.toLowerCase()
);
for (let i = 0; i <= triggerUpdateForFields.length; i++) {
if (allTags.includes(triggerUpdateForFields[i])) {
handleContact(payload, value, updateType, "contact", "update");
break;
}
}
}
});
} else if (updateType === "change_stage") {
payload.iparams.allEvents.forEach((event) => {
for (const [key, value] of Object.entries(event)) {
if (key !== updateType) return;
let triggerUpdateForFields = value.selected_ids;
for (let i = 0; i <= triggerUpdateForFields.length; i++) {
if (
changesObject?.["contact_status_id"]?.includes(
+triggerUpdateForFields[i]
)
) {
handleContact(payload, value, updateType, "contact", "update");
break;
}
}
}
});
} else if (updateType === "delete_contact") {
payload.iparams.allEvents.forEach((event) => {
for (const [key, value] of Object.entries(event)) {
if (key !== updateType) return;
handleContact(payload, value, updateType, "contact", "delete");
}
});
}
}
/**
* Function to handle create/update contact
*
* @param {*} payload
* @param {*} triggeredEvents // change_lead
* @param {*} platform // contact
* @param {*} type // delete | update
*/
function handleContact(payload, eventPayload, triggeredEvent, platform, type) {
let event = eventPayload.enabler;
if (event && eventPayload["variables"]) {
let filteredData = [];
if (type === "change_lead" || type === "delete_contact") {
filteredData = eventPayload["variables"].filter(
(data) => data.type == type
);
} else {
filteredData = eventPayload["variables"];
}
let msg91AuthKey = payload.iparams.msg_auth;
let campaign = eventPayload.campaign;
let sendTo = eventPayload.sendToFields;
let variables = [];
if (filteredData && filteredData?.length > 0) {
filteredData.map((data) => {
let fwField = data?.fw_field;
let fieldValue = "";
if (fwField && fwField.slice(0, 3) == "cf_") {
let matched = payload.data[platform].custom_fields.filter(
(data) => data.name == fwField
);
fieldValue = matched.length > 0 ? matched[0].value : "";
} else if (payload.data[platform] && payload.data[platform][fwField]) {
if (data.field_type === "dropdown") {
let value = payload.data[platform][fwField]?.value;
let choice = data?.choices?.find((choice) => choice.id == value);
fieldValue = choice?.value;
} else if (data.field_type === "multi_select_dropdown") {
const values = payload.data[platform][fwField].value.map(
(val) => val.value
);
fieldValue = values.join(",");
} else if (
fwField === "emails" &&
data.field_type === "group_field"
) {
let values;
if (payload.data[platform][fwField].value) {
values = payload.data[platform][fwField].value.filter(
(val) => val.is_primary === true
);
} else {
values = payload.data[platform][fwField].filter(
(val) => val.is_primary === true
);
}
fieldValue = values?.[0]?.email;
} else {
fieldValue = payload.data[platform][fwField]?.value;
}
}
variables[data?.campaign_field] = getFieldValue(fieldValue);
});
}
if (
payload.data[platform] &&
Object.keys(payload.data[platform]).length > 0
) {
Object.keys(payload.data[platform]).forEach((key) => {
if (isEmailMobileField(key)) {
sendTo = getSendToData(sendTo, key, payload.data[platform][key]);
}
});
if (
payload.data[platform].custom_fields &&
Object.keys(payload.data[platform].custom_fields).length > 0
) {
Object.keys(payload.data[platform].custom_fields).forEach((key) => {
if (
isEmailMobileField(payload.data[platform].custom_fields[key].name)
) {
sendTo = getSendToData(
sendTo,
payload.data[platform].custom_fields[key].name,
payload.data[platform].custom_fields[key]
);
}
});
}
}
sendCampaign(msg91AuthKey, campaign, sendTo, variables);
} else {
// event is inactive/not available
}
}
function getFieldValue(fieldValue) {
// let fieldValues = [];
// if (fieldValue && typeof fieldValue === "object" && fieldValue.length > 0) {
// fieldValue.forEach((field) => {
// fieldValues.push(field.value);
// });
// return fieldValues.join(", ");
// } else {
// return fieldValue;
// }
return fieldValue;
}
function getSendToData(sendTo, fwField, fieldValue) {
if (!fieldValue) return;
let sendToData = [];
if (sendTo && sendTo.to) {
let loop = 0;
sendTo.to.forEach((to) => {
if (to == fwField) {
// if (
// fieldValue.value &&
// typeof fieldValue.value === "object" &&
// !Array.isArray(fieldValue.value) &&
// fieldValue.value.length > 0
// ) {
// fieldValue.value.forEach((field) => {
// sendToData[loop] = field.value;
// loop++;
// });
// }
if (Array.isArray(fieldValue)) {
fieldValue.forEach((field) => {
sendToData[loop] = `mapped_${field?.value}`;
loop++;
});
} else if (
fieldValue.value &&
Array.isArray(fieldValue.value) &&
fieldValue.value.length > 0
) {
fieldValue.value.forEach((field) => {
sendToData[loop] = `mapped_${field?.email || field?.value}`;
loop++;
});
}
///////// else if (typeof fieldValue === "string" && !isValidEmail(fieldValue))
else if (typeof fieldValue === "string") {
sendToData[loop] = `mapped_${fieldValue}`;
loop++;
} else {
sendToData[loop] = `mapped_${fieldValue?.value}`;
loop++;
}
} else {
sendToData[loop] = to;
loop++;
}
});
}
sendTo.to = sendToData;
return sendTo;
}
function isEmailMobileField(fieldName) {
if (fieldName.indexOf("email") > -1 || fieldName.indexOf("mobile") > -1) {
return true;
} else {
return false;
}
}
/**
* Checks if email is valid
*
* @param {*} email
* @returns
*/
function isValidEmail(email) {
if (EMAIL_REGEX_PATTERN.test(email)) {
return true;
} else {
return false;
}
}
function isNumeric(str) {
if (typeof str != "string") return false;
return !isNaN(str) && !isNaN(parseFloat(str));
}
/**
* Handles sales activities
* @param {*} payload
* @param {*} subEvent // appointment | task
*/
function handleSalesActivities(payload, eventPayload, subEvent) {
let event = eventPayload.enabler;
if (
event &&
payload.data[subEvent].targetable_id !== null &&
payload.data[subEvent].targetable_type !== null
) {
let type = payload.data[subEvent].targetable_type.toLowerCase();
let filteredData = [];
filteredData = eventPayload.variables.filter(
(data) => data.type == subEvent && data.fw_field_group == type
);
getSalesActivity(payload, subEvent)
.then((salesData) => {
salesEventTriggered(
payload,
eventPayload,
salesData[type],
filteredData
);
})
.catch((err) => {
renderData(err);
});
} else {
// event is inactive/not available
}
}
function handleDealEvent(payload, eventPayload, triggeredEvent, platform) {
let event = eventPayload.enabler;
if (event && eventPayload.enabler) {
let filteredData = eventPayload.variables;
let targetableId = payload?.data?.[platform]?.contact_ids[0];
getDealsActivity(payload, targetableId)
.then((dealsData) => {
dealsEventTriggered(
payload,
eventPayload,
dealsData["contact"],
filteredData,
triggeredEvent,
platform
);
})
.catch((err) => {
renderData(err);
});
} else {
// event is inactive/not available
}
}
// Get deals
function getDealsActivity(payload, targetable_id) {
return new Promise(function (resolve, reject) {
let id = String(targetable_id);
let url = `${payload.iparams.fs_domain}/api/contacts/${id}`;
if (url) {
$request.invokeTemplate("getDealsActivity" , {
context: {
fs_domain: payload.iparams.fs_domain,
fs_api_key: payload.iparams.fs_api_key,
id: String(targetable_id)
}
}).then((value) => {
// if (response?.statusCode === 200) {
// resolve(JSON.parse(body));
// } else {
// reject(err, "Error on fetching Contact");
// }
console.log('getDealsActivity', value)
}).catch((error) => {
renderData(error);
})
} else {
reject("Selected record not selected from contacts");
}
});
}
function dealsEventTriggered(
payload,
eventPayload,
dealsData,
filteredData,
triggeredEvent,
platform
) {
let msg91AuthKey = payload.iparams.msg_auth;
let campaign = eventPayload.campaign;
let sendTo = eventPayload.sendToFields;
let variables = [];
if (filteredData && filteredData.length > 0) {
filteredData.map(async (data) => {
let fwField = data.fw_field;
let fieldValue = "";
if (fwField && fwField.slice(0, 3) == "cf_") {
let matched = payload.data[platform].custom_fields.filter(
(data) => data.name == fwField
);
fieldValue = matched.length > 0 ? matched[0].value : "";
} else if (
payload.data &&
payload.data[platform] &&
payload.data[platform][fwField]
) {
if (data.field_type === "dropdown") {
let value = payload.data[platform][fwField]?.value;
let choice = data.choices.find((choice) => choice.id == value);
fieldValue = choice?.value;
} else if (data.field_type === "multi_select_dropdown") {
const values = payload.data[platform][fwField].value.map(
(val) => val?.value
);
fieldValue = values.join(",");
} else {
fieldValue = payload.data[platform][fwField].value;
}
}
variables[data.campaign_field] = getFieldValue(fieldValue);
});
}
if (dealsData && Object.keys(dealsData).length > 0) {
Object.keys(dealsData).forEach((key) => {
if (isEmailMobileField(key)) {
if (!dealsData[key]) return;
sendTo = getSendToData(sendTo, key, dealsData[key]);
}
});
}
sendCampaign(msg91AuthKey, campaign, sendTo, variables);
}
function getSalesActivity(payload, activity) {
return new Promise(function (resolve, reject) {
let subEvent = payload.data[activity].targetable_type.toLowerCase();
let id = payload.data[activity].targetable_id;
if (subEvent != null && id != null) {
let url = "";
if (subEvent == "contact") {
url = `${payload.iparams.fs_domain}/api/contacts/${id}`;
}
if (url) {
$request.invokeTemplate("getSalesActivity" , {
context: {
fs_domain: payload.iparams.fs_domain,
fs_api_key: payload.iparams.fs_api_key,
id: String(targetable_id)
}
}).then((value) => {
// if (response?.statusCode === 200) {
// resolve(JSON.parse(body));
// } else {
// reject(err, "Error on fetching Contact");
// }
console.log('getSalesActivity', value)
}).catch((error) => {
reject("Error on fetch", error)
// reject("Error on fetch " + subEvent);
})
} else {
reject("Selected record not selected from " + activity);
}
} else {
reject("Record not selected from " + activity);
}
});
}
/**
* Triggers sales event
* @param {*} payload
* @param {*} salesData
* @param {*} filteredData
*/
function salesEventTriggered(payload, eventpayload, salesData, filteredData) {
let msg91AuthKey = payload.iparams.msg_auth;
let campaign = eventpayload.campaign;
let sendTo = eventpayload.sendToFields;
let variables = [];
if (filteredData && filteredData.length > 0) {
filteredData.map((data) => {
let fwField = data.fw_field;
let fieldValue = "";
if (fwField.slice(0, 3) == "cf_") {
fieldValue = salesData.custom_field[fwField];
} else {
if (data.field_type === "dropdown") {
let value = salesData?.[fwField];
let choice = data.choices.find((choice) => choice.id == value);
fieldValue = choice?.value || null;
} else {
fieldValue = salesData[fwField];
}
}
variables[data.campaign_field] = getFieldValue(fieldValue);
});
}
if (salesData && Object.keys(salesData).length > 0) {
Object.keys(salesData).forEach((key) => {
if (isEmailMobileField(key)) {
if (!salesData[key]) return;
sendTo = getSendToData(sendTo, key, salesData[key]);
}
});
// if (
// salesData.custom_fields &&
// Object.keys(salesData.custom_fields).length > 0
// ) {
// Object.keys(salesData.custom_fields).forEach((key) => {
// if (isEmailMobileField(salesData.custom_fields[key])) {
// sendTo = getSendToData(sendTo, key, salesData.custom_fields[key]);
// }
// });
// }
}
sendCampaign(msg91AuthKey, campaign, sendTo, variables);
}
/**
* Returns list of email/mobiles
*
* @param {*} data
* @returns
*/
function getEmailMobiles(data, isToField = false) {
let emailMobiles = [];
if (isToField) {
let toObject = {};
if (data && data.length > 0 && Array.isArray(data)) {
data.forEach((item) => {
if (item.split("_")?.length === 2) {
if (isValidEmail(item.split("_")[1])) {
toObject["email"] = item?.split("_")[1];
} else if (
!isValidEmail(item.split("_")[1]) &&
typeof item !== "object" &&
isNumeric(item.split("_")[1])
) {
toObject["mobiles"] = item?.split("_")[1];
}
} else {
if (isValidEmail(item)) {
emailMobiles.push({ email: item });
} else if (typeof item === "object" && isValidEmail(item?.email)) {
emailMobiles.push({ email: item?.email });
} else if (
!isValidEmail(item) &&
typeof item !== "object" &&
isNumeric(item)
) {
emailMobiles.push({ mobiles: item });
}
}
});
}
emailMobiles.push(toObject);
} else {
if (data && data.length > 0 && Array.isArray(data)) {
data.forEach((item) => {
if (isValidEmail(item)) {
emailMobiles.push({ email: item });
} else if (typeof item === "object" && isValidEmail(item?.email)) {
emailMobiles.push({ email: item?.email });
} else if (
!isValidEmail(item) &&
typeof item !== "object" &&
isNumeric(item)
) {
emailMobiles.push({ mobiles: item });
}
});
}
}
emailMobiles = emailMobiles.filter((item) => item.email || item.mobiles);
return emailMobiles;
}
/**
* Sends campaign
*
* @param {*} auth
* @param {*} campaign
* @param {*} sendTo
* @param {*} variables
*/
function sendCampaign(auth, campaign, sendTo, variables) {
if (!sendTo.to || !sendTo.to.length || !sendTo.to.flat().length) return;
let to = [];
let cc = [];
let bcc = [];
let fieldVariables = {};
Object.keys(variables).forEach((key) => {
if (typeof variables[key] === "object") {
// if (variables[key]?.length > 0) {
// variables[key] = variables[key][0].value;
// } else {
variables[key] = variables[key]?.value;
// }
}
fieldVariables[key] = variables[key];
});
if (sendTo) {
to = getEmailMobiles(sendTo.to, true);
cc = getEmailMobiles(sendTo.cc);
bcc = getEmailMobiles(sendTo.bcc);
$request.invokeTemplate("sendCampaign" , {
context: {
campaign: campaign,
auth: auth
},
body: JSON.stringify(
{
data: {
sendTo: [
{
to: to,
cc: cc,
bcc: bcc,
variables: fieldVariables,
},
],
},
}
)
}).then((value) => {
console.log('sendCampaign', value)
}).catch((error) => {
console.log('error 899', error)
})
}
}
in this code on every where i use $request.invokeTemplate i got error in command line also and on event api call in network tab.
let me know any changes from my side @Raviraj .