@bedrijfsdatanl/n8n-nodes-prospectpro
Version:
n8n node for ProspectPro - Identify Dutch B2B ProspectPro in rapid time
364 lines • 17.1 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.ProspectproTrigger = void 0;
const n8n_workflow_1 = require("n8n-workflow");
const GenericFunctions_1 = require("./GenericFunctions");
class ProspectproTrigger {
constructor() {
this.description = {
displayName: 'ProspectPro Trigger',
name: 'prospectproTrigger',
icon: 'file:logo.svg',
group: ['trigger'],
version: 1,
subtitle: '={{($parameter["event"] === "contactUpsert" || $parameter["event"] === "contactInsert") ? "Contacts" : "Prospects"}} - {{($parameter["event"] === "contactInsert" || $parameter["event"] === "prospectInsert") ? "Added" : "Added or Updated"}} — {{$metadata["lastTimeCheckedSeconds"] ? "Last check: " + new Date($metadata["lastTimeCheckedSeconds"] * 1000).toLocaleString() : "Polling..."}}',
description: 'Triggers when new prospects or contacts are found or existing ones are updated in ProspectPro.',
defaults: {
name: 'ProspectPro Trigger',
},
polling: true,
inputs: [],
outputs: ["main"],
credentials: [
{
name: 'prospectproApi',
required: true,
},
],
properties: [
{
displayName: 'Trigger On',
name: 'event',
type: 'options',
description: 'What event should trigger the workflow',
options: [
{
name: 'Prospect Added or Updated',
value: 'prospectUpsert',
},
{
name: 'Prospect Added',
value: 'prospectInsert',
},
{
name: 'Contact Added or Updated',
value: 'contactUpsert',
},
{
name: 'Contact Added',
value: 'contactInsert',
},
],
default: 'prospectUpsert',
required: true,
},
{
displayName: 'Qualification Status',
name: 'label',
type: 'options',
default: 666,
options: [
{ name: 'All', value: 666 },
{ name: 'Qualified', value: 1 },
{ name: 'Disqualified', value: 0 },
{ name: 'Not Qualified', value: -1 },
],
description: 'Filter Prospects by their qualification status',
displayOptions: {
show: {
event: ['prospectUpsert', 'prospectInsert'],
},
},
},
{
displayName: 'Tags to Include',
name: 'tags',
type: 'multiOptions',
typeOptions: {
loadOptionsMethod: 'getTags',
},
default: [],
description: 'Choose from the list, or specify IDs using an <a href="https://docs.n8n.io/code/expressions/">expression</a>',
displayOptions: {
show: {
event: ['prospectUpsert', 'prospectInsert'],
},
},
},
{
displayName: 'Tags to Exclude',
name: 'not_tags',
type: 'multiOptions',
typeOptions: {
loadOptionsMethod: 'getTags',
},
default: [],
description: 'Choose from the list, or specify IDs using an <a href="https://docs.n8n.io/code/expressions/">expression</a>',
displayOptions: {
show: {
event: ['prospectUpsert', 'prospectInsert'],
},
},
},
{
displayName: 'Website Visits',
name: 'total_visits',
type: 'options',
default: '666',
options: [
{ name: 'All', value: '666' },
{ name: 'With Website Visits', value: '1' },
{ name: 'Without Website Visits', value: '0:0' },
],
displayOptions: {
show: {
event: ['prospectUpsert', 'prospectInsert'],
},
},
description: 'Filter Prospects by website visits',
},
{
displayName: 'Contacts',
name: 'total_contacts',
type: 'options',
default: '666',
options: [
{ name: 'All', value: '666' },
{ name: 'With Contacts', value: '1' },
{ name: 'Without Contacts', value: '0:0' },
],
displayOptions: {
show: {
event: ['prospectUpsert', 'prospectInsert'],
},
},
description: 'Filter Prospects by contacts',
},
{
displayName: 'Audience Names or IDs',
name: 'audiences',
type: 'multiOptions',
typeOptions: {
loadOptionsMethod: 'getAudiences',
},
default: [],
description: 'Filter Prospects by Audiences (uses "lists" API parameter). Choose from the list, or specify IDs using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
displayOptions: {
show: {
event: ['prospectUpsert', 'prospectInsert'],
},
},
},
{
displayName: 'Owner Name or ID',
name: 'owner',
type: 'options',
typeOptions: {
loadOptionsMethod: 'getOwners',
},
default: '',
description: 'Filter Prospects by owner (uses "owner" API parameter). Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
displayOptions: {
show: {
event: ['prospectUpsert', 'prospectInsert'],
},
},
},
{
displayName: 'Company ID',
name: 'companyId',
type: 'string',
default: '',
description: 'Filter Contacts by Company/Prospect ID',
displayOptions: {
show: {
event: ['contactUpsert', 'contactInsert'],
},
},
},
],
};
this.methods = {
loadOptions: {
getTags: GenericFunctions_1.getProspectProTags,
getAudiences: GenericFunctions_1.getProspectProAudiences,
getOwners: GenericFunctions_1.getProspectProOwners,
},
};
}
async poll() {
var _a, _b, _c;
const workflowData = this.getWorkflowStaticData('node');
const event = this.getNodeParameter('event');
const nowInSeconds = Math.floor(Date.now() / 1000);
const isManualMode = this.getMode() === 'manual';
const parseItemTime = (item, timeField, isContact) => {
const time = item[timeField];
return isContact ? (parseInt(time) || 0) : (time || 0);
};
const fetchItems = async (endpoint, fromTime, useInsertedTime = false, lastSeenIds = []) => {
const maxRows = (isManualMode || !fromTime) ? 5 : 100;
const qs = {
no_header: 1,
sort_by: useInsertedTime ? 'inserted_time' : 'changed_time',
sort_order: 'asc',
rows: maxRows,
};
if (!isManualMode && fromTime) {
if (useInsertedTime) {
qs.from_inserted_time = fromTime + 1;
}
else {
qs.from_changed_time = fromTime;
}
}
if (endpoint === '/prospects') {
const label = this.getNodeParameter('label', 666);
if (label !== 666)
qs.label = label;
const tags = this.getNodeParameter('tags', []);
if (tags.length > 0)
qs.tags = tags.join(',');
const audiences = this.getNodeParameter('audiences', []);
if (audiences.length > 0)
qs.lists = audiences.join(',');
const owner = this.getNodeParameter('owner', '');
if (owner !== '')
qs.owner = owner;
const total_contacts = this.getNodeParameter('total_contacts', '666');
if (total_contacts !== '666')
qs.total_contacts = total_contacts;
const total_visits = this.getNodeParameter('total_visits', '666');
if (total_visits !== '666')
qs.total_visits = total_visits;
const not_tags = this.getNodeParameter('not_tags', []);
if (not_tags.length > 0)
qs.NOT_tags = not_tags.join(',');
}
else {
const companyId = this.getNodeParameter('companyId', '');
if (companyId !== '')
qs.company_id = companyId;
}
const response = await GenericFunctions_1.apiRequest.call(this, 'GET', endpoint, {}, qs);
let items;
if (Array.isArray(response)) {
items = response;
}
else if (endpoint === '/prospects') {
items = (response === null || response === void 0 ? void 0 : response.companies) || (response === null || response === void 0 ? void 0 : response.prospects) || (response === null || response === void 0 ? void 0 : response.data) || [];
}
else {
items = (response === null || response === void 0 ? void 0 : response.contacts) || (response === null || response === void 0 ? void 0 : response.data) || [];
}
if (!Array.isArray(items)) {
this.logger.warn(`Unexpected response structure from ProspectPro API: ${JSON.stringify(response)}`);
items = [];
}
const timeField = useInsertedTime ? 'inserted_time' : 'changed_time';
const isContact = endpoint === '/contacts';
items.sort((a, b) => {
const timeA = parseItemTime(a, timeField, isContact);
const timeB = parseItemTime(b, timeField, isContact);
return timeA - timeB;
});
if (!useInsertedTime && fromTime && lastSeenIds.length > 0) {
items = items.filter(item => {
const itemTime = parseItemTime(item, timeField, isContact);
const itemId = String(item.id || item.company_id || item.contact_id || '');
if (itemTime === fromTime && itemId && lastSeenIds.includes(itemId)) {
return false;
}
return true;
});
}
return (isManualMode || !fromTime)
? items.slice(-maxRows)
: items.slice(0, maxRows);
};
try {
const isContactEvent = event === 'contactUpsert' || event === 'contactInsert';
const isInsertMode = event === 'contactInsert' || event === 'prospectInsert';
const endpoint = isContactEvent ? '/contacts' : '/prospects';
const stateKey = isContactEvent
? (isInsertMode ? 'contactsInserted' : 'contacts')
: (isInsertMode ? 'prospectsInserted' : 'prospects');
if (!workflowData[stateKey]) {
workflowData[stateKey] = { lastPolledTimeSeconds: nowInSeconds, lastIdsAtTime: [] };
}
const state = workflowData[stateKey];
const lastPolledTime = state.lastPolledTimeSeconds || nowInSeconds;
const lastSeenIds = state.lastIdsAtTime || [];
const items = await fetchItems(endpoint, isManualMode ? undefined : lastPolledTime, isInsertMode, lastSeenIds);
if (isManualMode) {
return items.length > 0 ? [this.helpers.returnJsonArray(items)] : null;
}
if (lastPolledTime === nowInSeconds) {
state.lastPolledTimeSeconds = nowInSeconds;
state.lastIdsAtTime = [];
return null;
}
if (!items || items.length === 0) {
if (!isInsertMode && ((_b = (_a = state.lastIdsAtTime) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0) > 0) {
state.lastPolledTimeSeconds = (lastPolledTime || nowInSeconds) + 1;
state.lastIdsAtTime = [];
}
else {
state.lastPolledTimeSeconds = lastPolledTime || nowInSeconds;
state.lastIdsAtTime = [];
}
return null;
}
const timeField = isInsertMode ? 'inserted_time' : 'changed_time';
const latestItem = items[items.length - 1];
const newLastPolledTimeSeconds = parseItemTime(latestItem, timeField, isContactEvent);
if (newLastPolledTimeSeconds > lastPolledTime) {
state.lastPolledTimeSeconds = newLastPolledTimeSeconds;
state.lastIdsAtTime = !isInsertMode
? items
.filter(it => parseItemTime(it, timeField, isContactEvent) === newLastPolledTimeSeconds)
.map(it => String(it.id || it.company_id || it.contact_id || ''))
.filter(Boolean)
: [];
}
else if (newLastPolledTimeSeconds === lastPolledTime) {
if (!isInsertMode) {
const seen = new Set(state.lastIdsAtTime || []);
for (const it of items) {
if (parseItemTime(it, timeField, isContactEvent) === lastPolledTime) {
const id = String(it.id || it.company_id || it.contact_id || '');
if (id)
seen.add(id);
}
}
state.lastIdsAtTime = Array.from(seen);
}
state.lastPolledTimeSeconds = lastPolledTime;
}
else {
}
return [this.helpers.returnJsonArray(items)];
}
catch (error) {
const node = this.getNode();
const errorMessage = error instanceof Error ? error.message : String(error);
this.logger.error(`API request failed in ${node.name}: ${errorMessage}`, { error });
const stateKey = event === 'contactUpsert' ? 'contacts'
: event === 'contactInsert' ? 'contactsInserted'
: event === 'prospectInsert' ? 'prospectsInserted'
: 'prospects';
if (isManualMode || !((_c = workflowData[stateKey]) === null || _c === void 0 ? void 0 : _c.lastPolledTimeSeconds)) {
if (error instanceof n8n_workflow_1.NodeOperationError) {
throw error;
}
if (error instanceof Error) {
throw new n8n_workflow_1.NodeOperationError(node, error, { description: error.message });
}
throw new n8n_workflow_1.NodeOperationError(node, new Error('Unknown API error during ProspectPro request.'), { description: 'Unknown API error during ProspectPro request.' });
}
return null;
}
}
}
exports.ProspectproTrigger = ProspectproTrigger;
//# sourceMappingURL=ProspectproTrigger.node.js.map