From 8d886e37669419cdf4596448779624d8079e3a27 Mon Sep 17 00:00:00 2001 From: Ricardo Espinoza Date: Fri, 15 Nov 2019 15:10:51 -0500 Subject: [PATCH 01/10] :tada: node setup --- .../credentials/IntercomApi.credentials.ts | 18 ++++++ .../nodes/Intercom/Intercom.node.ts | 59 ++++++++++++++++++ .../nodes-base/nodes/Intercom/intercom.png | Bin 0 -> 3889 bytes packages/nodes-base/package.json | 6 +- 4 files changed, 81 insertions(+), 2 deletions(-) create mode 100644 packages/nodes-base/credentials/IntercomApi.credentials.ts create mode 100644 packages/nodes-base/nodes/Intercom/Intercom.node.ts create mode 100644 packages/nodes-base/nodes/Intercom/intercom.png diff --git a/packages/nodes-base/credentials/IntercomApi.credentials.ts b/packages/nodes-base/credentials/IntercomApi.credentials.ts new file mode 100644 index 0000000000..64263e889f --- /dev/null +++ b/packages/nodes-base/credentials/IntercomApi.credentials.ts @@ -0,0 +1,18 @@ +import { + ICredentialType, + NodePropertyTypes, +} from 'n8n-workflow'; + + +export class IntercomApi implements ICredentialType { + name = 'intercomApi'; + displayName = 'Intercom API'; + properties = [ + { + displayName: 'API Key', + name: 'apiKey', + type: 'string' as NodePropertyTypes, + default: '', + }, + ]; +} diff --git a/packages/nodes-base/nodes/Intercom/Intercom.node.ts b/packages/nodes-base/nodes/Intercom/Intercom.node.ts new file mode 100644 index 0000000000..55e61151b7 --- /dev/null +++ b/packages/nodes-base/nodes/Intercom/Intercom.node.ts @@ -0,0 +1,59 @@ +import { + IExecuteSingleFunctions, +} from 'n8n-core'; +import { + IDataObject, + INodeTypeDescription, + INodeExecutionData, + INodeType, + ILoadOptionsFunctions, + INodePropertyOptions, +} from 'n8n-workflow'; + +export class Intercom implements INodeType { + + description: INodeTypeDescription = { + displayName: 'Intercom', + name: 'intercom', + icon: 'file:intercom.png', + group: ['output'], + version: 1, + subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}', + description: 'Consume intercom API', + defaults: { + name: 'Intercom', + color: '#c02428', + }, + inputs: ['main'], + outputs: ['main'], + credentials: [ + { + name: 'intercomApi', + required: true, + } + ], + properties: [ + { + displayName: 'Resource', + name: 'resource', + type: 'options', + options: [ + { + name: 'Lead', + value: 'lead', + description: '', + }, + ], + default: '', + description: 'Resource to consume.', + }, + ], + }; + + async executeSingle(this: IExecuteSingleFunctions): Promise { + + return { + json: {}, + }; + } +} diff --git a/packages/nodes-base/nodes/Intercom/intercom.png b/packages/nodes-base/nodes/Intercom/intercom.png new file mode 100644 index 0000000000000000000000000000000000000000..5fb79c11eaef5ddafeccef79968dce56aae790f0 GIT binary patch literal 3889 zcmY*cc{~(c_qXpdmJA|evTtLlFkx)jcVaAAW-w$og9+I~5yD8e$ew+dq_HH~myn$h z*%@ISBhT zP5WIeq-awuHIk|!?r#?xS|4pIGzm#+!5#u0?|^zcGMu}a{-5YP+%PZ$CQ{RP3eD}mt##vpZXKWESl$?K9* zU}ZWG2&CxeiAD@!Z>h5Vn`KRSw#KjQyY%-@~<6}@OxnNAV% z@3kq@>30fQT|AGkj)tnaE9H(&SOU*&o)^#OAMDNJOz$Dxi1`wpJ2>~-@qA|m`PQsY z&K=mK`88hBi1_?s9^uekT4K7cn-@rF76AjX2$ZSm1DJ8fPhgpF(2c2uMjZD`i#Um6 z;lRC}-GNi$z;63&aP!{6-91ygRKwPj0Mt7|&ffY@cNbK#Y2n%{yRCO~Vo2qxdB4Lm z-+kq$@dgGo?%)l* zkrot!)Z$xt3KNKgIcAnRFntd=1s}G;Iw!pqPCi(4`UqpnEQ=J(vnMGF4if~&3|zNh zz(-8cVvwW7`M<{`sa^ezcC6mjV;Zl<_o#gGjUn?83=l6|?{ao;->W`s^(wDS&7DH! zP}6JfxYcdCZT76$T)B_SE9|OyRgre3t*+mY8J}C_l+f-G_uJ4iF*%)6r}s&_sh@(k z381xJ)WfLhtcWT;ZT-i7pDMn&*k#$xx84M@LT!;~$qZ}HGBmMB&9Pm!LH<(kMeLic z;h#~E&GPljk@+g=LI6IMC@B?&f-hTr^h5Qn8IuQ5>swrKtNC7Us0u5WSm7F6z$4r- z$WYw9h*!Jt9EiCQLSpfgDc6m8UAxSQizHdDi<`&J%g_c{stb#pUO>V(9y zC?{N53~XXzgE^cB*LQGjW15Yj=V7kgwOp=Lwr=gCRfjMlp{2bDM{JllcwmQm7en8tBs5lX z)sqWexAWSZ9s%hzPo8CepKtz*zO*OI8;!5lU3}YDkwP?mj_Fd1&eNHxdudlOtdNBJ z!D-=(z-&|=#_wm!r7vogdstuCX%R&@}_%A5xN6U!z$nHvUyOkV#@v zr=f|1JLG=de)?V2{Xn^vp=SRrM>vBil=|z6y!0->Tbs&D8Bct0LOnkRa?|>9fRO4D zWl$i6JPK~RN0&KROvT{Kf0`i`YMAssa7LahI(=HO#F=Ig!2+5H^s9RV{0|nxUtz2_274s&bwBj-?C%#Uh5`Dxos#lxVUchzYrF7BeHuYSyK;zF_ws*duvEXv_saq_x z_tUCawSvPYL5p|2dC4&}eQQ#LlYdrt+-7{}^+&UYZiGf@#fCOGh9ot?P9ZOg-#)*X^#bMK{2?H$k+_AlhjEyq*%yGe|)%o7CP zs7eVXlX0nyS8HU*f_?u3E-&qMQtJo|8T}Wm*p6tEYDLl^a2SXd;i)U}OyT8D^VM-# zV~IAatJ|mxjqDtC@TR?$Aljbc5wMrux}sPM@JJW5$$g^f=SkBb06%nJ8!L3XllCaP z<)mVoAEaZ>$wW0rf#KlvL_3$i5O7+e&(2$I_{!+KTt zz6T9}rBW!j`(5JtX3?@z+&gCdQ$-Cu8{6amH62MLn_G|e4= z{3;G{=e`O(S${24QsAkV^z1ZN5YWGTls*702BJg2$6YZAu%D^4a%T3%@_XScnwG4 zoYFR0ePXhk{}{br_f4ufv8xll*tf<(uge~u5L6hBy=l`E8B{mxIsqI^m9yg?Y2_js z{k*;rb3VTS!y5u^2>yZ!_pC+BhY9MWVq5Y-itSn=Px#$m*=qqSqb;FrLJo44NTev|P)(_Hy5P|U{Ahc=tm?|pPOCe(Js zL56k8FkUtr73xU-N-}~7Hb=OBf^3bJzAFE^(9ymWTpCyuob}6^`*xJP%%e{w!w_fc%lTAp5)_#x=T@q_-2>45|!C)%|cwk5U7f#vYkfT#7rPrsr;_$ii z;MW;znxB+MKdi7zK_1xG;ykNe#QlYp{RaQ4yU5}gm3_bLRq1P$BxaI~2&Mz^ zn*MfRz>lGkogiZJD%*c@O&Trw}vYX0%9Z3HZF3Or%wQqjuxy?=C;B`||zW zU&17@zu@wKwnIycOQ&#~>nOG6{q$=_S#vh`M{k-)@A2TyLysbzsA7S<)8=m}5(8yp z$_;w?2#z!9h&`{|X^-EJ_K3%e(KS*i|k`h#) zQsEjgZiw9C&?J$sYjX7G8djyEno7Cface3g{7l(`hg_QOXt}!{2Eb3f{~Hi;!pp(F*c0N}O>wNm(6!qyil;E`*QGXG z9*(VJ7jc7VWL@4rzA>p8_n=WNoh-043#p8{=VKd08{5bd)H8ham|lOKjvKsmO;*e` zxdp&V;ncm3G(bvIWY?HR-i{(T(%M-*m79Md=Gc2|;l|l1k?p?14eH6ESuYQ1AXSGC z7csbCj6s%CHmF*IZqj9!U0I=d{vUc) z0(>e(W4;977SJ6phqsfL~p_s(82ssm}kU* z-{}15Ayo)Alnw%mcG2cPEfy3w!C@0bX6^eDuR9Na(yMPx5Ik27voADjAD(e;i_hH( tkr6!R*tL5&V#M^F8d8()pzz=qOy2ME9Qh((>d!w`=eD6nm6}83e*jMfFM0p~ literal 0 HcmV?d00001 diff --git a/packages/nodes-base/package.json b/packages/nodes-base/package.json index 1e3e1ceeae..193f0c0fc6 100644 --- a/packages/nodes-base/package.json +++ b/packages/nodes-base/package.json @@ -39,7 +39,8 @@ "dist/credentials/GoogleApi.credentials.js", "dist/credentials/HttpBasicAuth.credentials.js", "dist/credentials/HttpDigestAuth.credentials.js", - "dist/credentials/HttpHeaderAuth.credentials.js", + "dist/credentials/HttpHeaderAuth.credentials.js", + "dist/credentials/IntercomApi.credentials.js", "dist/credentials/Imap.credentials.js", "dist/credentials/LinkFishApi.credentials.js", "dist/credentials/MailgunApi.credentials.js", @@ -95,7 +96,8 @@ "dist/nodes/GraphQL/GraphQL.node.js", "dist/nodes/HttpRequest.node.js", "dist/nodes/If.node.js", - "dist/nodes/Interval.node.js", + "dist/nodes/Interval.node.js", + "dist/nodes/Intercom/Intercom.node.js", "dist/nodes/LinkFish/LinkFish.node.js", "dist/nodes/Mailgun/Mailgun.node.js", "dist/nodes/Mandrill/Mandrill.node.js", From 7a1983783372f28813afee113349db4bee5319b0 Mon Sep 17 00:00:00 2001 From: Ricardo Espinoza Date: Sat, 16 Nov 2019 17:16:11 -0500 Subject: [PATCH 02/10] :lipstick: create lead UI done --- .../nodes/Intercom/GenericFunctions.ts | 45 +++++ .../nodes/Intercom/Intercom.node.ts | 35 ++++ .../nodes/Intercom/LeadDescription.ts | 172 ++++++++++++++++++ 3 files changed, 252 insertions(+) create mode 100644 packages/nodes-base/nodes/Intercom/GenericFunctions.ts create mode 100644 packages/nodes-base/nodes/Intercom/LeadDescription.ts diff --git a/packages/nodes-base/nodes/Intercom/GenericFunctions.ts b/packages/nodes-base/nodes/Intercom/GenericFunctions.ts new file mode 100644 index 0000000000..007aa700cb --- /dev/null +++ b/packages/nodes-base/nodes/Intercom/GenericFunctions.ts @@ -0,0 +1,45 @@ +import { OptionsWithUri } from 'request'; + +import { + IExecuteFunctions, + IHookFunctions, + ILoadOptionsFunctions, + IExecuteSingleFunctions +} from 'n8n-core'; + +export async function intercomApiRequest(this: IHookFunctions | IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions, resource: string, method: string, body: any = {}, headers?: object): Promise { // tslint:disable-line:no-any + const credentials = this.getCredentials('intercomApi'); + + if (credentials === undefined) { + throw new Error('No credentials got returned!'); + } + + const headerWithAuthentication = Object.assign({}, headers, + { Authorization: `Bearer ${credentials.apiKey}`, Accept: 'application/json' }); + + const endpoint = 'api.intercom.io'; + + const options: OptionsWithUri = { + headers: headerWithAuthentication, + method, + uri: `https://${endpoint}${resource}`, + body, + json: true + }; + + console.log(options) + + + try { + return await this.helpers.request!(options); + } catch (error) { + console.error(error); + + const errorMessage = error.response.body.message || error.response.body.Message; + + if (errorMessage !== undefined) { + throw errorMessage; + } + throw error.response.body; + } +} diff --git a/packages/nodes-base/nodes/Intercom/Intercom.node.ts b/packages/nodes-base/nodes/Intercom/Intercom.node.ts index 55e61151b7..e746715fbb 100644 --- a/packages/nodes-base/nodes/Intercom/Intercom.node.ts +++ b/packages/nodes-base/nodes/Intercom/Intercom.node.ts @@ -9,6 +9,13 @@ import { ILoadOptionsFunctions, INodePropertyOptions, } from 'n8n-workflow'; +import { + leadOpeations, + leadFields, +} from './LeadDescription'; +import { + intercomApiRequest, +} from './GenericFunctions'; export class Intercom implements INodeType { @@ -47,9 +54,37 @@ export class Intercom implements INodeType { default: '', description: 'Resource to consume.', }, + ...leadOpeations, + ...leadFields, ], }; + methods = { + loadOptions: { + // Get all the available companies to display them to user so that he can + // select them easily + async getCompanies(this: ILoadOptionsFunctions): Promise { + const returnData: INodePropertyOptions[] = []; + let companies, response; + try { + response = await intercomApiRequest.call(this, '/companies', 'GET'); + } catch (err) { + throw new Error(`Intercom Error: ${err}`); + } + companies = response.companies; + for (const company of companies) { + const companyName = company.name; + const companyId = company.id; + returnData.push({ + name: companyName, + value: companyId, + }); + } + return returnData; + } + }, + }; + async executeSingle(this: IExecuteSingleFunctions): Promise { return { diff --git a/packages/nodes-base/nodes/Intercom/LeadDescription.ts b/packages/nodes-base/nodes/Intercom/LeadDescription.ts new file mode 100644 index 0000000000..ef4e8ea3ff --- /dev/null +++ b/packages/nodes-base/nodes/Intercom/LeadDescription.ts @@ -0,0 +1,172 @@ +import { INodeProperties } from "n8n-workflow"; + +export const leadOpeations = [ + { + displayName: 'Operation', + name: 'operation', + type: 'options', + displayOptions: { + show: { + resource: [ + 'lead', + ], + }, + }, + options: [ + { + name: 'Create', + value: 'create', + description: 'Create a new lead', + }, + ], + default: '', + description: 'The operation to perform.', + }, +] as INodeProperties[]; + +export const leadFields = [ + { + displayName: 'Email', + name: 'email', + type: 'string', + default: '', + required: true, + displayOptions: { + show: { + resource: [ + 'lead', + ], + operation: [ + 'create', + ], + }, + }, + description: 'The email of the user.', + }, + { + displayName: 'JSON Parameters', + name: 'jsonParameters', + type: 'boolean', + default: false, + description: '', + displayOptions: { + show: { + operation: [ + 'create', + ], + resource: [ + 'lead' + ], + }, + }, + }, + { + displayName: 'Options', + name: 'options', + type: 'collection', + placeholder: 'Add Option', + default: {}, + displayOptions: { + show: { + operation: [ + 'create', + ], + resource: [ + 'lead' + ], + }, + }, + options: [ + { + displayName: 'Phone', + name: 'phone', + type: 'string', + default: '', + required: false, + description: 'The phone number of the user', + }, + { + displayName: 'Name', + name: 'name', + type: 'string', + default: '', + placeholder: '', + description: 'Name of the user', + }, + { + displayName: 'Unsubscribed From Emails', + name: 'unsubscribedFromEmails', + type: 'boolean', + default: '', + placeholder: '', + description: 'Whether the Lead is unsubscribed from emails', + }, + { + displayName: 'Update Last Request At', + name: 'updateLastRequestAt', + type: 'boolean', + default: false, + options: [], + required: false, + description: `A boolean value, which if true, instructs Intercom to update the users' last_request_at value to the current API service time in UTC. default value if not sent is false.`, + }, + { + displayName: 'Companies', + name: 'companies', + type: 'multiOptions', + typeOptions: { + loadOptionsMethod: 'getCompanies', + }, + default: [], + required: false, + description: 'Identifies the companies this user belongs to.', + }, + ] + }, + { + displayName: 'Custom Attributes', + name: 'customAttributes', + type: 'fixedCollection', + default: '', + placeholder: 'Add Attribute', + typeOptions: { + multipleValues: true, + }, + required: false, + displayOptions: { + show: { + resource: [ + 'lead', + ], + operation: [ + 'create', + ], + jsonParameters: [ + false, + ], + }, + }, + options: [ + { + name: 'customAttributesValues', + displayName: 'Attributes', + values: [ + { + displayName: 'Name', + name: 'name', + type: 'string', + default: '', + }, + { + displayName: 'Value', + name: 'value', + type: 'string', + default: '', + }, + ], + } + ], + description: 'A hash of key/value pairs to represent custom data you want to attribute to a user.', + }, +] as INodeProperties[]; + From 3cfcbead719c42a13d737acf2d22a0ce60830aa8 Mon Sep 17 00:00:00 2001 From: Ricardo Espinoza Date: Sat, 16 Nov 2019 18:47:28 -0500 Subject: [PATCH 03/10] :sparkles: Intercom node --- .../nodes/Intercom/GenericFunctions.ts | 13 +++- .../nodes/Intercom/Intercom.node.ts | 69 ++++++++++++++++++- .../nodes/Intercom/LeadDescription.ts | 26 ++++++- .../nodes/Intercom/LeadInterface.ts | 16 +++++ 4 files changed, 117 insertions(+), 7 deletions(-) create mode 100644 packages/nodes-base/nodes/Intercom/LeadInterface.ts diff --git a/packages/nodes-base/nodes/Intercom/GenericFunctions.ts b/packages/nodes-base/nodes/Intercom/GenericFunctions.ts index 007aa700cb..8b32b726be 100644 --- a/packages/nodes-base/nodes/Intercom/GenericFunctions.ts +++ b/packages/nodes-base/nodes/Intercom/GenericFunctions.ts @@ -27,9 +27,6 @@ export async function intercomApiRequest(this: IHookFunctions | IExecuteFunction json: true }; - console.log(options) - - try { return await this.helpers.request!(options); } catch (error) { @@ -43,3 +40,13 @@ export async function intercomApiRequest(this: IHookFunctions | IExecuteFunction throw error.response.body; } } + +export function validateJSON(json: string | undefined): any { // tslint:disable-line:no-any + let result; + try { + result = JSON.parse(json!); + } catch (exception) { + result = ''; + } + return result; +} diff --git a/packages/nodes-base/nodes/Intercom/Intercom.node.ts b/packages/nodes-base/nodes/Intercom/Intercom.node.ts index e746715fbb..8f4c63a926 100644 --- a/packages/nodes-base/nodes/Intercom/Intercom.node.ts +++ b/packages/nodes-base/nodes/Intercom/Intercom.node.ts @@ -15,7 +15,12 @@ import { } from './LeadDescription'; import { intercomApiRequest, + validateJSON, } from './GenericFunctions'; +import { + ILead, + ILeadCompany + } from './LeadInterface'; export class Intercom implements INodeType { @@ -74,7 +79,7 @@ export class Intercom implements INodeType { companies = response.companies; for (const company of companies) { const companyName = company.name; - const companyId = company.id; + const companyId = company.company_id; returnData.push({ name: companyName, value: companyId, @@ -86,9 +91,67 @@ export class Intercom implements INodeType { }; async executeSingle(this: IExecuteSingleFunctions): Promise { - + const resource = this.getNodeParameter('resource') as string; + const opeation = this.getNodeParameter('operation') as string; + let response; + if (resource === 'lead') { + if (opeation === 'create') { + const email = this.getNodeParameter('email') as string; + const options = this.getNodeParameter('options') as IDataObject; + const jsonActive = this.getNodeParameter('jsonParameters') as boolean; + const body: ILead = { + email, + }; + if (options.phone) { + body.phone = options.phone as string; + } + if (options.name) { + body.name = options.name as string; + } + if (options.name) { + body.name = options.name as string; + } + if (options.unsubscribedFromEmails) { + body.unsubscribed_from_emails = options.unsubscribedFromEmails as boolean; + } + if (options.updateLastRequestAt) { + body.update_last_request_at = options.updateLastRequestAt as boolean; + } + if (options.companies) { + const companies: ILeadCompany[] = []; + // @ts-ignore + options.companies.forEach( o => { + const company: ILeadCompany = {}; + company.company_id = o; + companies.push(company); + }); + body.companies = companies; + } + if (!jsonActive) { + const customAttributesValues = (this.getNodeParameter('customAttributesUi') as IDataObject).customAttributesValues as IDataObject[]; + if (customAttributesValues) { + const customAttributes = {}; + for (let i = 0; i < customAttributesValues.length; i++) { + // @ts-ignore + customAttributes[customAttributesValues[i].name] = customAttributesValues[i].value; + } + body.custom_attributes = customAttributes; + } + } else { + const customAttributesJson = validateJSON(this.getNodeParameter('customAttributesJson') as string); + if (customAttributesJson) { + body.custom_attributes = customAttributesJson; + } + } + try { + response = await intercomApiRequest.call(this, '/contacts', 'POST', body); + } catch (err) { + throw new Error(`Intercom Error: ${JSON.stringify(err)}`); + } + } + } return { - json: {}, + json: response, }; } } diff --git a/packages/nodes-base/nodes/Intercom/LeadDescription.ts b/packages/nodes-base/nodes/Intercom/LeadDescription.ts index ef4e8ea3ff..44dc94b594 100644 --- a/packages/nodes-base/nodes/Intercom/LeadDescription.ts +++ b/packages/nodes-base/nodes/Intercom/LeadDescription.ts @@ -125,7 +125,31 @@ export const leadFields = [ }, { displayName: 'Custom Attributes', - name: 'customAttributes', + name: 'customAttributesJson', + type: 'json', + required: false, + typeOptions: { + alwaysOpenEditWindow: true, + }, + displayOptions: { + show: { + resource: [ + 'lead', + ], + operation: [ + 'create', + ], + jsonParameters: [ + true, + ], + }, + }, + default: '', + description: 'A hash of key/value pairs to represent custom data you want to attribute to a user.', + }, + { + displayName: 'Custom Attributes', + name: 'customAttributesUi', type: 'fixedCollection', default: '', placeholder: 'Add Attribute', diff --git a/packages/nodes-base/nodes/Intercom/LeadInterface.ts b/packages/nodes-base/nodes/Intercom/LeadInterface.ts new file mode 100644 index 0000000000..480407bafb --- /dev/null +++ b/packages/nodes-base/nodes/Intercom/LeadInterface.ts @@ -0,0 +1,16 @@ +import { IDataObject } from "n8n-workflow"; + +export interface ILeadCompany { + company_id?: string; +} + +export interface ILead { + email: string; + phone?: string; + name?: string; + custom_attributes?: IDataObject; + companies?: ILeadCompany[]; + last_request_at?: number; + unsubscribed_from_emails?: boolean; + update_last_request_at?: boolean; +} From 2e51e224d8b5ff6cf576f175ecbd93007977bdd1 Mon Sep 17 00:00:00 2001 From: Ricardo Espinoza Date: Sat, 16 Nov 2019 18:57:06 -0500 Subject: [PATCH 04/10] :bug: field name repited --- packages/nodes-base/nodes/Intercom/Intercom.node.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/nodes-base/nodes/Intercom/Intercom.node.ts b/packages/nodes-base/nodes/Intercom/Intercom.node.ts index 8f4c63a926..f7a1024acd 100644 --- a/packages/nodes-base/nodes/Intercom/Intercom.node.ts +++ b/packages/nodes-base/nodes/Intercom/Intercom.node.ts @@ -108,9 +108,6 @@ export class Intercom implements INodeType { if (options.name) { body.name = options.name as string; } - if (options.name) { - body.name = options.name as string; - } if (options.unsubscribedFromEmails) { body.unsubscribed_from_emails = options.unsubscribedFromEmails as boolean; } From b281eb511a102ea863019233dccd81fb3b22c52c Mon Sep 17 00:00:00 2001 From: Ricardo Espinoza Date: Mon, 18 Nov 2019 16:41:00 -0500 Subject: [PATCH 05/10] :construction: added execute function --- .../nodes/Intercom/Intercom.node.ts | 118 ++++++++++-------- 1 file changed, 63 insertions(+), 55 deletions(-) diff --git a/packages/nodes-base/nodes/Intercom/Intercom.node.ts b/packages/nodes-base/nodes/Intercom/Intercom.node.ts index f7a1024acd..ea635e22b7 100644 --- a/packages/nodes-base/nodes/Intercom/Intercom.node.ts +++ b/packages/nodes-base/nodes/Intercom/Intercom.node.ts @@ -1,5 +1,5 @@ import { - IExecuteSingleFunctions, + IExecuteFunctions, } from 'n8n-core'; import { IDataObject, @@ -90,65 +90,73 @@ export class Intercom implements INodeType { }, }; - async executeSingle(this: IExecuteSingleFunctions): Promise { - const resource = this.getNodeParameter('resource') as string; - const opeation = this.getNodeParameter('operation') as string; - let response; - if (resource === 'lead') { - if (opeation === 'create') { - const email = this.getNodeParameter('email') as string; - const options = this.getNodeParameter('options') as IDataObject; - const jsonActive = this.getNodeParameter('jsonParameters') as boolean; - const body: ILead = { - email, - }; - if (options.phone) { - body.phone = options.phone as string; - } - if (options.name) { - body.name = options.name as string; - } - if (options.unsubscribedFromEmails) { - body.unsubscribed_from_emails = options.unsubscribedFromEmails as boolean; - } - if (options.updateLastRequestAt) { - body.update_last_request_at = options.updateLastRequestAt as boolean; - } - if (options.companies) { - const companies: ILeadCompany[] = []; - // @ts-ignore - options.companies.forEach( o => { - const company: ILeadCompany = {}; - company.company_id = o; - companies.push(company); - }); - body.companies = companies; - } - if (!jsonActive) { - const customAttributesValues = (this.getNodeParameter('customAttributesUi') as IDataObject).customAttributesValues as IDataObject[]; - if (customAttributesValues) { - const customAttributes = {}; - for (let i = 0; i < customAttributesValues.length; i++) { - // @ts-ignore - customAttributes[customAttributesValues[i].name] = customAttributesValues[i].value; + async execute(this: IExecuteFunctions): Promise { + const items = this.getInputData(); + const returnData: IDataObject[] = []; + const length = items.length as unknown as number; + let responseData; + for (let i = 0; i < length; i++) { + const resource = this.getNodeParameter('resource', 0) as string; + const opeation = this.getNodeParameter('operation', 0) as string; + if (resource === 'lead') { + if (opeation === 'create') { + const email = this.getNodeParameter('email', i) as string; + const options = this.getNodeParameter('options', i) as IDataObject; + const jsonActive = this.getNodeParameter('jsonParameters', i) as boolean; + const body: ILead = { + email, + }; + if (options.phone) { + body.phone = options.phone as string; + } + if (options.name) { + body.name = options.name as string; + } + if (options.unsubscribedFromEmails) { + body.unsubscribed_from_emails = options.unsubscribedFromEmails as boolean; + } + if (options.updateLastRequestAt) { + body.update_last_request_at = options.updateLastRequestAt as boolean; + } + if (options.companies) { + const companies: ILeadCompany[] = []; + // @ts-ignore + options.companies.forEach( o => { + const company: ILeadCompany = {}; + company.company_id = o; + companies.push(company); + }); + body.companies = companies; + } + if (!jsonActive) { + const customAttributesValues = (this.getNodeParameter('customAttributesUi', i) as IDataObject).customAttributesValues as IDataObject[]; + if (customAttributesValues) { + const customAttributes = {}; + for (let i = 0; i < customAttributesValues.length; i++) { + // @ts-ignore + customAttributes[customAttributesValues[i].name] = customAttributesValues[i].value; + } + body.custom_attributes = customAttributes; + } + } else { + const customAttributesJson = validateJSON(this.getNodeParameter('customAttributesJson', i) as string); + if (customAttributesJson) { + body.custom_attributes = customAttributesJson; } - body.custom_attributes = customAttributes; } - } else { - const customAttributesJson = validateJSON(this.getNodeParameter('customAttributesJson') as string); - if (customAttributesJson) { - body.custom_attributes = customAttributesJson; + try { + responseData = await intercomApiRequest.call(this, '/contacts', 'POST', body); + } catch (err) { + throw new Error(`Intercom Error: ${JSON.stringify(err)}`); } } - try { - response = await intercomApiRequest.call(this, '/contacts', 'POST', body); - } catch (err) { - throw new Error(`Intercom Error: ${JSON.stringify(err)}`); - } + } + if (Array.isArray(responseData)) { + returnData.push.apply(returnData, responseData as IDataObject[]); + } else { + returnData.push(responseData as IDataObject); } } - return { - json: response, - }; + return [this.helpers.returnJsonArray(returnData)]; } } From 503baf82f7b089ddaf5aabaab809798298495faa Mon Sep 17 00:00:00 2001 From: Ricardo Espinoza Date: Wed, 20 Nov 2019 09:45:58 -0500 Subject: [PATCH 06/10] :sparkles: update lead done --- .../nodes/Intercom/Intercom.node.ts | 14 +++- .../nodes/Intercom/LeadDescription.ts | 79 ++++++++++++++++++- .../nodes/Intercom/LeadInterface.ts | 2 + 3 files changed, 90 insertions(+), 5 deletions(-) diff --git a/packages/nodes-base/nodes/Intercom/Intercom.node.ts b/packages/nodes-base/nodes/Intercom/Intercom.node.ts index ea635e22b7..58fe5ebe94 100644 --- a/packages/nodes-base/nodes/Intercom/Intercom.node.ts +++ b/packages/nodes-base/nodes/Intercom/Intercom.node.ts @@ -97,9 +97,9 @@ export class Intercom implements INodeType { let responseData; for (let i = 0; i < length; i++) { const resource = this.getNodeParameter('resource', 0) as string; - const opeation = this.getNodeParameter('operation', 0) as string; + const operation = this.getNodeParameter('operation', 0) as string; if (resource === 'lead') { - if (opeation === 'create') { + if (operation === 'create' || operation === 'update') { const email = this.getNodeParameter('email', i) as string; const options = this.getNodeParameter('options', i) as IDataObject; const jsonActive = this.getNodeParameter('jsonParameters', i) as boolean; @@ -144,6 +144,16 @@ export class Intercom implements INodeType { body.custom_attributes = customAttributesJson; } } + if (operation === 'update') { + const updateBy = this.getNodeParameter('updateBy', 0) as string; + const value = this.getNodeParameter('value', i) as string; + if (updateBy === 'userId') { + body.user_id = value; + } + if (updateBy === 'id') { + body.id = value; + } + } try { responseData = await intercomApiRequest.call(this, '/contacts', 'POST', body); } catch (err) { diff --git a/packages/nodes-base/nodes/Intercom/LeadDescription.ts b/packages/nodes-base/nodes/Intercom/LeadDescription.ts index 44dc94b594..5e5f53bd01 100644 --- a/packages/nodes-base/nodes/Intercom/LeadDescription.ts +++ b/packages/nodes-base/nodes/Intercom/LeadDescription.ts @@ -18,6 +18,11 @@ export const leadOpeations = [ value: 'create', description: 'Create a new lead', }, + { + name: 'Update', + value: 'update', + description: 'Update a new lead', + }, ], default: '', description: 'The operation to perform.', @@ -25,6 +30,55 @@ export const leadOpeations = [ ] as INodeProperties[]; export const leadFields = [ + { + displayName: 'Update By', + name: 'updateBy', + type: 'options', + displayOptions: { + show: { + resource: [ + 'lead', + ], + operation: [ + 'update', + ], + }, + }, + options: [ + { + name: 'User Id', + value: 'userId', + default: '', + description: 'Automatically generated identifier for the Lead', + }, + { + name: 'Id', + value: 'id', + default: '', + description: 'The Intercom defined id representing the Lead', + }, + ], + default: '', + description: 'Update by', + }, + { + displayName: 'Value', + name: 'value', + type: 'string', + default: '', + required: true, + displayOptions: { + show: { + resource: [ + 'lead', + ], + operation: [ + 'update', + ], + }, + }, + description: 'Update by value', + }, { displayName: 'Email', name: 'email', @@ -43,6 +97,24 @@ export const leadFields = [ }, description: 'The email of the user.', }, + { + displayName: 'Email', + name: 'email', + type: 'string', + default: '', + required: false, + displayOptions: { + show: { + resource: [ + 'lead', + ], + operation: [ + 'update', + ], + }, + }, + description: 'The email of the user.', + }, { displayName: 'JSON Parameters', name: 'jsonParameters', @@ -53,6 +125,7 @@ export const leadFields = [ show: { operation: [ 'create', + 'update', ], resource: [ 'lead' @@ -70,6 +143,7 @@ export const leadFields = [ show: { operation: [ 'create', + 'update', ], resource: [ 'lead' @@ -82,7 +156,6 @@ export const leadFields = [ name: 'phone', type: 'string', default: '', - required: false, description: 'The phone number of the user', }, { @@ -107,7 +180,6 @@ export const leadFields = [ type: 'boolean', default: false, options: [], - required: false, description: `A boolean value, which if true, instructs Intercom to update the users' last_request_at value to the current API service time in UTC. default value if not sent is false.`, }, { @@ -118,7 +190,6 @@ export const leadFields = [ loadOptionsMethod: 'getCompanies', }, default: [], - required: false, description: 'Identifies the companies this user belongs to.', }, ] @@ -138,6 +209,7 @@ export const leadFields = [ ], operation: [ 'create', + 'update', ], jsonParameters: [ true, @@ -164,6 +236,7 @@ export const leadFields = [ ], operation: [ 'create', + 'update', ], jsonParameters: [ false, diff --git a/packages/nodes-base/nodes/Intercom/LeadInterface.ts b/packages/nodes-base/nodes/Intercom/LeadInterface.ts index 480407bafb..b7e4f9a000 100644 --- a/packages/nodes-base/nodes/Intercom/LeadInterface.ts +++ b/packages/nodes-base/nodes/Intercom/LeadInterface.ts @@ -5,6 +5,8 @@ export interface ILeadCompany { } export interface ILead { + user_id?: string; + id?: string; email: string; phone?: string; name?: string; From 1b111d4abae7ae31bf4806d189aedf1793e532e3 Mon Sep 17 00:00:00 2001 From: Ricardo Espinoza Date: Thu, 21 Nov 2019 12:39:04 -0500 Subject: [PATCH 07/10] :sparkles: done --- .../nodes/Intercom/CompanyDescription.ts | 402 ++++++++++++++ .../nodes/Intercom/CompanyInteface.ts | 13 + .../nodes/Intercom/GenericFunctions.ts | 1 - .../nodes/Intercom/Intercom.node.ts | 379 ++++++++++++- .../nodes/Intercom/LeadDescription.ts | 251 ++++++++- .../nodes/Intercom/LeadInterface.ts | 13 +- .../nodes/Intercom/UserDescription.ts | 514 ++++++++++++++++++ .../nodes/Intercom/UserInterface.ts | 32 ++ 8 files changed, 1593 insertions(+), 12 deletions(-) create mode 100644 packages/nodes-base/nodes/Intercom/CompanyDescription.ts create mode 100644 packages/nodes-base/nodes/Intercom/CompanyInteface.ts create mode 100644 packages/nodes-base/nodes/Intercom/UserDescription.ts create mode 100644 packages/nodes-base/nodes/Intercom/UserInterface.ts diff --git a/packages/nodes-base/nodes/Intercom/CompanyDescription.ts b/packages/nodes-base/nodes/Intercom/CompanyDescription.ts new file mode 100644 index 0000000000..fd95ce07d7 --- /dev/null +++ b/packages/nodes-base/nodes/Intercom/CompanyDescription.ts @@ -0,0 +1,402 @@ +import { INodeProperties } from "n8n-workflow"; + +export const companyOpeations = [ + { + displayName: 'Operation', + name: 'operation', + type: 'options', + displayOptions: { + show: { + resource: [ + 'company', + ], + }, + }, + options: [ + { + name: 'Create', + value: 'create', + description: 'Create a new company', + }, + { + name: 'Update', + value: 'update', + description: 'Update a company', + }, + { + name: 'View', + value: 'view', + description: 'View a company', + }, + { + name: 'List', + value: 'list', + description: 'List companies', + }, + { + name: 'Company Users', + value: 'companyUsers', + description: `List company's users`, + }, + ], + default: '', + description: 'The operation to perform.', + }, +] as INodeProperties[]; + +export const companyFields = [ + +/* -------------------------------------------------------------------------- */ +/* company:companyUsers */ +/* -------------------------------------------------------------------------- */ + + { + displayName: 'List By', + name: 'listBy', + type: 'options', + displayOptions: { + show: { + resource: [ + 'company', + ], + operation: [ + 'companyUsers', + ], + }, + }, + options: [ + { + name: 'ID', + value: 'id', + default: '', + description: 'The Intercom defined id representing the company', + }, + { + name: 'Company ID', + value: 'companyId', + default: '', + description: 'The company_id you have given to the company', + }, + ], + default: '', + description: 'List by' + }, + { + displayName: 'Value', + name: 'value', + type: 'string', + default: '', + required: true, + displayOptions: { + show: { + resource: [ + 'company', + ], + operation: [ + 'companyUsers', + ], + }, + }, + description: 'View by value', + }, +/* -------------------------------------------------------------------------- */ +/* company:list */ +/* -------------------------------------------------------------------------- */ + + { + displayName: 'List by', + name: 'listBy', + type: 'options', + displayOptions: { + show: { + resource: [ + 'company', + ], + operation: [ + 'list', + ], + }, + }, + options: [ + { + name: 'Segment ID', + value: 'segmentId', + default: '', + description: 'Segment representing the Lead', + }, + { + name: 'Tag ID', + value: 'tagId', + default: '', + description: 'Tag representing the Lead', + }, + { + name: 'All', + value: 'all', + default: '', + description: 'List all users', + }, + ], + default: '', + description: 'List by' + }, + { + displayName: 'Value', + name: 'value', + type: 'string', + default: '', + required: true, + displayOptions: { + show: { + resource: [ + 'company', + ], + operation: [ + 'list', + ], + }, + hide: { + listBy: [ + 'all' + ] + } + }, + description: 'list by value', + }, + +/* -------------------------------------------------------------------------- */ +/* company:view */ +/* -------------------------------------------------------------------------- */ + + { + displayName: 'View By', + name: 'viewBy', + type: 'options', + displayOptions: { + show: { + resource: [ + 'company', + ], + operation: [ + 'view', + ], + }, + }, + options: [ + { + name: 'ID', + value: 'id', + default: '', + description: 'The Intercom defined id representing the company', + }, + { + name: 'Company ID', + value: 'companyId', + default: '', + description: 'The company_id you have given to the company', + }, + { + name: 'Name', + value: 'name', + default: '', + description: 'The name of the company', + }, + ], + default: '', + description: 'View by' + }, + { + displayName: 'Value', + name: 'value', + type: 'string', + default: '', + required: true, + displayOptions: { + show: { + resource: [ + 'company', + ], + operation: [ + 'view', + ], + }, + }, + description: 'View by value', + }, + +/* -------------------------------------------------------------------------- */ +/* company:create/update */ +/* -------------------------------------------------------------------------- */ + + { + displayName: 'Company Id', + name: 'companyId', + type: 'string', + default: '', + displayOptions: { + show: { + resource: [ + 'company', + ], + operation: [ + 'create', + 'update' + ], + }, + }, + description: 'The company id you have defined for the company', + }, + { + displayName: 'JSON Parameters', + name: 'jsonParameters', + type: 'boolean', + default: false, + description: '', + displayOptions: { + show: { + operation: [ + 'create', + 'update', + ], + resource: [ + 'company' + ], + }, + }, + }, + { + displayName: 'Options', + name: 'options', + type: 'collection', + placeholder: 'Add Option', + default: {}, + displayOptions: { + show: { + operation: [ + 'create', + 'update', + ], + resource: [ + 'company' + ], + }, + }, + options: [ + { + displayName: 'Monthly Spend', + name: 'monthlySpend', + type: 'string', + default: '', + description: 'The phone number of the user', + }, + { + displayName: 'Name', + name: 'name', + type: 'string', + default: '', + placeholder: '', + description: 'Name of the user', + }, + { + displayName: 'Plan', + name: 'plan', + type: 'string', + default: '', + placeholder: '', + description: 'The name of the plan you have associated with the company', + }, + { + displayName: 'Size', + name: 'size', + type: 'number', + default: '', + description: 'The number of employees in this company', + }, + { + displayName: 'Website', + name: 'website', + type: 'string', + default: '', + description: `The URL for this company's website. Please note that the value specified here is not validated. Accepts any string.`, + }, + { + displayName: 'Industry', + name: 'industry', + type: 'string', + description: 'The industry that this company operates in', + }, + ] + }, + { + displayName: 'Custom Attributes', + name: 'customAttributesJson', + type: 'json', + required: false, + typeOptions: { + alwaysOpenEditWindow: true, + }, + displayOptions: { + show: { + resource: [ + 'company', + ], + operation: [ + 'create', + 'update', + ], + jsonParameters: [ + true, + ], + }, + }, + default: '', + description: 'A hash of key/value pairs to represent custom data you want to attribute to a user.', + }, + { + displayName: 'Custom Attributes', + name: 'customAttributesUi', + type: 'fixedCollection', + default: '', + placeholder: 'Add Attribute', + typeOptions: { + multipleValues: true, + }, + required: false, + displayOptions: { + show: { + resource: [ + 'company', + ], + operation: [ + 'create', + 'update', + ], + jsonParameters: [ + false, + ], + }, + }, + options: [ + { + name: 'customAttributesValues', + displayName: 'Attributes', + values: [ + { + displayName: 'Name', + name: 'name', + type: 'string', + default: '', + }, + { + displayName: 'Value', + name: 'value', + type: 'string', + default: '', + }, + ], + } + ], + description: 'A hash of key/value pairs to represent custom data you want to attribute to a user.', + }, +] as INodeProperties[]; + diff --git a/packages/nodes-base/nodes/Intercom/CompanyInteface.ts b/packages/nodes-base/nodes/Intercom/CompanyInteface.ts new file mode 100644 index 0000000000..bffa553341 --- /dev/null +++ b/packages/nodes-base/nodes/Intercom/CompanyInteface.ts @@ -0,0 +1,13 @@ +import { IDataObject } from "n8n-workflow"; + +export interface ICompany { + remote_created_at?: string; + company_id?: string; + name?: string; + monthly_spend?: number; + plan?: string; + size?: number; + website?: string; + industry?: string; + custom_attributes?: IDataObject; +} diff --git a/packages/nodes-base/nodes/Intercom/GenericFunctions.ts b/packages/nodes-base/nodes/Intercom/GenericFunctions.ts index 8b32b726be..2c8df9962d 100644 --- a/packages/nodes-base/nodes/Intercom/GenericFunctions.ts +++ b/packages/nodes-base/nodes/Intercom/GenericFunctions.ts @@ -9,7 +9,6 @@ import { export async function intercomApiRequest(this: IHookFunctions | IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions, resource: string, method: string, body: any = {}, headers?: object): Promise { // tslint:disable-line:no-any const credentials = this.getCredentials('intercomApi'); - if (credentials === undefined) { throw new Error('No credentials got returned!'); } diff --git a/packages/nodes-base/nodes/Intercom/Intercom.node.ts b/packages/nodes-base/nodes/Intercom/Intercom.node.ts index 58fe5ebe94..d5bc587ff6 100644 --- a/packages/nodes-base/nodes/Intercom/Intercom.node.ts +++ b/packages/nodes-base/nodes/Intercom/Intercom.node.ts @@ -19,11 +19,15 @@ import { } from './GenericFunctions'; import { ILead, - ILeadCompany + ILeadCompany, + IAvatar, } from './LeadInterface'; +import { userOpeations, userFields } from './UserDescription'; +import { IUser, IUserCompany } from './UserInterface'; +import { companyOpeations, companyFields } from './CompanyDescription'; +import { ICompany } from './CompanyInteface'; export class Intercom implements INodeType { - description: INodeTypeDescription = { displayName: 'Intercom', name: 'intercom', @@ -50,17 +54,31 @@ export class Intercom implements INodeType { name: 'resource', type: 'options', options: [ + { + name: 'User', + value: 'user', + description: 'The Users resource is the primary way of interacting with Intercom', + }, { name: 'Lead', value: 'lead', - description: '', + description: 'Leads are useful for representing logged-out users of your application.', + }, + { + name: 'Company', + value: 'company', + description: 'Companies allow you to represent commercial organizations using your product.', }, ], default: '', description: 'Resource to consume.', }, ...leadOpeations, + ...userOpeations, + ...companyOpeations, + ...userFields, ...leadFields, + ...companyFields, ], }; @@ -86,7 +104,7 @@ export class Intercom implements INodeType { }); } return returnData; - } + }, }, }; @@ -98,14 +116,16 @@ export class Intercom implements INodeType { for (let i = 0; i < length; i++) { const resource = this.getNodeParameter('resource', 0) as string; const operation = this.getNodeParameter('operation', 0) as string; + //https://developers.intercom.com/intercom-api-reference/reference#leads if (resource === 'lead') { if (operation === 'create' || operation === 'update') { const email = this.getNodeParameter('email', i) as string; const options = this.getNodeParameter('options', i) as IDataObject; const jsonActive = this.getNodeParameter('jsonParameters', i) as boolean; - const body: ILead = { - email, - }; + const body: ILead = {}; + if (email) { + body.email = this.getNodeParameter('email', i) as string; + } if (options.phone) { body.phone = options.phone as string; } @@ -118,6 +138,28 @@ export class Intercom implements INodeType { if (options.updateLastRequestAt) { body.update_last_request_at = options.updateLastRequestAt as boolean; } + if (options.utmSource) { + body.utm_source = options.utmSource as string; + } + if (options.utmMedium) { + body.utm_medium = options.utmMedium as string; + } + if (options.utmCampaign) { + body.utm_campaign = options.utmCampaign as string; + } + if (options.utmTerm) { + body.utm_term = options.utmTerm as string; + } + if (options.utmContent) { + body.utm_content = options.utmContent as string; + } + if(options.avatar) { + const avatar: IAvatar = { + type: 'avatar', + image_url: options.avatar as string, + }; + body.avatar = avatar; + } if (options.companies) { const companies: ILeadCompany[] = []; // @ts-ignore @@ -128,6 +170,18 @@ export class Intercom implements INodeType { }); body.companies = companies; } + // console.log(options.segments) + // if (options.segments) { + // const segments: ISegment[] = []; + // // @ts-ignore + // options.segments.forEach( o => { + // const segment: ISegment = {}; + // segment.id = o; + // segment.type = 'segment'; + // segments.push(segment); + // }); + // body.segments = { segments }; + // } if (!jsonActive) { const customAttributesValues = (this.getNodeParameter('customAttributesUi', i) as IDataObject).customAttributesValues as IDataObject[]; if (customAttributesValues) { @@ -138,7 +192,25 @@ export class Intercom implements INodeType { } body.custom_attributes = customAttributes; } + // const socialProfilesValues = (this.getNodeParameter('socialProfilesUi', i) as IDataObject).socialProfilesValues as IDataObject[]; + // if (socialProfilesValues && socialProfilesValues.length > 0) { + // const socialProfiles: ISocialProfile[] = []; + // socialProfilesValues.forEach( o => { + // const socialProfile: ISocialProfile = {}; + // socialProfile.name = o.name as string; + // socialProfile.type = 'social_profile'; + // socialProfile.username = o.username as string; + // socialProfile.url = o.url as string; + // socialProfile.id = o.id as string; + // socialProfiles.push(socialProfile); + // }); + // body.social_profiles = socialProfiles; + // } } else { + // const socialProfilesJson = validateJSON(this.getNodeParameter('socialProfilesJson', i) as string); + // if (socialProfilesJson) { + // body.social_profiles = socialProfilesJson; + // } const customAttributesJson = validateJSON(this.getNodeParameter('customAttributesJson', i) as string); if (customAttributesJson) { body.custom_attributes = customAttributesJson; @@ -160,6 +232,299 @@ export class Intercom implements INodeType { throw new Error(`Intercom Error: ${JSON.stringify(err)}`); } } + if (operation === 'view') { + let query = ''; + const viewBy = this.getNodeParameter('viewBy', 0) as string; + const value = this.getNodeParameter('value', i) as string; + if (viewBy === 'userId') { + query = `user_id=${value}`; + } + if (viewBy === 'phone') { + query = `phone=${value}`; + } + try { + if (viewBy === 'id') { + responseData = await intercomApiRequest.call(this, `/contacts/${value}`, 'GET'); + } else { + responseData = await intercomApiRequest.call(this, `/contacts?${query}`, 'GET'); + } + } catch (err) { + throw new Error(`Intercom Error: ${JSON.stringify(err)}`); + } + } + if (operation === 'list') { + let query = ''; + const listBy = this.getNodeParameter('listBy', 0) as string; + if (listBy === 'email') { + query = `email=${this.getNodeParameter('value', i) as string}`; + } + if (listBy === 'phone') { + query = `phone=${this.getNodeParameter('value', i) as string}`; + } + try { + responseData = await intercomApiRequest.call(this, `/contacts?${query}`, 'GET'); + } catch (err) { + throw new Error(`Intercom Error: ${JSON.stringify(err)}`); + } + } + if (operation === 'delete') { + const deleteBy = this.getNodeParameter('deleteBy', 0) as string; + const value = this.getNodeParameter('value', i) as string; + try { + if (deleteBy === 'id') { + responseData = await intercomApiRequest.call(this, `/contacts/${value}`, 'DELETE'); + } else { + responseData = await intercomApiRequest.call(this, `/contacts?user_id=${value}`, 'DELETE'); + } + } catch (err) { + throw new Error(`Intercom Error: ${JSON.stringify(err)}`); + } + } + } + //https://developers.intercom.com/intercom-api-reference/reference#users + if (resource === 'user') { + if (operation === 'create' || operation === 'update') { + const id = this.getNodeParameter('id', i) as string; + const options = this.getNodeParameter('options', i) as IDataObject; + const jsonActive = this.getNodeParameter('jsonParameters', i) as boolean; + const body: IUser = {}; + if (id === 'email') { + body.email = this.getNodeParameter('idValue', i) as string; + } + if (id === 'userId') { + body.user_id = this.getNodeParameter('idValue', i) as string; + } + if (options.phone) { + body.phone = options.phone as string; + } + if (options.name) { + body.name = options.name as string; + } + if (options.unsubscribedFromEmails) { + body.unsubscribed_from_emails = options.unsubscribedFromEmails as boolean; + } + if (options.updateLastRequestAt) { + body.update_last_request_at = options.updateLastRequestAt as boolean; + } + if (options.sessionCount) { + body.session_count = options.sessionCount as number; + } + if(options.avatar) { + const avatar: IAvatar = { + type: 'avatar', + image_url: options.avatar as string, + }; + body.avatar = avatar; + } + if (options.utmSource) { + body.utm_source = options.utmSource as string; + } + if (options.utmMedium) { + body.utm_medium = options.utmMedium as string; + } + if (options.utmCampaign) { + body.utm_campaign = options.utmCampaign as string; + } + if (options.utmTerm) { + body.utm_term = options.utmTerm as string; + } + if (options.utmContent) { + body.utm_content = options.utmContent as string; + } + if (options.companies) { + const companies: IUserCompany[] = []; + // @ts-ignore + options.companies.forEach( o => { + const company: IUserCompany = {}; + company.company_id = o; + companies.push(company); + }); + body.companies = companies; + } + if (options.sessionCount) { + body.session_count = options.sessionCount as number; + } + if (!jsonActive) { + const customAttributesValues = (this.getNodeParameter('customAttributesUi', i) as IDataObject).customAttributesValues as IDataObject[]; + if (customAttributesValues) { + const customAttributes = {}; + for (let i = 0; i < customAttributesValues.length; i++) { + // @ts-ignore + customAttributes[customAttributesValues[i].name] = customAttributesValues[i].value; + } + body.custom_attributes = customAttributes; + } + } else { + const customAttributesJson = validateJSON(this.getNodeParameter('customAttributesJson', i) as string); + if (customAttributesJson) { + body.custom_attributes = customAttributesJson; + } + } + if (operation === 'update') { + const id = this.getNodeParameter('id', i) as string; + const email = this.getNodeParameter('email', i) as string; + const userId = this.getNodeParameter('userId', i) as string; + if (id) { + body.id = id; + } + if (email) { + body.email = email; + } + if (userId) { + body.user_id = userId; + } + } + try { + responseData = await intercomApiRequest.call(this, '/users', 'POST', body); + } catch (err) { + throw new Error(`Intercom Error: ${JSON.stringify(err)}`); + } + } + if (operation === 'view') { + let query = ''; + const viewBy = this.getNodeParameter('viewBy', 0) as string; + const value = this.getNodeParameter('value', i) as string; + if (viewBy === 'userId') { + query = `user_id=${value}`; + } + try { + if (viewBy === 'id') { + responseData = await intercomApiRequest.call(this, `/users/${value}`, 'GET'); + } else { + responseData = await intercomApiRequest.call(this, `/users?${query}`, 'GET'); + } + } catch (err) { + throw new Error(`Intercom Error: ${JSON.stringify(err)}`); + } + } + if (operation === 'list') { + let query = ''; + const listBy = this.getNodeParameter('listBy', 0) as string; + if (listBy === 'email') { + query = `email=${this.getNodeParameter('value', i) as string}`; + } + if (listBy === 'segmentId') { + query = `segment_id=${this.getNodeParameter('value', i) as string}`; + } + if (listBy === 'tagId') { + query = `tag_id=${this.getNodeParameter('value', i) as string}`; + } + try { + responseData = await intercomApiRequest.call(this, `/users?${query}`, 'GET'); + } catch (err) { + throw new Error(`Intercom Error: ${JSON.stringify(err)}`); + } + } + if (operation === 'delete') { + const id = this.getNodeParameter('id', i) as string; + try { + responseData = await intercomApiRequest.call(this, `/users/${id}`, 'DELETE'); + } catch (err) { + throw new Error(`Intercom Error: ${JSON.stringify(err)}`); + } + } + } + //https://developers.intercom.com/intercom-api-reference/reference#companies + if (resource === 'company') { + if (operation === 'create' || operation === 'update') { + const id = this.getNodeParameter('companyId', i) as string; + const options = this.getNodeParameter('options', i) as IDataObject; + const jsonActive = this.getNodeParameter('jsonParameters', i) as boolean; + const body: ICompany = { + company_id: id, + }; + if (options.monthlySpend) { + body.monthly_spend = options.monthlySpend as number; + } + if (options.name) { + body.name = options.name as string; + } + if (options.plan) { + body.plan = options.plan as string; + } + if (options.size) { + body.size = options.size as number; + } + if (options.website) { + body.website = options.website as string; + } + if (options.industry) { + body.industry = options.industry as string; + } + if (!jsonActive) { + const customAttributesValues = (this.getNodeParameter('customAttributesUi', i) as IDataObject).customAttributesValues as IDataObject[]; + if (customAttributesValues) { + const customAttributes = {}; + for (let i = 0; i < customAttributesValues.length; i++) { + // @ts-ignore + customAttributes[customAttributesValues[i].name] = customAttributesValues[i].value; + } + body.custom_attributes = customAttributes; + } + } else { + const customAttributesJson = validateJSON(this.getNodeParameter('customAttributesJson', i) as string); + if (customAttributesJson) { + body.custom_attributes = customAttributesJson; + } + } + try { + responseData = await intercomApiRequest.call(this, '/companies', 'POST', body); + } catch (err) { + throw new Error(`Intercom Error: ${JSON.stringify(err)}`); + } + } + if (operation === 'view') { + let query = ''; + const viewBy = this.getNodeParameter('viewBy', 0) as string; + const value = this.getNodeParameter('value', i) as string; + if (viewBy === 'companyId') { + query = `company_id=${value}`; + } + if (viewBy === 'name') { + query = `name=${value}`; + } + try { + if (viewBy === 'id') { + responseData = await intercomApiRequest.call(this, `/companies/${value}`, 'GET'); + } else { + responseData = await intercomApiRequest.call(this, `/companies?${query}`, 'GET'); + } + } catch (err) { + throw new Error(`Intercom Error: ${JSON.stringify(err)}`); + } + } + if (operation === 'list') { + let query = ''; + const listBy = this.getNodeParameter('listBy', 0) as string; + if (listBy === 'segmentId') { + query = `segment_id=${this.getNodeParameter('value', i) as string}`; + } + if (listBy === 'tagId') { + query = `tag_id=${this.getNodeParameter('value', i) as string}`; + } + try { + responseData = await intercomApiRequest.call(this, `/companies?${query}`, 'GET'); + } catch (err) { + throw new Error(`Intercom Error: ${JSON.stringify(err)}`); + } + } + if (operation === 'companyUsers') { + let query = ''; + const listBy = this.getNodeParameter('listBy', 0) as string; + const value = this.getNodeParameter('value', i) as string; + if (listBy === 'companyId') { + query = `company_id=${value}`; + } + try { + if (listBy === 'id') { + responseData = await intercomApiRequest.call(this, `/companies/${value}/users`, 'GET'); + } else { + responseData = await intercomApiRequest.call(this, `/companies?${query}&type=users`, 'GET'); + } + } catch (err) { + throw new Error(`Intercom Error: ${JSON.stringify(err)}`); + } + } } if (Array.isArray(responseData)) { returnData.push.apply(returnData, responseData as IDataObject[]); diff --git a/packages/nodes-base/nodes/Intercom/LeadDescription.ts b/packages/nodes-base/nodes/Intercom/LeadDescription.ts index 5e5f53bd01..03bfd1f299 100644 --- a/packages/nodes-base/nodes/Intercom/LeadDescription.ts +++ b/packages/nodes-base/nodes/Intercom/LeadDescription.ts @@ -21,8 +21,23 @@ export const leadOpeations = [ { name: 'Update', value: 'update', - description: 'Update a new lead', + description: 'Update new lead', }, + { + name: 'View', + value: 'view', + description: 'View a lead', + }, + { + name: 'List', + value: 'list', + description: 'List leads', + }, + { + name: 'Delete', + value: 'delete', + description: 'Delete a lead', + } ], default: '', description: 'The operation to perform.', @@ -30,6 +45,189 @@ export const leadOpeations = [ ] as INodeProperties[]; export const leadFields = [ + +/* -------------------------------------------------------------------------- */ +/* lead:delete */ +/* -------------------------------------------------------------------------- */ + + { + displayName: 'Delete By', + name: 'deleteBy', + type: 'options', + displayOptions: { + show: { + resource: [ + 'lead', + ], + operation: [ + 'delete', + ], + }, + }, + options: [ + { + name: 'ID', + value: 'id', + default: '', + description: 'The Intercom defined id representing the Lead', + }, + { + name: 'User ID', + value: 'userId', + default: '', + description: 'Automatically generated identifier for the Lead', + }, + ], + default: '', + description: 'Delete by' + }, + { + displayName: 'Value', + name: 'value', + type: 'string', + required: true, + displayOptions: { + show: { + resource: [ + 'lead', + ], + operation: [ + 'delete', + ], + }, + }, + description: 'Delete by value', + }, + +/* -------------------------------------------------------------------------- */ +/* lead:view */ +/* -------------------------------------------------------------------------- */ + + { + displayName: 'View By', + name: 'viewBy', + type: 'options', + displayOptions: { + show: { + resource: [ + 'lead', + ], + operation: [ + 'view', + ], + }, + }, + options: [ + { + name: 'ID', + value: 'id', + default: '', + description: 'The Intercom defined id representing the Lead', + }, + { + name: 'User ID', + value: 'userId', + default: '', + description: 'Automatically generated identifier for the Lead', + }, + { + name: 'Phone', + value: 'phone', + default: '', + description: 'Phone representing the Lead', + }, + ], + default: '', + description: 'View by' + }, + { + displayName: 'Value', + name: 'value', + type: 'string', + default: '', + required: true, + displayOptions: { + show: { + resource: [ + 'lead', + ], + operation: [ + 'view', + ], + }, + }, + description: 'View by value', + }, + +/* -------------------------------------------------------------------------- */ +/* lead:list */ +/* -------------------------------------------------------------------------- */ + + { + displayName: 'List by', + name: 'listBy', + type: 'options', + displayOptions: { + show: { + resource: [ + 'lead', + ], + operation: [ + 'list', + ], + }, + }, + options: [ + { + name: 'Email', + value: 'email', + default: '', + description: 'Email representing the Lead', + }, + { + name: 'Phone', + value: 'phone', + default: '', + description: 'Phone representing the Lead', + }, + { + name: 'All', + value: 'all', + default: '', + description: 'List all leads', + }, + ], + default: '', + description: 'List by' + }, + { + displayName: 'Value', + name: 'value', + type: 'string', + default: '', + required: true, + displayOptions: { + show: { + resource: [ + 'lead', + ], + operation: [ + 'list', + ], + }, + hide: { + listBy: [ + 'all' + ] + } + }, + description: 'list by value', + }, + +/* -------------------------------------------------------------------------- */ +/* lead:update */ +/* -------------------------------------------------------------------------- */ + { displayName: 'Update By', name: 'updateBy', @@ -46,13 +244,13 @@ export const leadFields = [ }, options: [ { - name: 'User Id', + name: 'User ID', value: 'userId', default: '', description: 'Automatically generated identifier for the Lead', }, { - name: 'Id', + name: 'ID', value: 'id', default: '', description: 'The Intercom defined id representing the Lead', @@ -79,6 +277,11 @@ export const leadFields = [ }, description: 'Update by value', }, + +/* -------------------------------------------------------------------------- */ +/* lead:create */ +/* -------------------------------------------------------------------------- */ + { displayName: 'Email', name: 'email', @@ -192,6 +395,48 @@ export const leadFields = [ default: [], description: 'Identifies the companies this user belongs to.', }, + { + displayName: 'Avatar', + name: 'avatar', + type: 'string', + default: '', + description: 'An avatar image URL. note: the image url needs to be https.', + }, + { + displayName: 'UTM Source', + name: 'utmSource', + type: 'string', + default: '', + description: 'An avatar image URL. note: the image url needs to be https.', + }, + { + displayName: 'UTM Medium', + name: 'utmMedium', + type: 'string', + default: '', + description: 'Identifies what type of link was used', + }, + { + displayName: 'UTM Campaign', + name: 'utmCampaign', + type: 'string', + default: '', + description: 'Identifies a specific product promotion or strategic campaign', + }, + { + displayName: 'UTM Term', + name: 'utmTerm', + type: 'string', + default: '', + description: 'Identifies search terms', + }, + { + displayName: 'UTM Content', + name: 'utmContent', + type: 'string', + default: '', + description: 'Identifies what specifically was clicked to bring the user to the site', + }, ] }, { diff --git a/packages/nodes-base/nodes/Intercom/LeadInterface.ts b/packages/nodes-base/nodes/Intercom/LeadInterface.ts index b7e4f9a000..6a716577fa 100644 --- a/packages/nodes-base/nodes/Intercom/LeadInterface.ts +++ b/packages/nodes-base/nodes/Intercom/LeadInterface.ts @@ -4,10 +4,15 @@ export interface ILeadCompany { company_id?: string; } +export interface IAvatar { + type?: string; + image_url?: string; +} + export interface ILead { user_id?: string; id?: string; - email: string; + email?: string; phone?: string; name?: string; custom_attributes?: IDataObject; @@ -15,4 +20,10 @@ export interface ILead { last_request_at?: number; unsubscribed_from_emails?: boolean; update_last_request_at?: boolean; + avatar?: IAvatar; + utm_source?: string; + utm_medium?: string; + utm_campaign?: string; + utm_term?: string; + utm_content?: string; } diff --git a/packages/nodes-base/nodes/Intercom/UserDescription.ts b/packages/nodes-base/nodes/Intercom/UserDescription.ts new file mode 100644 index 0000000000..2f89ae3682 --- /dev/null +++ b/packages/nodes-base/nodes/Intercom/UserDescription.ts @@ -0,0 +1,514 @@ +import { INodeProperties } from "n8n-workflow"; + +export const userOpeations = [ + { + displayName: 'Operation', + name: 'operation', + type: 'options', + displayOptions: { + show: { + resource: [ + 'user', + ], + }, + }, + options: [ + { + name: 'Create', + value: 'create', + description: 'Create a new user', + }, + { + name: 'Update', + value: 'update', + description: 'Update a user', + }, + { + name: 'View', + value: 'view', + description: 'View a user', + }, + { + name: 'List', + value: 'list', + description: 'List users', + }, + { + name: 'Delete', + value: 'delete', + description: 'Delete a user', + } + ], + default: '', + description: 'The operation to perform.', + }, +] as INodeProperties[]; + +export const userFields = [ + +/* -------------------------------------------------------------------------- */ +/* user:delete */ +/* -------------------------------------------------------------------------- */ + + { + displayName: 'ID', + name: 'id', + type: 'string', + required: true, + displayOptions: { + show: { + resource: [ + 'user', + ], + operation: [ + 'delete', + ], + }, + }, + default: '', + description: 'The Intercom defined id representing the Lead', + }, + +/* -------------------------------------------------------------------------- */ +/* user:list */ +/* -------------------------------------------------------------------------- */ + + { + displayName: 'List by', + name: 'listBy', + type: 'options', + displayOptions: { + show: { + resource: [ + 'user', + ], + operation: [ + 'list', + ], + }, + }, + options: [ + { + name: 'Email', + value: 'email', + default: '', + description: 'Email representing the Lead', + }, + { + name: 'Segment ID', + value: 'segmentId', + default: '', + description: 'Segment representing the Lead', + }, + { + name: 'Tag ID', + value: 'tagId', + default: '', + description: 'Tag representing the Lead', + }, + { + name: 'Company ID', + value: 'companyId', + default: '', + description: 'Company representing the Lead', + }, + { + name: 'All', + value: 'all', + default: '', + description: 'List all users', + }, + ], + default: '', + description: 'List by' + }, + { + displayName: 'Value', + name: 'value', + type: 'string', + default: '', + required: true, + displayOptions: { + show: { + resource: [ + 'user', + ], + operation: [ + 'list', + ], + }, + hide: { + listBy: [ + 'all' + ] + } + }, + description: 'list by value', + }, + +/* -------------------------------------------------------------------------- */ +/* view:user */ +/* -------------------------------------------------------------------------- */ + + { + displayName: 'View By', + name: 'viewBy', + type: 'options', + displayOptions: { + show: { + resource: [ + 'user', + ], + operation: [ + 'view', + ], + }, + }, + options: [ + { + name: 'ID', + value: 'id', + default: '', + description: 'The Intercom defined id representing the Lead', + }, + { + name: 'User ID', + value: 'userId', + default: '', + description: 'Automatically generated identifier for the Lead', + }, + ], + default: '', + description: 'View by' + }, + { + displayName: 'Value', + name: 'value', + type: 'string', + default: '', + required: true, + displayOptions: { + show: { + resource: [ + 'user', + ], + operation: [ + 'view', + ], + }, + }, + description: 'View by value', + }, + +/* -------------------------------------------------------------------------- */ +/* user:update */ +/* -------------------------------------------------------------------------- */ + + { + displayName: 'Id', + name: 'id', + type: 'string', + default: '', + displayOptions: { + show: { + resource: [ + 'user', + ], + operation: [ + 'update', + ], + }, + }, + description: 'id is matched - the user_id and email will be updated if they are sent.', + }, + { + displayName: 'User Id', + name: 'userId', + type: 'string', + default: '', + displayOptions: { + show: { + resource: [ + 'user', + ], + operation: [ + 'update', + ], + }, + }, + description: 'user_id match - the email will be updated, the id is not updated.', + }, + { + displayName: 'Email', + name: 'email', + type: 'string', + default: '', + displayOptions: { + show: { + resource: [ + 'user', + ], + operation: [ + 'update', + ], + }, + }, + description: `email match where no user_id set on the matching user - the user_id will be set to the value sent in the request, the id is not updated. + email match where there is a user_id set on the matching user - a new unique record with new id will be created if a new value for user_id is sent in the request.`, + }, + +/* -------------------------------------------------------------------------- */ +/* user:create */ +/* -------------------------------------------------------------------------- */ + + { + displayName: 'Id', + name: 'id', + type: 'options', + displayOptions: { + show: { + resource: [ + 'user', + ], + operation: [ + 'create', + ], + }, + }, + options: [ + { + name: 'User Id', + value: 'userId', + default: '', + description: 'A unique string identifier for the user. It is required on creation if an email is not supplied.', + }, + { + name: 'Email', + value: 'email', + default: '', + description: `The user's email address. It is required on creation if a user_id is not supplied.`, + }, + ], + default: '', + description: 'Unique string identifier', + }, + { + displayName: 'Value', + name: 'idValue', + type: 'string', + default: '', + required: true, + displayOptions: { + show: { + resource: [ + 'user', + ], + operation: [ + 'create', + ], + }, + }, + description: 'Unique string identifier value', + }, + { + displayName: 'JSON Parameters', + name: 'jsonParameters', + type: 'boolean', + default: false, + description: '', + displayOptions: { + show: { + operation: [ + 'create', + 'update', + ], + resource: [ + 'user' + ], + }, + }, + }, + { + displayName: 'Options', + name: 'options', + type: 'collection', + placeholder: 'Add Option', + default: {}, + displayOptions: { + show: { + operation: [ + 'create', + 'update', + ], + resource: [ + 'user' + ], + }, + }, + options: [ + { + displayName: 'Phone', + name: 'phone', + type: 'string', + default: '', + description: 'The phone number of the user', + }, + { + displayName: 'Name', + name: 'name', + type: 'string', + default: '', + placeholder: '', + description: 'Name of the user', + }, + { + displayName: 'Unsubscribed From Emails', + name: 'unsubscribedFromEmails', + type: 'boolean', + default: '', + placeholder: '', + description: 'Whether the user is unsubscribed from emails', + }, + { + displayName: 'Update Last Request At', + name: 'updateLastRequestAt', + type: 'boolean', + default: false, + options: [], + description: `A boolean value, which if true, instructs Intercom to update the users' last_request_at value to the current API service time in UTC. default value if not sent is false.`, + }, + { + displayName: 'Session Count', + name: 'sessionCount', + type: 'number', + default: false, + options: [], + description: `How many sessions the user has recorded`, + }, + { + displayName: 'Companies', + name: 'companies', + type: 'multiOptions', + typeOptions: { + loadOptionsMethod: 'getCompanies', + }, + default: [], + description: 'Identifies the companies this user belongs to.', + }, + { + displayName: 'Avatar', + name: 'avatar', + type: 'string', + default: '', + description: 'An avatar image URL. note: the image url needs to be https.', + }, + { + displayName: 'UTM Source', + name: 'utmSource', + type: 'string', + default: '', + description: 'An avatar image URL. note: the image url needs to be https.', + }, + { + displayName: 'UTM Medium', + name: 'utmMedium', + type: 'string', + default: '', + description: 'Identifies what type of link was used', + }, + { + displayName: 'UTM Campaign', + name: 'utmCampaign', + type: 'string', + default: '', + description: 'Identifies a specific product promotion or strategic campaign', + }, + { + displayName: 'UTM Term', + name: 'utmTerm', + type: 'string', + default: '', + description: 'Identifies search terms', + }, + { + displayName: 'UTM Content', + name: 'utmContent', + type: 'string', + default: '', + description: 'Identifies what specifically was clicked to bring the user to the site', + }, + ] + }, + { + displayName: 'Custom Attributes', + name: 'customAttributesJson', + type: 'json', + required: false, + typeOptions: { + alwaysOpenEditWindow: true, + }, + displayOptions: { + show: { + resource: [ + 'user', + ], + operation: [ + 'create', + 'update', + ], + jsonParameters: [ + true, + ], + }, + }, + default: '', + description: 'A hash of key/value pairs to represent custom data you want to attribute to a user.', + }, + { + displayName: 'Custom Attributes', + name: 'customAttributesUi', + type: 'fixedCollection', + default: '', + placeholder: 'Add Attribute', + typeOptions: { + multipleValues: true, + }, + required: false, + displayOptions: { + show: { + resource: [ + 'user', + ], + operation: [ + 'create', + 'update', + ], + jsonParameters: [ + false, + ], + }, + }, + options: [ + { + name: 'customAttributesValues', + displayName: 'Attributes', + values: [ + { + displayName: 'Name', + name: 'name', + type: 'string', + default: '', + }, + { + displayName: 'Value', + name: 'value', + type: 'string', + default: '', + }, + ], + } + ], + description: 'A hash of key/value pairs to represent custom data you want to attribute to a user.', + }, +] as INodeProperties[]; + diff --git a/packages/nodes-base/nodes/Intercom/UserInterface.ts b/packages/nodes-base/nodes/Intercom/UserInterface.ts new file mode 100644 index 0000000000..802941af9f --- /dev/null +++ b/packages/nodes-base/nodes/Intercom/UserInterface.ts @@ -0,0 +1,32 @@ +import { IDataObject } from "n8n-workflow"; + +export interface IUserCompany { + company_id?: string; +} + +export interface IAvatar { + type?: string; + image_url?: string; +} + +export interface IUser { + user_id?: string; + id?: string; + email?: string; + phone?: string; + name?: string; + custom_attributes?: IDataObject; + companies?: IUserCompany[]; + last_request_at?: number; + signed_up_at?: string; + unsubscribed_from_emails?: boolean; + update_last_request_at?: boolean; + last_seen_user_agent?: boolean; + session_count?: number; + avatar?: IAvatar; + utm_source?: string; + utm_medium?: string; + utm_campaign?: string; + utm_term?: string; + utm_content?: string; +} From c91bc5679256e1330ef9684da38e16788756dc80 Mon Sep 17 00:00:00 2001 From: Ricardo Espinoza Date: Thu, 21 Nov 2019 12:52:57 -0500 Subject: [PATCH 08/10] renamed opeation --- .../nodes-base/nodes/Intercom/CompanyDescription.ts | 10 +++++----- packages/nodes-base/nodes/Intercom/Intercom.node.ts | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/nodes-base/nodes/Intercom/CompanyDescription.ts b/packages/nodes-base/nodes/Intercom/CompanyDescription.ts index fd95ce07d7..39d9ddf37f 100644 --- a/packages/nodes-base/nodes/Intercom/CompanyDescription.ts +++ b/packages/nodes-base/nodes/Intercom/CompanyDescription.ts @@ -34,8 +34,8 @@ export const companyOpeations = [ description: 'List companies', }, { - name: 'Company Users', - value: 'companyUsers', + name: 'Users', + value: 'users', description: `List company's users`, }, ], @@ -47,7 +47,7 @@ export const companyOpeations = [ export const companyFields = [ /* -------------------------------------------------------------------------- */ -/* company:companyUsers */ +/* company:users */ /* -------------------------------------------------------------------------- */ { @@ -60,7 +60,7 @@ export const companyFields = [ 'company', ], operation: [ - 'companyUsers', + 'users', ], }, }, @@ -93,7 +93,7 @@ export const companyFields = [ 'company', ], operation: [ - 'companyUsers', + 'users', ], }, }, diff --git a/packages/nodes-base/nodes/Intercom/Intercom.node.ts b/packages/nodes-base/nodes/Intercom/Intercom.node.ts index d5bc587ff6..7cdaec3833 100644 --- a/packages/nodes-base/nodes/Intercom/Intercom.node.ts +++ b/packages/nodes-base/nodes/Intercom/Intercom.node.ts @@ -508,7 +508,7 @@ export class Intercom implements INodeType { throw new Error(`Intercom Error: ${JSON.stringify(err)}`); } } - if (operation === 'companyUsers') { + if (operation === 'users') { let query = ''; const listBy = this.getNodeParameter('listBy', 0) as string; const value = this.getNodeParameter('value', i) as string; From 61d6ecb03d1fcdc49a2a4ffd8682913e14d01417 Mon Sep 17 00:00:00 2001 From: Ricardo Espinoza Date: Thu, 21 Nov 2019 12:57:37 -0500 Subject: [PATCH 09/10] :lipstick: removed comments --- .../nodes/Intercom/Intercom.node.ts | 30 ------------------- 1 file changed, 30 deletions(-) diff --git a/packages/nodes-base/nodes/Intercom/Intercom.node.ts b/packages/nodes-base/nodes/Intercom/Intercom.node.ts index 7cdaec3833..bb59d277f3 100644 --- a/packages/nodes-base/nodes/Intercom/Intercom.node.ts +++ b/packages/nodes-base/nodes/Intercom/Intercom.node.ts @@ -170,18 +170,6 @@ export class Intercom implements INodeType { }); body.companies = companies; } - // console.log(options.segments) - // if (options.segments) { - // const segments: ISegment[] = []; - // // @ts-ignore - // options.segments.forEach( o => { - // const segment: ISegment = {}; - // segment.id = o; - // segment.type = 'segment'; - // segments.push(segment); - // }); - // body.segments = { segments }; - // } if (!jsonActive) { const customAttributesValues = (this.getNodeParameter('customAttributesUi', i) as IDataObject).customAttributesValues as IDataObject[]; if (customAttributesValues) { @@ -192,25 +180,7 @@ export class Intercom implements INodeType { } body.custom_attributes = customAttributes; } - // const socialProfilesValues = (this.getNodeParameter('socialProfilesUi', i) as IDataObject).socialProfilesValues as IDataObject[]; - // if (socialProfilesValues && socialProfilesValues.length > 0) { - // const socialProfiles: ISocialProfile[] = []; - // socialProfilesValues.forEach( o => { - // const socialProfile: ISocialProfile = {}; - // socialProfile.name = o.name as string; - // socialProfile.type = 'social_profile'; - // socialProfile.username = o.username as string; - // socialProfile.url = o.url as string; - // socialProfile.id = o.id as string; - // socialProfiles.push(socialProfile); - // }); - // body.social_profiles = socialProfiles; - // } } else { - // const socialProfilesJson = validateJSON(this.getNodeParameter('socialProfilesJson', i) as string); - // if (socialProfilesJson) { - // body.social_profiles = socialProfilesJson; - // } const customAttributesJson = validateJSON(this.getNodeParameter('customAttributesJson', i) as string); if (customAttributesJson) { body.custom_attributes = customAttributesJson; From 9897a156caa5876f212f5acc701ecb96e24b43bf Mon Sep 17 00:00:00 2001 From: Jan Oberhauser Date: Fri, 22 Nov 2019 23:04:06 +0100 Subject: [PATCH 10/10] :zap: Some changes and fixes on Intercom-Node --- .../nodes/Intercom/CompanyDescription.ts | 177 ++++----- .../nodes/Intercom/GenericFunctions.ts | 45 ++- .../nodes/Intercom/Intercom.node.ts | 352 ++++++++++-------- .../nodes/Intercom/LeadDescription.ts | 283 +++++++------- .../nodes/Intercom/UserDescription.ts | 262 ++++++++----- 5 files changed, 624 insertions(+), 495 deletions(-) diff --git a/packages/nodes-base/nodes/Intercom/CompanyDescription.ts b/packages/nodes-base/nodes/Intercom/CompanyDescription.ts index 39d9ddf37f..df8239719f 100644 --- a/packages/nodes-base/nodes/Intercom/CompanyDescription.ts +++ b/packages/nodes-base/nodes/Intercom/CompanyDescription.ts @@ -1,6 +1,6 @@ import { INodeProperties } from "n8n-workflow"; -export const companyOpeations = [ +export const companyOperations = [ { displayName: 'Operation', name: 'operation', @@ -18,28 +18,28 @@ export const companyOpeations = [ value: 'create', description: 'Create a new company', }, + { + name: 'Get', + value: 'get', + description: 'Get data of a company', + }, + { + name: 'Get All', + value: 'getAll', + description: 'Get data of all companies', + }, { name: 'Update', value: 'update', description: 'Update a company', }, - { - name: 'View', - value: 'view', - description: 'View a company', - }, - { - name: 'List', - value: 'list', - description: 'List companies', - }, { name: 'Users', value: 'users', description: `List company's users`, }, ], - default: '', + default: 'create', description: 'The operation to perform.', }, ] as INodeProperties[]; @@ -68,18 +68,16 @@ export const companyFields = [ { name: 'ID', value: 'id', - default: '', description: 'The Intercom defined id representing the company', }, { name: 'Company ID', value: 'companyId', - default: '', description: 'The company_id you have given to the company', }, ], default: '', - description: 'List by' + description: 'List by', }, { displayName: 'Value', @@ -100,77 +98,91 @@ export const companyFields = [ description: 'View by value', }, /* -------------------------------------------------------------------------- */ -/* company:list */ +/* company:getAll */ /* -------------------------------------------------------------------------- */ { - displayName: 'List by', - name: 'listBy', - type: 'options', + displayName: 'Return All', + name: 'returnAll', + type: 'boolean', displayOptions: { show: { resource: [ 'company', ], operation: [ - 'list', + 'getAll', + ], + }, + }, + default: false, + description: 'If all results should be returned or only up to a given limit.', + }, + { + displayName: 'Limit', + name: 'limit', + type: 'number', + displayOptions: { + show: { + resource: [ + 'company', + ], + operation: [ + 'getAll', + ], + returnAll: [ + false, + ], + }, + }, + typeOptions: { + minValue: 1, + maxValue: 60, + }, + default: 50, + description: 'How many results to return.', + }, + { + displayName: 'Filters', + name: 'filters', + type: 'collection', + placeholder: 'Add Filter', + default: {}, + displayOptions: { + show: { + resource: [ + 'company', + ], + operation: [ + 'getAll', ], }, }, options: [ { - name: 'Segment ID', - value: 'segmentId', + displayName: 'Segment ID', + name: 'segment_id', + type: 'string', default: '', description: 'Segment representing the Lead', }, { - name: 'Tag ID', - value: 'tagId', + displayName: 'Tag ID', + name: 'tag_id', + type: 'string', default: '', description: 'Tag representing the Lead', }, - { - name: 'All', - value: 'all', - default: '', - description: 'List all users', - }, - ], - default: '', - description: 'List by' - }, - { - displayName: 'Value', - name: 'value', - type: 'string', - default: '', - required: true, - displayOptions: { - show: { - resource: [ - 'company', - ], - operation: [ - 'list', - ], - }, - hide: { - listBy: [ - 'all' - ] - } - }, - description: 'list by value', + ] }, /* -------------------------------------------------------------------------- */ -/* company:view */ +/* company:get */ /* -------------------------------------------------------------------------- */ { - displayName: 'View By', - name: 'viewBy', + displayName: 'Select By', + name: 'selectBy', type: 'options', displayOptions: { show: { @@ -178,32 +190,29 @@ export const companyFields = [ 'company', ], operation: [ - 'view', + 'get', ], }, }, options: [ - { - name: 'ID', - value: 'id', - default: '', - description: 'The Intercom defined id representing the company', - }, { name: 'Company ID', value: 'companyId', - default: '', description: 'The company_id you have given to the company', }, + { + name: 'ID', + value: 'id', + description: 'The Intercom defined id representing the company', + }, { name: 'Name', value: 'name', - default: '', description: 'The name of the company', }, ], default: '', - description: 'View by' + description: 'What property to use to query the company.', }, { displayName: 'Value', @@ -217,7 +226,7 @@ export const companyFields = [ 'company', ], operation: [ - 'view', + 'get', ], }, }, @@ -240,7 +249,7 @@ export const companyFields = [ ], operation: [ 'create', - 'update' + 'update', ], }, }, @@ -259,16 +268,16 @@ export const companyFields = [ 'update', ], resource: [ - 'company' + 'company', ], }, }, }, { - displayName: 'Options', - name: 'options', + displayName: 'Additional Fields', + name: 'additionalFields', type: 'collection', - placeholder: 'Add Option', + placeholder: 'Add Field', default: {}, displayOptions: { show: { @@ -277,11 +286,18 @@ export const companyFields = [ 'update', ], resource: [ - 'company' + 'company', ], }, }, options: [ + { + displayName: 'Industry', + name: 'industry', + type: 'string', + default: '', + description: 'The industry that this company operates in', + }, { displayName: 'Monthly Spend', name: 'monthlySpend', @@ -317,13 +333,7 @@ export const companyFields = [ name: 'website', type: 'string', default: '', - description: `The URL for this company's website. Please note that the value specified here is not validated. Accepts any string.`, - }, - { - displayName: 'Industry', - name: 'industry', - type: 'string', - description: 'The industry that this company operates in', + description: `The URL for this company's website. Please note that the value
specified here is not validated. Accepts any string.`, }, ] }, @@ -399,4 +409,3 @@ export const companyFields = [ description: 'A hash of key/value pairs to represent custom data you want to attribute to a user.', }, ] as INodeProperties[]; - diff --git a/packages/nodes-base/nodes/Intercom/GenericFunctions.ts b/packages/nodes-base/nodes/Intercom/GenericFunctions.ts index 2c8df9962d..be68ef0c34 100644 --- a/packages/nodes-base/nodes/Intercom/GenericFunctions.ts +++ b/packages/nodes-base/nodes/Intercom/GenericFunctions.ts @@ -7,21 +7,24 @@ import { IExecuteSingleFunctions } from 'n8n-core'; -export async function intercomApiRequest(this: IHookFunctions | IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions, resource: string, method: string, body: any = {}, headers?: object): Promise { // tslint:disable-line:no-any +import { + IDataObject, +} from 'n8n-workflow'; + +export async function intercomApiRequest(this: IHookFunctions | IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions, endpoint: string, method: string, body: any = {}, query?: IDataObject, uri?: string): Promise { // tslint:disable-line:no-any const credentials = this.getCredentials('intercomApi'); if (credentials === undefined) { throw new Error('No credentials got returned!'); } - const headerWithAuthentication = Object.assign({}, headers, + const headerWithAuthentication = Object.assign({}, { Authorization: `Bearer ${credentials.apiKey}`, Accept: 'application/json' }); - const endpoint = 'api.intercom.io'; - const options: OptionsWithUri = { headers: headerWithAuthentication, method, - uri: `https://${endpoint}${resource}`, + qs: query, + uri: uri || `https://api.intercom.io${endpoint}`, body, json: true }; @@ -29,8 +32,6 @@ export async function intercomApiRequest(this: IHookFunctions | IExecuteFunction try { return await this.helpers.request!(options); } catch (error) { - console.error(error); - const errorMessage = error.response.body.message || error.response.body.Message; if (errorMessage !== undefined) { @@ -40,6 +41,36 @@ export async function intercomApiRequest(this: IHookFunctions | IExecuteFunction } } + + +/** + * Make an API request to paginated intercom endpoint + * and return all results + */ +export async function intercomApiRequestAllItems(this: IHookFunctions | IExecuteFunctions, propertyName: string, endpoint: string, method: string, body: any = {}, query: IDataObject = {}): Promise { // tslint:disable-line:no-any + + const returnData: IDataObject[] = []; + + let responseData; + + query.per_page = 60; + + let uri: string | undefined; + + do { + responseData = await intercomApiRequest.call(this, endpoint, method, body, query, uri); + uri = responseData.pages.next; + returnData.push.apply(returnData, responseData[propertyName]); + } while ( + responseData.pages !== undefined && + responseData.pages.next !== undefined && + responseData.pages.next !== null + ); + + return returnData; +} + + export function validateJSON(json: string | undefined): any { // tslint:disable-line:no-any let result; try { diff --git a/packages/nodes-base/nodes/Intercom/Intercom.node.ts b/packages/nodes-base/nodes/Intercom/Intercom.node.ts index bb59d277f3..6486517c3c 100644 --- a/packages/nodes-base/nodes/Intercom/Intercom.node.ts +++ b/packages/nodes-base/nodes/Intercom/Intercom.node.ts @@ -15,6 +15,7 @@ import { } from './LeadDescription'; import { intercomApiRequest, + intercomApiRequestAllItems, validateJSON, } from './GenericFunctions'; import { @@ -24,7 +25,7 @@ import { } from './LeadInterface'; import { userOpeations, userFields } from './UserDescription'; import { IUser, IUserCompany } from './UserInterface'; -import { companyOpeations, companyFields } from './CompanyDescription'; +import { companyOperations, companyFields } from './CompanyDescription'; import { ICompany } from './CompanyInteface'; export class Intercom implements INodeType { @@ -55,9 +56,9 @@ export class Intercom implements INodeType { type: 'options', options: [ { - name: 'User', - value: 'user', - description: 'The Users resource is the primary way of interacting with Intercom', + name: 'Company', + value: 'company', + description: 'Companies allow you to represent commercial organizations using your product.', }, { name: 'Lead', @@ -65,17 +66,17 @@ export class Intercom implements INodeType { description: 'Leads are useful for representing logged-out users of your application.', }, { - name: 'Company', - value: 'company', - description: 'Companies allow you to represent commercial organizations using your product.', + name: 'User', + value: 'user', + description: 'The Users resource is the primary way of interacting with Intercom', }, ], - default: '', + default: 'user', description: 'Resource to consume.', }, ...leadOpeations, ...userOpeations, - ...companyOpeations, + ...companyOperations, ...userFields, ...leadFields, ...companyFields, @@ -112,58 +113,62 @@ export class Intercom implements INodeType { const items = this.getInputData(); const returnData: IDataObject[] = []; const length = items.length as unknown as number; + let qs: IDataObject; let responseData; for (let i = 0; i < length; i++) { + qs = {}; const resource = this.getNodeParameter('resource', 0) as string; const operation = this.getNodeParameter('operation', 0) as string; //https://developers.intercom.com/intercom-api-reference/reference#leads if (resource === 'lead') { if (operation === 'create' || operation === 'update') { - const email = this.getNodeParameter('email', i) as string; - const options = this.getNodeParameter('options', i) as IDataObject; + const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject; const jsonActive = this.getNodeParameter('jsonParameters', i) as boolean; const body: ILead = {}; - if (email) { + if (operation === 'create') { body.email = this.getNodeParameter('email', i) as string; } - if (options.phone) { - body.phone = options.phone as string; + if (additionalFields.email) { + body.email = additionalFields.email as string; } - if (options.name) { - body.name = options.name as string; + if (additionalFields.phone) { + body.phone = additionalFields.phone as string; } - if (options.unsubscribedFromEmails) { - body.unsubscribed_from_emails = options.unsubscribedFromEmails as boolean; + if (additionalFields.name) { + body.name = additionalFields.name as string; } - if (options.updateLastRequestAt) { - body.update_last_request_at = options.updateLastRequestAt as boolean; + if (additionalFields.unsubscribedFromEmails) { + body.unsubscribed_from_emails = additionalFields.unsubscribedFromEmails as boolean; } - if (options.utmSource) { - body.utm_source = options.utmSource as string; + if (additionalFields.updateLastRequestAt) { + body.update_last_request_at = additionalFields.updateLastRequestAt as boolean; } - if (options.utmMedium) { - body.utm_medium = options.utmMedium as string; + if (additionalFields.utmSource) { + body.utm_source = additionalFields.utmSource as string; } - if (options.utmCampaign) { - body.utm_campaign = options.utmCampaign as string; + if (additionalFields.utmMedium) { + body.utm_medium = additionalFields.utmMedium as string; } - if (options.utmTerm) { - body.utm_term = options.utmTerm as string; + if (additionalFields.utmCampaign) { + body.utm_campaign = additionalFields.utmCampaign as string; } - if (options.utmContent) { - body.utm_content = options.utmContent as string; + if (additionalFields.utmTerm) { + body.utm_term = additionalFields.utmTerm as string; } - if(options.avatar) { + if (additionalFields.utmContent) { + body.utm_content = additionalFields.utmContent as string; + } + if (additionalFields.avatar) { const avatar: IAvatar = { type: 'avatar', - image_url: options.avatar as string, + image_url: additionalFields.avatar as string, }; body.avatar = avatar; } - if (options.companies) { + if (additionalFields.companies) { const companies: ILeadCompany[] = []; // @ts-ignore - options.companies.forEach( o => { + additionalFields.companies.forEach( o => { const company: ILeadCompany = {}; company.company_id = o; companies.push(company); @@ -186,6 +191,7 @@ export class Intercom implements INodeType { body.custom_attributes = customAttributesJson; } } + if (operation === 'update') { const updateBy = this.getNodeParameter('updateBy', 0) as string; const value = this.getNodeParameter('value', i) as string; @@ -196,43 +202,49 @@ export class Intercom implements INodeType { body.id = value; } } + try { responseData = await intercomApiRequest.call(this, '/contacts', 'POST', body); } catch (err) { throw new Error(`Intercom Error: ${JSON.stringify(err)}`); } } - if (operation === 'view') { - let query = ''; - const viewBy = this.getNodeParameter('viewBy', 0) as string; + if (operation === 'get') { + const selectBy = this.getNodeParameter('selectBy', 0) as string; const value = this.getNodeParameter('value', i) as string; - if (viewBy === 'userId') { - query = `user_id=${value}`; + if (selectBy === 'email') { + qs.email = value; } - if (viewBy === 'phone') { - query = `phone=${value}`; + if (selectBy === 'userId') { + qs.user_id = value; + } + if (selectBy === 'phone') { + qs.phone = value; } try { - if (viewBy === 'id') { - responseData = await intercomApiRequest.call(this, `/contacts/${value}`, 'GET'); - } else { - responseData = await intercomApiRequest.call(this, `/contacts?${query}`, 'GET'); - } + if (selectBy === 'id') { + responseData = await intercomApiRequest.call(this, `/contacts/${value}`, 'GET'); + } else { + responseData = await intercomApiRequest.call(this, '/contacts', 'GET', {}, qs); + responseData = responseData.contacts; + } } catch (err) { throw new Error(`Intercom Error: ${JSON.stringify(err)}`); } } - if (operation === 'list') { - let query = ''; - const listBy = this.getNodeParameter('listBy', 0) as string; - if (listBy === 'email') { - query = `email=${this.getNodeParameter('value', i) as string}`; - } - if (listBy === 'phone') { - query = `phone=${this.getNodeParameter('value', i) as string}`; - } + if (operation === 'getAll') { + const returnAll = this.getNodeParameter('returnAll', i) as boolean; + const filters = this.getNodeParameter('filters', i) as IDataObject; + Object.assign(qs, filters); + try { - responseData = await intercomApiRequest.call(this, `/contacts?${query}`, 'GET'); + if (returnAll === true) { + responseData = await intercomApiRequestAllItems.call(this, 'contacts', '/contacts', 'GET', {}, qs); + } else { + qs.per_page = this.getNodeParameter('limit', i) as number; + responseData = await intercomApiRequest.call(this, '/contacts', 'GET', {}, qs); + responseData = responseData.contacts; + } } catch (err) { throw new Error(`Intercom Error: ${JSON.stringify(err)}`); } @@ -244,7 +256,8 @@ export class Intercom implements INodeType { if (deleteBy === 'id') { responseData = await intercomApiRequest.call(this, `/contacts/${value}`, 'DELETE'); } else { - responseData = await intercomApiRequest.call(this, `/contacts?user_id=${value}`, 'DELETE'); + qs.user_id = value; + responseData = await intercomApiRequest.call(this, '/contacts', 'DELETE', {}, qs); } } catch (err) { throw new Error(`Intercom Error: ${JSON.stringify(err)}`); @@ -254,65 +267,74 @@ export class Intercom implements INodeType { //https://developers.intercom.com/intercom-api-reference/reference#users if (resource === 'user') { if (operation === 'create' || operation === 'update') { - const id = this.getNodeParameter('id', i) as string; - const options = this.getNodeParameter('options', i) as IDataObject; + const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject; const jsonActive = this.getNodeParameter('jsonParameters', i) as boolean; const body: IUser = {}; - if (id === 'email') { - body.email = this.getNodeParameter('idValue', i) as string; + + if (operation === 'create') { + const identifierType = this.getNodeParameter('identifierType', i) as string; + if (identifierType === 'email') { + body.email = this.getNodeParameter('idValue', i) as string; + } else if (identifierType === 'userId') { + body.user_id = this.getNodeParameter('idValue', i) as string; + } } - if (id === 'userId') { - body.user_id = this.getNodeParameter('idValue', i) as string; + + if (additionalFields.email) { + body.email = additionalFields.email as string; } - if (options.phone) { - body.phone = options.phone as string; + if (additionalFields.userId) { + body.user_id = additionalFields.userId as string; } - if (options.name) { - body.name = options.name as string; + if (additionalFields.phone) { + body.phone = additionalFields.phone as string; } - if (options.unsubscribedFromEmails) { - body.unsubscribed_from_emails = options.unsubscribedFromEmails as boolean; + if (additionalFields.name) { + body.name = additionalFields.name as string; } - if (options.updateLastRequestAt) { - body.update_last_request_at = options.updateLastRequestAt as boolean; + if (additionalFields.unsubscribedFromEmails) { + body.unsubscribed_from_emails = additionalFields.unsubscribedFromEmails as boolean; } - if (options.sessionCount) { - body.session_count = options.sessionCount as number; + if (additionalFields.updateLastRequestAt) { + body.update_last_request_at = additionalFields.updateLastRequestAt as boolean; } - if(options.avatar) { + if (additionalFields.sessionCount) { + body.session_count = additionalFields.sessionCount as number; + } + if (additionalFields.avatar) { const avatar: IAvatar = { type: 'avatar', - image_url: options.avatar as string, + image_url: additionalFields.avatar as string, }; body.avatar = avatar; } - if (options.utmSource) { - body.utm_source = options.utmSource as string; + if (additionalFields.utmSource) { + body.utm_source = additionalFields.utmSource as string; } - if (options.utmMedium) { - body.utm_medium = options.utmMedium as string; + if (additionalFields.utmMedium) { + body.utm_medium = additionalFields.utmMedium as string; } - if (options.utmCampaign) { - body.utm_campaign = options.utmCampaign as string; + if (additionalFields.utmCampaign) { + body.utm_campaign = additionalFields.utmCampaign as string; } - if (options.utmTerm) { - body.utm_term = options.utmTerm as string; + if (additionalFields.utmTerm) { + body.utm_term = additionalFields.utmTerm as string; } - if (options.utmContent) { - body.utm_content = options.utmContent as string; + if (additionalFields.utmContent) { + body.utm_content = additionalFields.utmContent as string; } - if (options.companies) { + if (additionalFields.companies) { const companies: IUserCompany[] = []; // @ts-ignore - options.companies.forEach( o => { + additionalFields.companies.forEach( o => { const company: IUserCompany = {}; company.company_id = o; companies.push(company); }); body.companies = companies; } - if (options.sessionCount) { - body.session_count = options.sessionCount as number; + if (additionalFields.sessionCount) { + body.session_count = additionalFields.sessionCount as number; } if (!jsonActive) { const customAttributesValues = (this.getNodeParameter('customAttributesUi', i) as IDataObject).customAttributesValues as IDataObject[]; @@ -330,57 +352,56 @@ export class Intercom implements INodeType { body.custom_attributes = customAttributesJson; } } + if (operation === 'update') { - const id = this.getNodeParameter('id', i) as string; - const email = this.getNodeParameter('email', i) as string; - const userId = this.getNodeParameter('userId', i) as string; - if (id) { - body.id = id; + const updateBy = this.getNodeParameter('updateBy', 0) as string; + const value = this.getNodeParameter('value', i) as string; + if (updateBy === 'userId') { + body.user_id = value; } - if (email) { - body.email = email; + if (updateBy === 'id') { + body.id = value; } - if (userId) { - body.user_id = userId; + if (updateBy === 'email') { + body.email = value; } } + try { - responseData = await intercomApiRequest.call(this, '/users', 'POST', body); + responseData = await intercomApiRequest.call(this, '/users', 'POST', body, qs); } catch (err) { throw new Error(`Intercom Error: ${JSON.stringify(err)}`); } } - if (operation === 'view') { - let query = ''; - const viewBy = this.getNodeParameter('viewBy', 0) as string; + if (operation === 'get') { + const selectBy = this.getNodeParameter('selectBy', 0) as string; const value = this.getNodeParameter('value', i) as string; - if (viewBy === 'userId') { - query = `user_id=${value}`; + if (selectBy === 'userId') { + qs.user_id = value; } try { - if (viewBy === 'id') { - responseData = await intercomApiRequest.call(this, `/users/${value}`, 'GET'); - } else { - responseData = await intercomApiRequest.call(this, `/users?${query}`, 'GET'); - } + if (selectBy === 'id') { + responseData = await intercomApiRequest.call(this, `/users/${value}`, 'GET', {}, qs); + } else { + responseData = await intercomApiRequest.call(this, '/users', 'GET', {}, qs); + } } catch (err) { throw new Error(`Intercom Error: ${JSON.stringify(err)}`); } } - if (operation === 'list') { - let query = ''; - const listBy = this.getNodeParameter('listBy', 0) as string; - if (listBy === 'email') { - query = `email=${this.getNodeParameter('value', i) as string}`; - } - if (listBy === 'segmentId') { - query = `segment_id=${this.getNodeParameter('value', i) as string}`; - } - if (listBy === 'tagId') { - query = `tag_id=${this.getNodeParameter('value', i) as string}`; - } + if (operation === 'getAll') { + const returnAll = this.getNodeParameter('returnAll', i) as boolean; + const filters = this.getNodeParameter('filters', i) as IDataObject; + Object.assign(qs, filters); + try { - responseData = await intercomApiRequest.call(this, `/users?${query}`, 'GET'); + if (returnAll === true) { + responseData = await intercomApiRequestAllItems.call(this, 'users', '/users', 'GET', {}, qs); + } else { + qs.per_page = this.getNodeParameter('limit', i) as number; + responseData = await intercomApiRequest.call(this, '/users', 'GET', {}, qs); + responseData = responseData.users; + } } catch (err) { throw new Error(`Intercom Error: ${JSON.stringify(err)}`); } @@ -398,28 +419,28 @@ export class Intercom implements INodeType { if (resource === 'company') { if (operation === 'create' || operation === 'update') { const id = this.getNodeParameter('companyId', i) as string; - const options = this.getNodeParameter('options', i) as IDataObject; + const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject; const jsonActive = this.getNodeParameter('jsonParameters', i) as boolean; const body: ICompany = { company_id: id, }; - if (options.monthlySpend) { - body.monthly_spend = options.monthlySpend as number; + if (additionalFields.monthlySpend) { + body.monthly_spend = additionalFields.monthlySpend as number; } - if (options.name) { - body.name = options.name as string; + if (additionalFields.name) { + body.name = additionalFields.name as string; } - if (options.plan) { - body.plan = options.plan as string; + if (additionalFields.plan) { + body.plan = additionalFields.plan as string; } - if (options.size) { - body.size = options.size as number; + if (additionalFields.size) { + body.size = additionalFields.size as number; } - if (options.website) { - body.website = options.website as string; + if (additionalFields.website) { + body.website = additionalFields.website as string; } - if (options.industry) { - body.industry = options.industry as string; + if (additionalFields.industry) { + body.industry = additionalFields.industry as string; } if (!jsonActive) { const customAttributesValues = (this.getNodeParameter('customAttributesUi', i) as IDataObject).customAttributesValues as IDataObject[]; @@ -438,58 +459,59 @@ export class Intercom implements INodeType { } } try { - responseData = await intercomApiRequest.call(this, '/companies', 'POST', body); + responseData = await intercomApiRequest.call(this, '/companies', 'POST', body, qs); } catch (err) { throw new Error(`Intercom Error: ${JSON.stringify(err)}`); } } - if (operation === 'view') { - let query = ''; - const viewBy = this.getNodeParameter('viewBy', 0) as string; + if (operation === 'get') { + const selectBy = this.getNodeParameter('selectBy', 0) as string; const value = this.getNodeParameter('value', i) as string; - if (viewBy === 'companyId') { - query = `company_id=${value}`; + if (selectBy === 'companyId') { + qs.company_id = value; } - if (viewBy === 'name') { - query = `name=${value}`; + if (selectBy === 'name') { + qs.name = value; } try { - if (viewBy === 'id') { - responseData = await intercomApiRequest.call(this, `/companies/${value}`, 'GET'); - } else { - responseData = await intercomApiRequest.call(this, `/companies?${query}`, 'GET'); - } + if (selectBy === 'id') { + responseData = await intercomApiRequest.call(this, `/companies/${value}`, 'GET', {}, qs); + } else { + responseData = await intercomApiRequest.call(this, '/companies', 'GET', {}, qs); + } } catch (err) { throw new Error(`Intercom Error: ${JSON.stringify(err)}`); } } - if (operation === 'list') { - let query = ''; - const listBy = this.getNodeParameter('listBy', 0) as string; - if (listBy === 'segmentId') { - query = `segment_id=${this.getNodeParameter('value', i) as string}`; - } - if (listBy === 'tagId') { - query = `tag_id=${this.getNodeParameter('value', i) as string}`; - } + if (operation === 'getAll') { + const returnAll = this.getNodeParameter('returnAll', i) as boolean; + const filters = this.getNodeParameter('filters', i) as IDataObject; + Object.assign(qs, filters); + try { - responseData = await intercomApiRequest.call(this, `/companies?${query}`, 'GET'); + if (returnAll === true) { + responseData = await intercomApiRequestAllItems.call(this, 'companies', '/companies', 'GET', {}, qs); + } else { + qs.per_page = this.getNodeParameter('limit', i) as number; + responseData = await intercomApiRequest.call(this, '/companies', 'GET', {}, qs); + responseData = responseData.companies; + } } catch (err) { throw new Error(`Intercom Error: ${JSON.stringify(err)}`); } } if (operation === 'users') { - let query = ''; - const listBy = this.getNodeParameter('listBy', 0) as string; + const filterBy = this.getNodeParameter('filterBy', 0) as string; const value = this.getNodeParameter('value', i) as string; - if (listBy === 'companyId') { - query = `company_id=${value}`; + if (filterBy === 'companyId') { + qs.company_id = value; } try { - if (listBy === 'id') { - responseData = await intercomApiRequest.call(this, `/companies/${value}/users`, 'GET'); + if (filterBy === 'id') { + responseData = await intercomApiRequest.call(this, `/companies/${value}/users`, 'GET', {}, qs); } else { - responseData = await intercomApiRequest.call(this, `/companies?${query}&type=users`, 'GET'); + qs.type = 'users'; + responseData = await intercomApiRequest.call(this, '/companies', 'GET', {}, qs); } } catch (err) { throw new Error(`Intercom Error: ${JSON.stringify(err)}`); diff --git a/packages/nodes-base/nodes/Intercom/LeadDescription.ts b/packages/nodes-base/nodes/Intercom/LeadDescription.ts index 03bfd1f299..e7414ac8b6 100644 --- a/packages/nodes-base/nodes/Intercom/LeadDescription.ts +++ b/packages/nodes-base/nodes/Intercom/LeadDescription.ts @@ -18,28 +18,28 @@ export const leadOpeations = [ value: 'create', description: 'Create a new lead', }, + { + name: 'Get', + value: 'get', + description: 'Get data of a lead', + }, + { + name: 'Get All', + value: 'getAll', + description: 'Get data of all leads', + }, { name: 'Update', value: 'update', description: 'Update new lead', }, - { - name: 'View', - value: 'view', - description: 'View a lead', - }, - { - name: 'List', - value: 'list', - description: 'List leads', - }, { name: 'Delete', value: 'delete', description: 'Delete a lead', } ], - default: '', + default: 'create', description: 'The operation to perform.', }, ] as INodeProperties[]; @@ -68,18 +68,16 @@ export const leadFields = [ { name: 'ID', value: 'id', - default: '', description: 'The Intercom defined id representing the Lead', }, { name: 'User ID', value: 'userId', - default: '', description: 'Automatically generated identifier for the Lead', }, ], default: '', - description: 'Delete by' + description: 'Delete by', }, { displayName: 'Value', @@ -100,12 +98,12 @@ export const leadFields = [ }, /* -------------------------------------------------------------------------- */ -/* lead:view */ +/* lead:get */ /* -------------------------------------------------------------------------- */ { - displayName: 'View By', - name: 'viewBy', + displayName: 'Select By', + name: 'selectBy', type: 'options', displayOptions: { show: { @@ -113,67 +111,7 @@ export const leadFields = [ 'lead', ], operation: [ - 'view', - ], - }, - }, - options: [ - { - name: 'ID', - value: 'id', - default: '', - description: 'The Intercom defined id representing the Lead', - }, - { - name: 'User ID', - value: 'userId', - default: '', - description: 'Automatically generated identifier for the Lead', - }, - { - name: 'Phone', - value: 'phone', - default: '', - description: 'Phone representing the Lead', - }, - ], - default: '', - description: 'View by' - }, - { - displayName: 'Value', - name: 'value', - type: 'string', - default: '', - required: true, - displayOptions: { - show: { - resource: [ - 'lead', - ], - operation: [ - 'view', - ], - }, - }, - description: 'View by value', - }, - -/* -------------------------------------------------------------------------- */ -/* lead:list */ -/* -------------------------------------------------------------------------- */ - - { - displayName: 'List by', - name: 'listBy', - type: 'options', - displayOptions: { - show: { - resource: [ - 'lead', - ], - operation: [ - 'list', + 'get', ], }, }, @@ -181,24 +119,26 @@ export const leadFields = [ { name: 'Email', value: 'email', - default: '', description: 'Email representing the Lead', }, + { + name: 'ID', + value: 'id', + description: 'The Intercom defined id representing the Lead', + }, + { + name: 'User ID', + value: 'userId', + description: 'Automatically generated identifier for the Lead', + }, { name: 'Phone', value: 'phone', - default: '', description: 'Phone representing the Lead', }, - { - name: 'All', - value: 'all', - default: '', - description: 'List all leads', - }, ], default: '', - description: 'List by' + description: 'The property to select the lead by.', }, { displayName: 'Value', @@ -212,16 +152,90 @@ export const leadFields = [ 'lead', ], operation: [ - 'list', + 'get', ], }, - hide: { - listBy: [ - 'all' - ] - } }, - description: 'list by value', + description: 'View by value', + }, + +/* -------------------------------------------------------------------------- */ +/* lead:getAll */ +/* -------------------------------------------------------------------------- */ + + { + displayName: 'Return All', + name: 'returnAll', + type: 'boolean', + displayOptions: { + show: { + resource: [ + 'lead', + ], + operation: [ + 'getAll', + ], + }, + }, + default: false, + description: 'If all results should be returned or only up to a given limit.', + }, + { + displayName: 'Limit', + name: 'limit', + type: 'number', + displayOptions: { + show: { + resource: [ + 'lead', + ], + operation: [ + 'getAll', + ], + returnAll: [ + false, + ], + }, + }, + typeOptions: { + minValue: 1, + maxValue: 60, + }, + default: 50, + description: 'How many results to return.', + }, + { + displayName: 'Filters', + name: 'filters', + type: 'collection', + placeholder: 'Add Filter', + default: {}, + displayOptions: { + show: { + resource: [ + 'lead', + ], + operation: [ + 'getAll', + ], + }, + }, + options: [ + { + displayName: 'Email', + name: 'email', + type: 'string', + default: '', + description: 'The email address of the lead', + }, + { + displayName: 'Phone', + name: 'phone', + type: 'string', + default: '', + description: 'The phone number of the lead', + }, + ] }, /* -------------------------------------------------------------------------- */ @@ -246,18 +260,16 @@ export const leadFields = [ { name: 'User ID', value: 'userId', - default: '', description: 'Automatically generated identifier for the Lead', }, { name: 'ID', value: 'id', - default: '', description: 'The Intercom defined id representing the Lead', }, ], - default: '', - description: 'Update by', + default: 'id', + description: 'The property via which to query the lead.', }, { displayName: 'Value', @@ -275,7 +287,7 @@ export const leadFields = [ ], }, }, - description: 'Update by value', + description: 'Value of the property to identify the lead to update', }, /* -------------------------------------------------------------------------- */ @@ -300,24 +312,6 @@ export const leadFields = [ }, description: 'The email of the user.', }, - { - displayName: 'Email', - name: 'email', - type: 'string', - default: '', - required: false, - displayOptions: { - show: { - resource: [ - 'lead', - ], - operation: [ - 'update', - ], - }, - }, - description: 'The email of the user.', - }, { displayName: 'JSON Parameters', name: 'jsonParameters', @@ -331,16 +325,16 @@ export const leadFields = [ 'update', ], resource: [ - 'lead' + 'lead', ], }, }, }, { - displayName: 'Options', - name: 'options', + displayName: 'Additional Fields', + name: 'additionalFields', type: 'collection', - placeholder: 'Add Option', + placeholder: 'Add Field', default: {}, displayOptions: { show: { @@ -349,11 +343,25 @@ export const leadFields = [ 'update', ], resource: [ - 'lead' + 'lead', ], }, }, options: [ + { + displayName: 'Avatar', + name: 'avatar', + type: 'string', + default: '', + description: 'An avatar image URL. note: the image url needs to be https.', + }, + { + displayName: 'Name', + name: 'name', + type: 'string', + default: '', + description: 'Name of the user', + }, { displayName: 'Phone', name: 'phone', @@ -361,20 +369,11 @@ export const leadFields = [ default: '', description: 'The phone number of the user', }, - { - displayName: 'Name', - name: 'name', - type: 'string', - default: '', - placeholder: '', - description: 'Name of the user', - }, { displayName: 'Unsubscribed From Emails', name: 'unsubscribedFromEmails', type: 'boolean', - default: '', - placeholder: '', + default: false, description: 'Whether the Lead is unsubscribed from emails', }, { @@ -382,8 +381,7 @@ export const leadFields = [ name: 'updateLastRequestAt', type: 'boolean', default: false, - options: [], - description: `A boolean value, which if true, instructs Intercom to update the users' last_request_at value to the current API service time in UTC. default value if not sent is false.`, + description: 'A boolean value, which if true, instructs Intercom to update the
users last_request_at value to the current API service time in
UTC. default value if not sent is false.', }, { displayName: 'Companies', @@ -396,11 +394,21 @@ export const leadFields = [ description: 'Identifies the companies this user belongs to.', }, { - displayName: 'Avatar', - name: 'avatar', + displayName: 'Email', + name: 'email', type: 'string', default: '', - description: 'An avatar image URL. note: the image url needs to be https.', + displayOptions: { + show: { + '/resource': [ + 'lead', + ], + '/operation': [ + 'update', + ], + }, + }, + description: 'The email of the user.', }, { displayName: 'UTM Source', @@ -511,4 +519,3 @@ export const leadFields = [ description: 'A hash of key/value pairs to represent custom data you want to attribute to a user.', }, ] as INodeProperties[]; - diff --git a/packages/nodes-base/nodes/Intercom/UserDescription.ts b/packages/nodes-base/nodes/Intercom/UserDescription.ts index 2f89ae3682..b54952b5f1 100644 --- a/packages/nodes-base/nodes/Intercom/UserDescription.ts +++ b/packages/nodes-base/nodes/Intercom/UserDescription.ts @@ -18,28 +18,28 @@ export const userOpeations = [ value: 'create', description: 'Create a new user', }, + { + name: 'Get', + value: 'get', + description: 'Get data of a user', + }, + { + name: 'Get All', + value: 'getAll', + description: 'Get data of all users', + }, { name: 'Update', value: 'update', description: 'Update a user', }, - { - name: 'View', - value: 'view', - description: 'View a user', - }, - { - name: 'List', - value: 'list', - description: 'List users', - }, { name: 'Delete', value: 'delete', description: 'Delete a user', } ], - default: '', + default: 'create', description: 'The operation to perform.', }, ] as INodeProperties[]; @@ -70,89 +70,106 @@ export const userFields = [ }, /* -------------------------------------------------------------------------- */ -/* user:list */ +/* user:getAll */ /* -------------------------------------------------------------------------- */ { - displayName: 'List by', - name: 'listBy', - type: 'options', + displayName: 'Return All', + name: 'returnAll', + type: 'boolean', displayOptions: { show: { resource: [ 'user', ], operation: [ - 'list', + 'getAll', + ], + }, + }, + default: false, + description: 'If all results should be returned or only up to a given limit.', + }, + { + displayName: 'Limit', + name: 'limit', + type: 'number', + displayOptions: { + show: { + resource: [ + 'user', + ], + operation: [ + 'getAll', + ], + returnAll: [ + false, + ], + }, + }, + typeOptions: { + minValue: 1, + maxValue: 60, + }, + default: 50, + description: 'How many results to return.', + }, + { + displayName: 'Filters', + name: 'filters', + type: 'collection', + placeholder: 'Add Filter', + default: {}, + displayOptions: { + show: { + resource: [ + 'user', + ], + operation: [ + 'getAll', ], }, }, options: [ { - name: 'Email', - value: 'email', + displayName: 'Company ID', + name: 'company_id', + type: 'string', default: '', - description: 'Email representing the Lead', + description: 'Company ID representing the user', }, { - name: 'Segment ID', - value: 'segmentId', + displayName: 'Email', + name: 'email', + type: 'string', default: '', - description: 'Segment representing the Lead', + description: 'The email address of the user', }, { - name: 'Tag ID', - value: 'tagId', + displayName: 'Tag ID', + name: 'tag_id', + type: 'string', default: '', - description: 'Tag representing the Lead', + description: 'Tag representing the user', }, { - name: 'Company ID', - value: 'companyId', + displayName: 'Segment ID', + name: 'segment_id', + type: 'string', default: '', - description: 'Company representing the Lead', - }, - { - name: 'All', - value: 'all', - default: '', - description: 'List all users', + description: 'Segment representing the user', }, ], - default: '', - description: 'List by' - }, - { - displayName: 'Value', - name: 'value', - type: 'string', - default: '', - required: true, - displayOptions: { - show: { - resource: [ - 'user', - ], - operation: [ - 'list', - ], - }, - hide: { - listBy: [ - 'all' - ] - } - }, - description: 'list by value', }, + /* -------------------------------------------------------------------------- */ -/* view:user */ +/* user:get */ /* -------------------------------------------------------------------------- */ { - displayName: 'View By', - name: 'viewBy', + displayName: 'Select By', + name: 'selectBy', type: 'options', displayOptions: { show: { @@ -160,7 +177,7 @@ export const userFields = [ 'user', ], operation: [ - 'view', + 'get', ], }, }, @@ -179,7 +196,7 @@ export const userFields = [ }, ], default: '', - description: 'View by' + description: 'The property to select the user by.', }, { displayName: 'Value', @@ -193,7 +210,7 @@ export const userFields = [ 'user', ], operation: [ - 'view', + 'get', ], }, }, @@ -205,10 +222,9 @@ export const userFields = [ /* -------------------------------------------------------------------------- */ { - displayName: 'Id', - name: 'id', - type: 'string', - default: '', + displayName: 'Update By', + name: 'updateBy', + type: 'options', displayOptions: { show: { resource: [ @@ -219,13 +235,33 @@ export const userFields = [ ], }, }, - description: 'id is matched - the user_id and email will be updated if they are sent.', + options: [ + { + name: 'ID', + value: 'id', + description: 'The Intercom defined id representing the user', + }, + { + name: 'Email', + value: 'email', + description: 'The email address of user', + }, + { + name: 'User ID', + value: 'userId', + description: 'Automatically generated identifier for the user', + }, + + ], + default: 'id', + description: 'The property via which to query the user.', }, { - displayName: 'User Id', - name: 'userId', + displayName: 'Value', + name: 'value', type: 'string', default: '', + required: true, displayOptions: { show: { resource: [ @@ -236,25 +272,7 @@ export const userFields = [ ], }, }, - description: 'user_id match - the email will be updated, the id is not updated.', - }, - { - displayName: 'Email', - name: 'email', - type: 'string', - default: '', - displayOptions: { - show: { - resource: [ - 'user', - ], - operation: [ - 'update', - ], - }, - }, - description: `email match where no user_id set on the matching user - the user_id will be set to the value sent in the request, the id is not updated. - email match where there is a user_id set on the matching user - a new unique record with new id will be created if a new value for user_id is sent in the request.`, + description: 'Value of the property to identify the user to update', }, /* -------------------------------------------------------------------------- */ @@ -262,8 +280,8 @@ export const userFields = [ /* -------------------------------------------------------------------------- */ { - displayName: 'Id', - name: 'id', + displayName: 'Identifier Type', + name: 'identifierType', type: 'options', displayOptions: { show: { @@ -277,15 +295,13 @@ export const userFields = [ }, options: [ { - name: 'User Id', + name: 'User ID', value: 'userId', - default: '', description: 'A unique string identifier for the user. It is required on creation if an email is not supplied.', }, { name: 'Email', value: 'email', - default: '', description: `The user's email address. It is required on creation if a user_id is not supplied.`, }, ], @@ -329,10 +345,10 @@ export const userFields = [ }, }, { - displayName: 'Options', - name: 'options', + displayName: 'Additional Fields', + name: 'additionalFields', type: 'collection', - placeholder: 'Add Option', + placeholder: 'Add Field', default: {}, displayOptions: { show: { @@ -346,6 +362,51 @@ export const userFields = [ }, }, options: [ + { + displayName: 'Email', + name: 'email', + displayOptions: { + show: { + '/operation': [ + 'update', + ], + '/resource': [ + 'user' + ], + }, + hide: { + '/updateBy': [ + 'email', + ] + }, + }, + type: 'string', + default: '', + description: 'Email of the user', + }, + { + displayName: 'User ID', + name: 'userId', + displayOptions: { + show: { + '/operation': [ + 'update', + ], + '/resource': [ + 'user' + ], + }, + hide: { + '/updateBy': [ + 'email', + 'userId', + ] + }, + }, + type: 'string', + default: '', + description: 'Email of the user', + }, { displayName: 'Phone', name: 'phone', @@ -375,7 +436,7 @@ export const userFields = [ type: 'boolean', default: false, options: [], - description: `A boolean value, which if true, instructs Intercom to update the users' last_request_at value to the current API service time in UTC. default value if not sent is false.`, + description: 'A boolean value, which if true, instructs Intercom to update the users
last_request_at value to the current API service time in UTC.', }, { displayName: 'Session Count', @@ -511,4 +572,3 @@ export const userFields = [ description: 'A hash of key/value pairs to represent custom data you want to attribute to a user.', }, ] as INodeProperties[]; -