mirror of
https://github.com/n8n-io/n8n.git
synced 2025-01-11 12:57:29 -08:00
✨ Add support for multiple subscriptions in Hubspot Trigger (#1358)
* ⚡ Add support for multiple subscriptions in Hubspot Trigger * ⚡ Load object properties for the user * ⚡ Improvements * ⚡ Some improvements to the Hubspot-Node Co-authored-by: Jan Oberhauser <jan.oberhauser@gmail.com>
This commit is contained in:
parent
5549550928
commit
dc98de1ab2
|
@ -2,6 +2,18 @@
|
||||||
|
|
||||||
This list shows all the versions which include breaking changes and how to upgrade.
|
This list shows all the versions which include breaking changes and how to upgrade.
|
||||||
|
|
||||||
|
## 0.105.0
|
||||||
|
|
||||||
|
### What changed?
|
||||||
|
In the Hubspot Trigger, now multiple events can be provided and the field `App ID` was so moved to the credentials.
|
||||||
|
|
||||||
|
### When is action necessary?
|
||||||
|
If you are using the Hubspot Trigger node.
|
||||||
|
|
||||||
|
### How to upgrade:
|
||||||
|
Open the Hubspot Trigger and set the events again. Also open the credentials `Hubspot Developer API` and set your APP ID.
|
||||||
|
|
||||||
|
|
||||||
## 0.104.0
|
## 0.104.0
|
||||||
|
|
||||||
### What changed?
|
### What changed?
|
||||||
|
|
|
@ -20,5 +20,13 @@ export class HubspotDeveloperApi implements ICredentialType {
|
||||||
type: 'string' as NodePropertyTypes,
|
type: 'string' as NodePropertyTypes,
|
||||||
default: '',
|
default: '',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
displayName: 'App ID',
|
||||||
|
name: 'appId',
|
||||||
|
type: 'string' as NodePropertyTypes,
|
||||||
|
required: true,
|
||||||
|
default: '',
|
||||||
|
description: 'The App ID',
|
||||||
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
@ -378,6 +378,7 @@ export const companyFields = [
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
/* company:update */
|
/* company:update */
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
|
@ -700,6 +701,7 @@ export const companyFields = [
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
/* company:get */
|
/* company:get */
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
|
@ -747,6 +749,7 @@ export const companyFields = [
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
/* company:getAll */
|
/* company:getAll */
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
|
@ -838,6 +841,7 @@ export const companyFields = [
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
/* company:delete */
|
/* company:delete */
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
|
@ -859,6 +863,7 @@ export const companyFields = [
|
||||||
default: '',
|
default: '',
|
||||||
description: 'Unique identifier for a particular company',
|
description: 'Unique identifier for a particular company',
|
||||||
},
|
},
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
/* company:getRecentlyCreated company:getRecentlyModifie */
|
/* company:getRecentlyCreated company:getRecentlyModifie */
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
|
@ -939,6 +944,7 @@ export const companyFields = [
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
/* company:searchByDomain */
|
/* company:searchByDomain */
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
|
@ -501,6 +501,7 @@ export const contactFields = [
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
/* contact:get */
|
/* contact:get */
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
|
@ -603,6 +604,7 @@ export const contactFields = [
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
/* contact:getAll */
|
/* contact:getAll */
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
|
@ -728,6 +730,7 @@ export const contactFields = [
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
/* contact:delete */
|
/* contact:delete */
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
|
@ -749,6 +752,7 @@ export const contactFields = [
|
||||||
default: '',
|
default: '',
|
||||||
description: 'Unique identifier for a particular contact',
|
description: 'Unique identifier for a particular contact',
|
||||||
},
|
},
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
/* contact:getRecentlyCreatedUpdated */
|
/* contact:getRecentlyCreatedUpdated */
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
|
@ -120,6 +120,7 @@ export const contactListFields = [
|
||||||
},
|
},
|
||||||
default: '',
|
default: '',
|
||||||
},
|
},
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
/* contactList:remove */
|
/* contactList:remove */
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
|
@ -301,6 +301,7 @@ export const formFields = [
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
/* form:getFields */
|
/* form:getFields */
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -63,7 +63,7 @@ export class Hubspot implements INodeType {
|
||||||
description: INodeTypeDescription = {
|
description: INodeTypeDescription = {
|
||||||
displayName: 'HubSpot',
|
displayName: 'HubSpot',
|
||||||
name: 'hubspot',
|
name: 'hubspot',
|
||||||
icon: 'file:hubspot.png',
|
icon: 'file:hubspot.svg',
|
||||||
group: ['output'],
|
group: ['output'],
|
||||||
version: 1,
|
version: 1,
|
||||||
subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
|
subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
|
||||||
|
|
|
@ -5,27 +5,36 @@ import {
|
||||||
|
|
||||||
import {
|
import {
|
||||||
IDataObject,
|
IDataObject,
|
||||||
|
ILoadOptionsFunctions,
|
||||||
|
INodePropertyOptions,
|
||||||
INodeType,
|
INodeType,
|
||||||
INodeTypeDescription,
|
INodeTypeDescription,
|
||||||
IWebhookResponseData,
|
IWebhookResponseData,
|
||||||
} from 'n8n-workflow';
|
} from 'n8n-workflow';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
companyFields,
|
||||||
|
contactFields,
|
||||||
|
dealFields,
|
||||||
hubspotApiRequest,
|
hubspotApiRequest,
|
||||||
|
propertyEvents,
|
||||||
} from './GenericFunctions';
|
} from './GenericFunctions';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
createHash,
|
createHash,
|
||||||
} from 'crypto';
|
} from 'crypto';
|
||||||
|
|
||||||
|
import {
|
||||||
|
capitalCase,
|
||||||
|
} from 'change-case';
|
||||||
|
|
||||||
export class HubspotTrigger implements INodeType {
|
export class HubspotTrigger implements INodeType {
|
||||||
description: INodeTypeDescription = {
|
description: INodeTypeDescription = {
|
||||||
displayName: 'HubSpot Trigger',
|
displayName: 'HubSpot Trigger',
|
||||||
name: 'hubspotTrigger',
|
name: 'hubspotTrigger',
|
||||||
icon: 'file:hubspot.png',
|
icon: 'file:hubspot.svg',
|
||||||
group: ['trigger'],
|
group: ['trigger'],
|
||||||
version: 1,
|
version: 1,
|
||||||
subtitle: '={{($parameter["appId"]) ? $parameter["event"] : ""}}',
|
|
||||||
description: 'Starts the workflow when HubSpot events occur.',
|
description: 'Starts the workflow when HubSpot events occur.',
|
||||||
defaults: {
|
defaults: {
|
||||||
name: 'Hubspot Trigger',
|
name: 'Hubspot Trigger',
|
||||||
|
@ -55,65 +64,71 @@ export class HubspotTrigger implements INodeType {
|
||||||
],
|
],
|
||||||
properties: [
|
properties: [
|
||||||
{
|
{
|
||||||
displayName: 'App ID',
|
displayName: 'Events',
|
||||||
name: 'appId',
|
name: 'eventsUi',
|
||||||
type: 'string',
|
type: 'fixedCollection',
|
||||||
default: '',
|
typeOptions: {
|
||||||
required: true,
|
multipleValues: true,
|
||||||
description: 'App ID',
|
|
||||||
},
|
},
|
||||||
|
placeholder: 'Add Event',
|
||||||
|
default: {},
|
||||||
|
options: [
|
||||||
{
|
{
|
||||||
displayName: 'Event',
|
displayName: 'Event',
|
||||||
name: 'event',
|
name: 'eventValues',
|
||||||
|
values: [
|
||||||
|
{
|
||||||
|
displayName: 'Name',
|
||||||
|
name: 'name',
|
||||||
type: 'options',
|
type: 'options',
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
name: 'contact.creation',
|
name: 'Contact Created',
|
||||||
value: 'contact.creation',
|
value: 'contact.creation',
|
||||||
description: `To get notified if any contact is created in a customer's account.`,
|
description: `To get notified if any contact is created in a customer's account.`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'contact.deletion',
|
name: 'Contact Deleted',
|
||||||
value: 'contact.deletion',
|
value: 'contact.deletion',
|
||||||
description: `To get notified if any contact is deleted in a customer's account.`,
|
description: `To get notified if any contact is deleted in a customer's account.`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'contact.privacyDeletion',
|
name: 'Contact Privacy Deleted',
|
||||||
value: 'contact.privacyDeletion',
|
value: 'contact.privacyDeletion',
|
||||||
description: `To get notified if a contact is deleted for privacy compliance reasons. `,
|
description: `To get notified if a contact is deleted for privacy compliance reasons. `,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'contact.propertyChange',
|
name: 'Contact Property Changed',
|
||||||
value: 'contact.propertyChange',
|
value: 'contact.propertyChange',
|
||||||
description: `to get notified if a specified property is changed for any contact in a customer's account. `,
|
description: `to get notified if a specified property is changed for any contact in a customer's account. `,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'company.creation',
|
name: 'Company Created',
|
||||||
value: 'company.creation',
|
value: 'company.creation',
|
||||||
description: `To get notified if any company is created in a customer's account.`,
|
description: `To get notified if any company is created in a customer's account.`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'company.deletion',
|
name: 'Company Deleted',
|
||||||
value: 'company.deletion',
|
value: 'company.deletion',
|
||||||
description: `To get notified if any company is deleted in a customer's account.`,
|
description: `To get notified if any company is deleted in a customer's account.`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'company.propertyChange',
|
name: 'Company Property Changed',
|
||||||
value: 'company.propertyChange',
|
value: 'company.propertyChange',
|
||||||
description: `To get notified if a specified property is changed for any company in a customer's account.`,
|
description: `To get notified if a specified property is changed for any company in a customer's account.`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'deal.creation',
|
name: 'Deal Created',
|
||||||
value: 'deal.creation',
|
value: 'deal.creation',
|
||||||
description: `To get notified if any deal is created in a customer's account.`,
|
description: `To get notified if any deal is created in a customer's account.`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'deal.deletion',
|
name: 'Deal Deleted',
|
||||||
value: 'deal.deletion',
|
value: 'deal.deletion',
|
||||||
description: `To get notified if any deal is deleted in a customer's account.`,
|
description: `To get notified if any deal is deleted in a customer's account.`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'deal.propertyChange',
|
name: 'Deal Property Changed',
|
||||||
value: 'deal.propertyChange',
|
value: 'deal.propertyChange',
|
||||||
description: `To get notified if a specified property is changed for any deal in a customer's account.`,
|
description: `To get notified if a specified property is changed for any deal in a customer's account.`,
|
||||||
},
|
},
|
||||||
|
@ -124,12 +139,47 @@ export class HubspotTrigger implements INodeType {
|
||||||
{
|
{
|
||||||
displayName: 'Property',
|
displayName: 'Property',
|
||||||
name: 'property',
|
name: 'property',
|
||||||
type: 'string',
|
type: 'options',
|
||||||
|
typeOptions: {
|
||||||
|
loadOptionsMethod: 'getContactProperties',
|
||||||
|
},
|
||||||
displayOptions: {
|
displayOptions: {
|
||||||
show: {
|
show: {
|
||||||
event: [
|
name: [
|
||||||
'contact.propertyChange',
|
'contact.propertyChange',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
default: '',
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Property',
|
||||||
|
name: 'property',
|
||||||
|
type: 'options',
|
||||||
|
typeOptions: {
|
||||||
|
loadOptionsMethod: 'getCompanyProperties',
|
||||||
|
},
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
name: [
|
||||||
'company.propertyChange',
|
'company.propertyChange',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
default: '',
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Property',
|
||||||
|
name: 'property',
|
||||||
|
type: 'options',
|
||||||
|
typeOptions: {
|
||||||
|
loadOptionsMethod: 'getDealProperties',
|
||||||
|
},
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
name: [
|
||||||
'deal.propertyChange',
|
'deal.propertyChange',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
@ -137,6 +187,10 @@ export class HubspotTrigger implements INodeType {
|
||||||
default: '',
|
default: '',
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
displayName: 'Additional Fields',
|
displayName: 'Additional Fields',
|
||||||
name: 'additionalFields',
|
name: 'additionalFields',
|
||||||
|
@ -156,7 +210,62 @@ export class HubspotTrigger implements INodeType {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
methods = {
|
||||||
|
loadOptions: {
|
||||||
|
// Get all the available contacts to display them to user so that he can
|
||||||
|
// select them easily
|
||||||
|
async getContactProperties(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
|
||||||
|
const returnData: INodePropertyOptions[] = [];
|
||||||
|
for (const field of contactFields) {
|
||||||
|
returnData.push({
|
||||||
|
name: capitalCase(field.label),
|
||||||
|
value: field.id,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
returnData.sort((a, b) => {
|
||||||
|
if (a.name < b.name) { return -1; }
|
||||||
|
if (a.name > b.name) { return 1; }
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
return returnData;
|
||||||
|
},
|
||||||
|
// Get all the available companies to display them to user so that he can
|
||||||
|
// select them easily
|
||||||
|
async getCompanyProperties(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
|
||||||
|
const returnData: INodePropertyOptions[] = [];
|
||||||
|
for (const field of companyFields) {
|
||||||
|
returnData.push({
|
||||||
|
name: capitalCase(field.label),
|
||||||
|
value: field.id,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
returnData.sort((a, b) => {
|
||||||
|
if (a.name < b.name) { return -1; }
|
||||||
|
if (a.name > b.name) { return 1; }
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
return returnData;
|
||||||
|
},
|
||||||
|
// Get all the available deals to display them to user so that he can
|
||||||
|
// select them easily
|
||||||
|
async getDealProperties(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
|
||||||
|
const returnData: INodePropertyOptions[] = [];
|
||||||
|
for (const field of dealFields) {
|
||||||
|
returnData.push({
|
||||||
|
name: capitalCase(field.label),
|
||||||
|
value: field.id,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
returnData.sort((a, b) => {
|
||||||
|
if (a.name < b.name) { return -1; }
|
||||||
|
if (a.name > b.name) { return 1; }
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
return returnData;
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
// @ts-ignore (because of request)
|
// @ts-ignore (because of request)
|
||||||
|
@ -165,81 +274,79 @@ export class HubspotTrigger implements INodeType {
|
||||||
async checkExists(this: IHookFunctions): Promise<boolean> {
|
async checkExists(this: IHookFunctions): Promise<boolean> {
|
||||||
// Check all the webhooks which exist already if it is identical to the
|
// Check all the webhooks which exist already if it is identical to the
|
||||||
// one that is supposed to get created.
|
// one that is supposed to get created.
|
||||||
const app = parseInt(this.getNodeParameter('appId') as string, 10);
|
const currentWebhookUrl = this.getNodeWebhookUrl('default') as string;
|
||||||
const event = this.getNodeParameter('event') as string;
|
const { appId } = this.getCredentials('hubspotDeveloperApi') as IDataObject;
|
||||||
const webhookUrlUi = this.getNodeWebhookUrl('default') as string;
|
|
||||||
let endpoint = `/webhooks/v1/${app}/settings`;
|
try {
|
||||||
const { webhookUrl , appId } = await hubspotApiRequest.call(this, 'GET', endpoint, {});
|
const { targetUrl } = await hubspotApiRequest.call(this, 'GET', `/webhooks/v3/${appId}/settings`, {});
|
||||||
endpoint = `/webhooks/v1/${app}/subscriptions`;
|
if (targetUrl !== currentWebhookUrl) {
|
||||||
const subscriptions = await hubspotApiRequest.call(this, 'GET', endpoint, {});
|
throw new Error(`The APP ID ${appId} already has a target url ${targetUrl}. Delete it or use another APP ID before executing the trigger. Due to Hubspot API limitations, you can have just one trigger per APP.`);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
if (error.statusCode === 404) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// if the app is using the current webhook url. Delete everything and create it again with the current events
|
||||||
|
|
||||||
|
const { results: subscriptions } = await hubspotApiRequest.call(this, 'GET', `/webhooks/v3/${appId}/subscriptions`, {});
|
||||||
|
|
||||||
|
// delete all subscriptions
|
||||||
for (const subscription of subscriptions) {
|
for (const subscription of subscriptions) {
|
||||||
if (webhookUrl === webhookUrlUi
|
await hubspotApiRequest.call(this, 'DELETE', `/webhooks/v3/${appId}/subscriptions/${subscription.id}`, {});
|
||||||
&& appId === app
|
|
||||||
&& subscription.subscriptionDetails.subscriptionType === event
|
|
||||||
&& subscription.enabled === true) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await hubspotApiRequest.call(this, 'DELETE', `/webhooks/v3/${appId}/settings`, {});
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
async create(this: IHookFunctions): Promise<boolean> {
|
async create(this: IHookFunctions): Promise<boolean> {
|
||||||
const webhookUrl = this.getNodeWebhookUrl('default');
|
const webhookUrl = this.getNodeWebhookUrl('default');
|
||||||
const app = this.getNodeParameter('appId') as string;
|
const { appId } = this.getCredentials('hubspotDeveloperApi') as IDataObject;
|
||||||
const event = this.getNodeParameter('event') as string;
|
const events = (this.getNodeParameter('eventsUi') as IDataObject || {}).eventValues as IDataObject[] || [];
|
||||||
const additionalFields = this.getNodeParameter('additionalFields') as IDataObject;
|
const additionalFields = this.getNodeParameter('additionalFields') as IDataObject;
|
||||||
const propertyEvents = [
|
let endpoint = `/webhooks/v3/${appId}/settings`;
|
||||||
'contact.propertyChange',
|
|
||||||
'company.propertyChange',
|
|
||||||
'deal.propertyChange',
|
|
||||||
];
|
|
||||||
let endpoint = `/webhooks/v1/${app}/settings`;
|
|
||||||
let body: IDataObject = {
|
let body: IDataObject = {
|
||||||
webhookUrl,
|
targetUrl: webhookUrl,
|
||||||
maxConcurrentRequests: additionalFields.maxConcurrentRequests || 5,
|
maxConcurrentRequests: additionalFields.maxConcurrentRequests || 5,
|
||||||
};
|
};
|
||||||
|
|
||||||
await hubspotApiRequest.call(this, 'PUT', endpoint, body);
|
await hubspotApiRequest.call(this, 'PUT', endpoint, body);
|
||||||
|
|
||||||
endpoint = `/webhooks/v1/${app}/subscriptions`;
|
endpoint = `/webhooks/v3/${appId}/subscriptions`;
|
||||||
|
|
||||||
|
if (Array.isArray(events) && events.length === 0) {
|
||||||
|
throw new Error(`You must define at least one event`);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const event of events) {
|
||||||
body = {
|
body = {
|
||||||
subscriptionDetails: {
|
eventType: event.name,
|
||||||
subscriptionType: event,
|
active: true,
|
||||||
},
|
|
||||||
enabled: true,
|
|
||||||
};
|
};
|
||||||
if (propertyEvents.includes(event)) {
|
if (propertyEvents.includes(event.name as string)) {
|
||||||
const property = this.getNodeParameter('property') as string;
|
const property = event.property;
|
||||||
//@ts-ignore
|
body.propertyName = property;
|
||||||
body.subscriptionDetails.propertyName = property;
|
}
|
||||||
|
await hubspotApiRequest.call(this, 'POST', endpoint, body);
|
||||||
}
|
}
|
||||||
|
|
||||||
const responseData = await hubspotApiRequest.call(this, 'POST', endpoint, body);
|
|
||||||
|
|
||||||
if (responseData.id === undefined) {
|
|
||||||
// Required data is missing so was not successful
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const webhookData = this.getWorkflowStaticData('node');
|
|
||||||
webhookData.webhookId = responseData.id as string;
|
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
async delete(this: IHookFunctions): Promise<boolean> {
|
async delete(this: IHookFunctions): Promise<boolean> {
|
||||||
const webhookData = this.getWorkflowStaticData('node');
|
const { appId } = this.getCredentials('hubspotDeveloperApi') as IDataObject;
|
||||||
const app = this.getNodeParameter('appId') as string;
|
|
||||||
if (webhookData.webhookId !== undefined) {
|
|
||||||
const endpoint = `/webhooks/v1/${app}/subscriptions/${webhookData.webhookId}`;
|
|
||||||
|
|
||||||
const body = {};
|
const { results: subscriptions } = await hubspotApiRequest.call(this, 'GET', `/webhooks/v3/${appId}/subscriptions`, {});
|
||||||
|
|
||||||
|
for (const subscription of subscriptions) {
|
||||||
|
await hubspotApiRequest.call(this, 'DELETE', `/webhooks/v3/${appId}/subscriptions/${subscription.id}`, {});
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await hubspotApiRequest.call(this, 'DELETE', endpoint, body);
|
await hubspotApiRequest.call(this, 'DELETE', `/webhooks/v3/${appId}/settings`, {});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// Remove from the static workflow data so that it is clear
|
|
||||||
// that no webhooks are registred anymore
|
|
||||||
delete webhookData.webhookId;
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -247,7 +247,7 @@ export const ticketFields = [
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
default: '',
|
default: '',
|
||||||
description: 'Unique identifier for a particular ticket',
|
description: 'Unique identifier for a particular ticket.',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
displayName: 'Update Fields',
|
displayName: 'Update Fields',
|
||||||
|
@ -274,7 +274,7 @@ export const ticketFields = [
|
||||||
loadOptionsMethod: 'getCompanies',
|
loadOptionsMethod: 'getCompanies',
|
||||||
},
|
},
|
||||||
default: [],
|
default: [],
|
||||||
description: 'Companies associated with the ticket',
|
description: 'Companies associated with the ticket.',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
displayName: 'Contact Ids',
|
displayName: 'Contact Ids',
|
||||||
|
@ -284,7 +284,7 @@ export const ticketFields = [
|
||||||
loadOptionsMethod: 'getContacts',
|
loadOptionsMethod: 'getContacts',
|
||||||
},
|
},
|
||||||
default: [],
|
default: [],
|
||||||
description: 'Contact associated with the ticket',
|
description: 'Contact associated with the ticket.',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
displayName: 'Category',
|
displayName: 'Category',
|
||||||
|
@ -294,21 +294,21 @@ export const ticketFields = [
|
||||||
loadOptionsMethod: 'getTicketCategories',
|
loadOptionsMethod: 'getTicketCategories',
|
||||||
},
|
},
|
||||||
default: '',
|
default: '',
|
||||||
description: 'Main reason customer reached out for help',
|
description: 'Main reason customer reached out for help.',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
displayName: 'Close Date',
|
displayName: 'Close Date',
|
||||||
name: 'closeDate',
|
name: 'closeDate',
|
||||||
type: 'dateTime',
|
type: 'dateTime',
|
||||||
default: '',
|
default: '',
|
||||||
description: 'The date the ticket was closed',
|
description: 'The date the ticket was closed.',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
displayName: 'Create Date',
|
displayName: 'Create Date',
|
||||||
name: 'createDate',
|
name: 'createDate',
|
||||||
type: 'dateTime',
|
type: 'dateTime',
|
||||||
default: '',
|
default: '',
|
||||||
description: 'the date the ticket was created',
|
description: 'The date the ticket was created.',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
displayName: 'Description',
|
displayName: 'Description',
|
||||||
|
@ -358,7 +358,7 @@ export const ticketFields = [
|
||||||
loadOptionsMethod: 'getTicketSources',
|
loadOptionsMethod: 'getTicketSources',
|
||||||
},
|
},
|
||||||
default: '',
|
default: '',
|
||||||
description: 'Channel where ticket was originally submitted',
|
description: 'Channel where ticket was originally submitted.',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
displayName: 'Ticket Name',
|
displayName: 'Ticket Name',
|
||||||
|
@ -380,6 +380,7 @@ export const ticketFields = [
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
/* ticket:get */
|
/* ticket:get */
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
|
@ -447,6 +448,7 @@ export const ticketFields = [
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
/* ticket:getAll */
|
/* ticket:getAll */
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
|
@ -531,6 +533,7 @@ export const ticketFields = [
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
/* ticket:delete */
|
/* ticket:delete */
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 1,022 B |
1
packages/nodes-base/nodes/Hubspot/hubspot.svg
Normal file
1
packages/nodes-base/nodes/Hubspot/hubspot.svg
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 62.883 69.883" fill="#fff" fill-rule="evenodd" stroke="#000" stroke-linecap="round" stroke-linejoin="round"><use xlink:href="#A" x="2.442" y="2.442"/><symbol id="A" overflow="visible"><path d="M55.504 30.401a16.26 16.26 0 0 0-5.904-5.864c-1.865-1.084-3.794-1.773-5.972-2.07v-7.798c2.161-.895 3.558-3.018 3.525-5.357a5.86 5.86 0 0 0-5.859-5.889 5.91 5.91 0 0 0-5.908 5.889c0 2.393 1.27 4.434 3.452 5.357v7.754c-1.808.262-3.562.812-5.195 1.631L12.769 8.247c.146-.552.273-1.123.273-1.724C13.042 2.92 10.122 0 6.519 0A6.52 6.52 0 0 0 0 6.524c0 3.604 2.92 6.524 6.524 6.524a6.47 6.47 0 0 0 3.35-.952l1.367 1.035 18.726 13.501c-.991.908-1.914 1.943-2.651 3.105-1.494 2.368-2.407 4.971-2.407 7.813v.586c.007 1.927.354 3.838 1.025 5.645.566 1.543 1.396 2.949 2.427 4.219l-6.221 6.235c-1.841-.684-3.906-.23-5.298 1.162-.947.942-1.48 2.227-1.475 3.565s.527 2.612 1.479 3.564 2.227 1.48 3.565 1.48a5.01 5.01 0 0 0 3.565-1.48c.942-.952 1.479-2.227 1.475-3.564a5.03 5.03 0 0 0-.234-1.514l6.426-6.426a16.09 16.09 0 0 0 2.856 1.563 16.7 16.7 0 0 0 6.685 1.406h.439a15.76 15.76 0 0 0 7.627-1.929 15.77 15.77 0 0 0 5.977-5.63c1.499-2.393 2.319-5.044 2.319-7.959v-.146c0-2.866-.664-5.508-2.051-7.93zm-7.847 13.487c-1.743 1.938-3.75 3.135-6.016 3.135h-.43c-1.294 0-2.564-.356-3.799-1.011a8.79 8.79 0 0 1-3.33-3.032c-.898-1.27-1.387-2.656-1.387-4.126v-.439c0-1.445.278-2.817.977-4.111.747-1.465 1.758-2.515 3.101-3.389a7.6 7.6 0 0 1 4.297-1.294h.147c1.416 0 2.769.278 4.038.928 1.286.677 2.378 1.67 3.174 2.886a9.18 9.18 0 0 1 1.421 4.053l.034.913c0 1.987-.762 3.828-2.28 5.498z" stroke="none" fill="#f8761f" fill-rule="nonzero"/></symbol></svg>
|
After Width: | Height: | Size: 1.7 KiB |
Loading…
Reference in a new issue