2023-01-27 03:22:44 -08:00
import type { IExecuteFunctions } from 'n8n-core' ;
2021-11-05 10:37:50 -07:00
2023-01-27 03:22:44 -08:00
import type {
2021-11-05 10:37:50 -07:00
IDataObject ,
INodeExecutionData ,
INodeType ,
INodeTypeDescription ,
} from 'n8n-workflow' ;
2023-01-27 03:22:44 -08:00
import { NodeApiError } from 'n8n-workflow' ;
2021-11-05 10:37:50 -07:00
2023-01-31 11:39:20 -08:00
import { dropcontactApiRequest , mapPairedItemsFrom } from './GenericFunction' ;
2021-11-05 10:37:50 -07:00
export class Dropcontact implements INodeType {
description : INodeTypeDescription = {
displayName : 'Dropcontact' ,
name : 'dropcontact' ,
icon : 'file:dropcontact.svg' ,
group : [ 'transform' ] ,
version : 1 ,
description : 'Find B2B emails and enrich contacts' ,
subtitle : '={{$parameter["operation"] + ": " + $parameter["resource"]}}' ,
defaults : {
name : 'Dropcontact' ,
} ,
inputs : [ 'main' ] ,
outputs : [ 'main' ] ,
credentials : [
{
name : 'dropcontactApi' ,
required : true ,
} ,
] ,
properties : [
{
displayName : 'Resource' ,
noDataExpression : true ,
name : 'resource' ,
type : 'options' ,
options : [
{
name : 'Contact' ,
value : 'contact' ,
} ,
] ,
default : 'contact' ,
required : true ,
} ,
{
displayName : 'Operation' ,
noDataExpression : true ,
name : 'operation' ,
type : 'options' ,
options : [
{
name : 'Enrich' ,
value : 'enrich' ,
description : 'Find B2B emails and enrich your contact from his name and his website' ,
2022-07-10 13:50:51 -07:00
action : 'Find B2B emails' ,
2021-11-05 10:37:50 -07:00
} ,
{
name : 'Fetch Request' ,
value : 'fetchRequest' ,
} ,
] ,
default : 'enrich' ,
required : true ,
} ,
{
displayName : 'Request ID' ,
name : 'requestId' ,
type : 'string' ,
required : true ,
displayOptions : {
show : {
2022-08-01 13:47:55 -07:00
resource : [ 'contact' ] ,
operation : [ 'fetchRequest' ] ,
2021-11-05 10:37:50 -07:00
} ,
} ,
default : '' ,
} ,
{
displayName : 'Email' ,
name : 'email' ,
type : 'string' ,
2022-06-20 07:54:01 -07:00
placeholder : 'name@email.com' ,
2021-11-05 10:37:50 -07:00
displayOptions : {
show : {
2022-08-01 13:47:55 -07:00
resource : [ 'contact' ] ,
operation : [ 'enrich' ] ,
2021-11-05 10:37:50 -07:00
} ,
} ,
default : '' ,
} ,
{
displayName : 'Simplify Output (Faster)' ,
name : 'simplify' ,
type : 'boolean' ,
displayOptions : {
show : {
2022-08-01 13:47:55 -07:00
resource : [ 'contact' ] ,
operation : [ 'enrich' ] ,
2021-11-05 10:37:50 -07:00
} ,
} ,
default : false ,
2022-06-20 07:54:01 -07:00
// eslint-disable-next-line n8n-nodes-base/node-param-description-boolean-without-whether
2022-08-01 13:47:55 -07:00
description :
'When off, waits for the contact data before completing. Waiting time can be adjusted with Extend Wait Time option. When on, returns a request_id that can be used later in the Fetch Request operation.' ,
2021-11-05 10:37:50 -07:00
} ,
{
displayName : 'Additional Fields' ,
name : 'additionalFields' ,
type : 'collection' ,
placeholder : 'Add Field' ,
default : { } ,
displayOptions : {
show : {
2022-08-01 13:47:55 -07:00
resource : [ 'contact' ] ,
operation : [ 'enrich' ] ,
2021-11-05 10:37:50 -07:00
} ,
} ,
options : [
{
displayName : 'Company SIREN Number' ,
name : 'num_siren' ,
type : 'string' ,
default : '' ,
} ,
{
displayName : 'Company SIRET Code' ,
name : 'siret' ,
type : 'string' ,
default : '' ,
} ,
{
displayName : 'Company Name' ,
name : 'company' ,
type : 'string' ,
default : '' ,
} ,
{
displayName : 'Country' ,
name : 'country' ,
type : 'string' ,
default : '' ,
} ,
{
displayName : 'First Name' ,
name : 'first_name' ,
type : 'string' ,
default : '' ,
} ,
{
displayName : 'Full Name' ,
name : 'full_name' ,
type : 'string' ,
default : '' ,
} ,
{
displayName : 'Last Name' ,
name : 'last_name' ,
type : 'string' ,
default : '' ,
} ,
{
displayName : 'LinkedIn Profile' ,
name : 'linkedin' ,
type : 'string' ,
default : '' ,
} ,
{
displayName : 'Phone Number' ,
name : 'phone' ,
type : 'string' ,
default : '' ,
} ,
{
displayName : 'Website' ,
name : 'website' ,
type : 'string' ,
default : '' ,
} ,
] ,
} ,
{
displayName : 'Options' ,
name : 'options' ,
type : 'collection' ,
displayOptions : {
show : {
2022-08-01 13:47:55 -07:00
resource : [ 'contact' ] ,
operation : [ 'enrich' ] ,
2021-11-05 10:37:50 -07:00
} ,
} ,
placeholder : 'Add Option' ,
default : { } ,
options : [
{
displayName : 'Data Fetch Wait Time' ,
name : 'waitTime' ,
type : 'number' ,
typeOptions : {
minValue : 1 ,
} ,
displayOptions : {
show : {
2022-08-01 13:47:55 -07:00
'/simplify' : [ false ] ,
2021-11-05 10:37:50 -07:00
} ,
} ,
default : 45 ,
2022-08-01 13:47:55 -07:00
description :
'When not simplifying the response, data will be fetched in two steps. This parameter controls how long to wait (in seconds) before trying the second step.' ,
2021-11-05 10:37:50 -07:00
} ,
{
displayName : 'French Company Enrich' ,
name : 'siren' ,
type : 'boolean' ,
default : false ,
2022-08-01 13:47:55 -07:00
description :
'Whether you want the <a href="https://en.wikipedia.org/wiki/SIREN_code" target="_blank">SIREN number</a>, NAF code, TVA number, company address and informations about the company leader. Only applies to french companies.' ,
2021-11-05 10:37:50 -07:00
} ,
{
displayName : 'Language' ,
name : 'language' ,
type : 'options' ,
options : [
{
name : 'English' ,
value : 'en' ,
} ,
{
name : 'French' ,
value : 'fr' ,
} ,
] ,
default : 'en' ,
description : 'Whether the response is in English or French' ,
} ,
] ,
} ,
] ,
} ;
2022-12-02 12:54:28 -08:00
2021-11-05 10:37:50 -07:00
async execute ( this : IExecuteFunctions ) : Promise < INodeExecutionData [ ] [ ] > {
const entryData = this . getInputData ( ) ;
2022-12-02 03:53:59 -08:00
const resource = this . getNodeParameter ( 'resource' , 0 ) ;
const operation = this . getNodeParameter ( 'operation' , 0 ) ;
2022-12-02 06:25:21 -08:00
2021-11-05 10:37:50 -07:00
let responseData : any ;
2023-01-31 11:39:20 -08:00
const returnData : INodeExecutionData [ ] = [ ] ;
2021-11-05 10:37:50 -07:00
if ( resource === 'contact' ) {
if ( operation === 'enrich' ) {
2022-12-02 12:54:28 -08:00
const options = this . getNodeParameter ( 'options' , 0 ) ;
2021-11-05 10:37:50 -07:00
const data = [ ] ;
const simplify = this . getNodeParameter ( 'simplify' , 0 ) as boolean ;
const siren = options . siren === true ? true : false ;
const language = options . language ? options . language : 'en' ;
for ( let i = 0 ; i < entryData . length ; i ++ ) {
const email = this . getNodeParameter ( 'email' , i ) as string ;
const additionalFields = this . getNodeParameter ( 'additionalFields' , i ) ;
const body : IDataObject = { } ;
if ( email !== '' ) {
body . email = email ;
}
Object . assign ( body , additionalFields ) ;
data . push ( body ) ;
}
2022-08-01 13:47:55 -07:00
responseData = ( await dropcontactApiRequest . call (
this ,
'POST' ,
'/batch' ,
{ data , siren , language } ,
{ } ,
) ) as { request_id : string ; error : string ; success : boolean } ;
2021-11-05 10:37:50 -07:00
if ( ! responseData . success ) {
if ( this . continueOnFail ( ) ) {
2023-01-31 11:39:20 -08:00
const executionData = this . helpers . constructExecutionMetaData (
this . helpers . returnJsonArray ( { error : responseData.reason || 'invalid request' } ) ,
{
itemData : mapPairedItemsFrom ( entryData ) ,
} ,
) ;
returnData . push ( . . . executionData ) ;
2021-11-05 10:37:50 -07:00
} else {
2022-08-01 13:47:55 -07:00
throw new NodeApiError ( this . getNode ( ) , {
error : responseData.reason || 'invalid request' ,
} ) ;
2021-11-05 10:37:50 -07:00
}
}
2022-12-02 12:54:28 -08:00
if ( ! simplify ) {
2021-11-05 10:37:50 -07:00
const waitTime = this . getNodeParameter ( 'options.waitTime' , 0 , 45 ) as number ;
2022-12-02 06:25:21 -08:00
2022-12-02 12:54:28 -08:00
const delay = async ( ms : any ) = > new Promise ( ( res ) = > setTimeout ( res , ms * 1000 ) ) ;
2021-11-05 10:37:50 -07:00
await delay ( waitTime ) ;
2022-08-01 13:47:55 -07:00
responseData = await dropcontactApiRequest . call (
this ,
'GET' ,
` /batch/ ${ responseData . request_id } ` ,
{ } ,
{ } ,
) ;
2021-11-05 10:37:50 -07:00
if ( ! responseData . success ) {
if ( this . continueOnFail ( ) ) {
2023-01-31 11:39:20 -08:00
const executionData = this . helpers . constructExecutionMetaData (
this . helpers . returnJsonArray ( { error : responseData.reason } ) ,
{
itemData : mapPairedItemsFrom ( entryData ) ,
} ,
) ;
returnData . push ( . . . executionData ) ;
2021-11-05 10:37:50 -07:00
} else {
throw new NodeApiError ( this . getNode ( ) , {
error : responseData.reason ,
description : 'Hint: Increase the Wait Time to avoid this error' ,
} ) ;
}
} else {
2023-01-31 11:39:20 -08:00
responseData . data . forEach ( ( d : IDataObject , index : number ) = > {
const executionData = this . helpers . constructExecutionMetaData (
this . helpers . returnJsonArray ( d ) ,
{ itemData : { item : index } } ,
) ;
returnData . push ( . . . executionData ) ;
} ) ;
2021-11-05 10:37:50 -07:00
}
} else {
2023-01-31 11:39:20 -08:00
const executionData = this . helpers . constructExecutionMetaData (
2023-02-27 19:39:43 -08:00
this . helpers . returnJsonArray ( responseData as IDataObject [ ] ) ,
2023-01-31 11:39:20 -08:00
{
itemData : mapPairedItemsFrom ( entryData ) ,
} ,
) ;
returnData . push ( . . . executionData ) ;
2021-11-05 10:37:50 -07:00
}
}
if ( operation === 'fetchRequest' ) {
for ( let i = 0 ; i < entryData . length ; i ++ ) {
const requestId = this . getNodeParameter ( 'requestId' , i ) as string ;
2022-08-01 13:47:55 -07:00
responseData = ( await dropcontactApiRequest . call (
this ,
'GET' ,
` /batch/ ${ requestId } ` ,
{ } ,
{ } ,
) ) as { request_id : string ; error : string ; success : boolean } ;
2021-11-05 10:37:50 -07:00
if ( ! responseData . success ) {
if ( this . continueOnFail ( ) ) {
2023-01-31 11:39:20 -08:00
const executionData = this . helpers . constructExecutionMetaData (
this . helpers . returnJsonArray ( { error : responseData.reason || 'invalid request' } ) ,
{ itemData : { item : i } } ,
) ;
returnData . push ( . . . executionData ) ;
2021-11-05 10:37:50 -07:00
} else {
2022-08-01 13:47:55 -07:00
throw new NodeApiError ( this . getNode ( ) , {
error : responseData.reason || 'invalid request' ,
} ) ;
2021-11-05 10:37:50 -07:00
}
}
2023-01-31 11:39:20 -08:00
const executionData = this . helpers . constructExecutionMetaData (
2023-02-27 19:39:43 -08:00
this . helpers . returnJsonArray ( responseData . data as IDataObject [ ] ) ,
2023-01-31 11:39:20 -08:00
{ itemData : { item : i } } ,
) ;
returnData . push ( . . . executionData ) ;
2021-11-05 10:37:50 -07:00
}
}
}
2023-01-31 11:39:20 -08:00
return this . prepareOutputData ( returnData ) ;
2021-11-05 10:37:50 -07:00
}
}