mirror of
https://github.com/n8n-io/n8n.git
synced 2024-12-27 13:39:44 -08:00
6dcdb30bf4
* ✏️ Alphabetize lint rules * 🔥 Remove duplicates * ⚡ Update `lintfix` script * 👕 Apply `node-param-operation-without-no-data-expression` (#3329) * 👕 Apply `node-param-operation-without-no-data-expression` * 👕 Add exceptions * 👕 Apply `node-param-description-weak` (#3328) Co-authored-by: Iván Ovejero <ivov.src@gmail.com> * 👕 Apply `node-param-option-value-duplicate` (#3331) * 👕 Apply `node-param-description-miscased-json` (#3337) * 👕 Apply `node-param-display-name-excess-inner-whitespace` (#3335) Co-authored-by: Iván Ovejero <ivov.src@gmail.com> * 👕 Apply `node-param-type-options-missing-from-limit` (#3336) * Rule workig as intended * ✏️ Uncomment rules Co-authored-by: Iván Ovejero <ivov.src@gmail.com> * 👕 Apply `node-param-option-name-duplicate` (#3338) Co-authored-by: Iván Ovejero <ivov.src@gmail.com> * 👕 Apply `node-param-description-wrong-for-simplify` (#3334) * ⚡ fix * ⚡ exceptions * ⚡ changed rule ignoring from file to line * 👕 Apply `node-param-resource-without-no-data-expression` (#3339) * 👕 Apply `node-param-display-name-untrimmed` (#3341) * 👕 Apply `node-param-display-name-miscased-id` (#3340) Co-authored-by: Iván Ovejero <ivov.src@gmail.com> * 👕 Apply `node-param-resource-with-plural-option` (#3342) * 👕 Apply `node-param-description-wrong-for-upsert` (#3333) * ⚡ fix * ⚡ replaced record with contact in description * ⚡ fix Co-authored-by: Iván Ovejero <ivov.src@gmail.com> * 👕 Apply `node-param-option-description-identical-to-name` (#3343) * 👕 Apply `node-param-option-name-containing-star` (#3347) * 👕 Apply `node-param-display-name-wrong-for-update-fields` (#3348) * 👕 Apply `node-param-option-name-wrong-for-get-all` (#3345) * ⚡ fix * ⚡ exceptions * 👕 Apply node-param-display-name-wrong-for-simplify (#3344) * Rule working as intended * Uncomented other rules * 👕 Undo and add exceptions Co-authored-by: Iván Ovejero <ivov.src@gmail.com> * ⚡ Alphabetize lint rules * ⚡ Restore `lintfix` script Co-authored-by: Michael Kret <88898367+michael-radency@users.noreply.github.com> Co-authored-by: agobrech <45268029+agobrech@users.noreply.github.com>
337 lines
8.5 KiB
TypeScript
337 lines
8.5 KiB
TypeScript
import {
|
|
IExecuteFunctions,
|
|
} from 'n8n-core';
|
|
|
|
import {
|
|
IDataObject,
|
|
ILoadOptionsFunctions,
|
|
INodeExecutionData,
|
|
INodePropertyOptions,
|
|
INodeType,
|
|
INodeTypeDescription,
|
|
NodeApiError,
|
|
NodeOperationError,
|
|
} from 'n8n-workflow';
|
|
|
|
import {
|
|
iterableApiRequest,
|
|
} from './GenericFunctions';
|
|
|
|
import {
|
|
eventFields,
|
|
eventOperations,
|
|
} from './EventDescription';
|
|
|
|
import {
|
|
userFields,
|
|
userOperations,
|
|
} from './UserDescription';
|
|
|
|
import {
|
|
userListFields,
|
|
userListOperations,
|
|
} from './UserListDescription';
|
|
|
|
import moment from 'moment-timezone';
|
|
|
|
export class Iterable implements INodeType {
|
|
description: INodeTypeDescription = {
|
|
displayName: 'Iterable',
|
|
name: 'iterable',
|
|
icon: 'file:iterable.png',
|
|
group: ['input'],
|
|
version: 1,
|
|
subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
|
|
description: 'Consume Iterable API',
|
|
defaults: {
|
|
name: 'Iterable',
|
|
},
|
|
inputs: ['main'],
|
|
outputs: ['main'],
|
|
credentials: [
|
|
{
|
|
name: 'iterableApi',
|
|
required: true,
|
|
},
|
|
],
|
|
properties: [
|
|
{
|
|
displayName: 'Resource',
|
|
name: 'resource',
|
|
type: 'options',
|
|
noDataExpression: true,
|
|
options: [
|
|
{
|
|
name: 'Event',
|
|
value: 'event',
|
|
},
|
|
{
|
|
name: 'User',
|
|
value: 'user',
|
|
},
|
|
{
|
|
name: 'User List',
|
|
value: 'userList',
|
|
},
|
|
],
|
|
default: 'user',
|
|
},
|
|
...eventOperations,
|
|
...eventFields,
|
|
...userOperations,
|
|
...userFields,
|
|
...userListOperations,
|
|
...userListFields,
|
|
],
|
|
};
|
|
|
|
methods = {
|
|
loadOptions: {
|
|
// Get all the lists available channels
|
|
async getLists(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
|
|
const { lists } = await iterableApiRequest.call(this, 'GET', '/lists');
|
|
const returnData: INodePropertyOptions[] = [];
|
|
for (const list of lists) {
|
|
returnData.push({
|
|
name: list.name,
|
|
value: list.id,
|
|
});
|
|
}
|
|
return returnData;
|
|
},
|
|
},
|
|
};
|
|
|
|
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
|
|
const items = this.getInputData();
|
|
const returnData: IDataObject[] = [];
|
|
const length = items.length;
|
|
const timezone = this.getTimezone();
|
|
const qs: IDataObject = {};
|
|
let responseData;
|
|
const resource = this.getNodeParameter('resource', 0) as string;
|
|
const operation = this.getNodeParameter('operation', 0) as string;
|
|
|
|
if (resource === 'event') {
|
|
if (operation === 'track') {
|
|
// https://api.iterable.com/api/docs#events_trackBulk
|
|
const events = [];
|
|
|
|
for (let i = 0; i < length; i++) {
|
|
|
|
const name = this.getNodeParameter('name', i) as string;
|
|
|
|
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
|
|
|
|
if (!additionalFields.email && !additionalFields.id) {
|
|
throw new NodeOperationError(this.getNode(), 'Either email or userId must be passed in to identify the user. Please add one of both via "Additional Fields". If both are passed in, email takes precedence.');
|
|
}
|
|
|
|
const body: IDataObject = {
|
|
eventName: name,
|
|
};
|
|
|
|
Object.assign(body, additionalFields);
|
|
|
|
if (body.dataFieldsUi) {
|
|
const dataFields = (body.dataFieldsUi as IDataObject).dataFieldValues as IDataObject[];
|
|
const data: IDataObject = {};
|
|
for (const dataField of dataFields) {
|
|
data[dataField.key as string] = dataField.value;
|
|
}
|
|
body.dataFields = data;
|
|
delete body.dataFieldsUi;
|
|
}
|
|
|
|
if (body.createdAt) {
|
|
body.createdAt = moment.tz(body.createdAt, timezone).unix();
|
|
}
|
|
|
|
events.push(body);
|
|
}
|
|
|
|
responseData = await iterableApiRequest.call(this, 'POST', '/events/trackBulk', { events });
|
|
|
|
returnData.push(responseData);
|
|
}
|
|
}
|
|
|
|
if (resource === 'user') {
|
|
if (operation === 'upsert') {
|
|
// https://api.iterable.com/api/docs#users_updateUser
|
|
for (let i = 0; i < length; i++) {
|
|
|
|
const identifier = this.getNodeParameter('identifier', i) as string;
|
|
|
|
const value = this.getNodeParameter('value', i) as string;
|
|
|
|
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
|
|
|
|
const body: IDataObject = {};
|
|
|
|
if (identifier === 'email') {
|
|
body.email = value;
|
|
} else {
|
|
body.preferUserId = this.getNodeParameter('preferUserId', i) as boolean;
|
|
body.userId = value;
|
|
}
|
|
|
|
Object.assign(body, additionalFields);
|
|
|
|
if (body.dataFieldsUi) {
|
|
const dataFields = (body.dataFieldsUi as IDataObject).dataFieldValues as IDataObject[];
|
|
const data: IDataObject = {};
|
|
for (const dataField of dataFields) {
|
|
data[dataField.key as string] = dataField.value;
|
|
}
|
|
body.dataFields = data;
|
|
delete body.dataFieldsUi;
|
|
}
|
|
|
|
responseData = await iterableApiRequest.call(this, 'POST', '/users/update', body);
|
|
|
|
if (this.continueOnFail() === false) {
|
|
if (responseData.code !== 'Success') {
|
|
throw new NodeOperationError(this.getNode(),
|
|
`Iterable error response [400]: ${responseData.msg}`,
|
|
);
|
|
}
|
|
}
|
|
|
|
returnData.push(responseData);
|
|
}
|
|
}
|
|
|
|
if (operation === 'delete') {
|
|
// https://api.iterable.com/api/docs#users_delete
|
|
// https://api.iterable.com/api/docs#users_delete_0
|
|
for (let i = 0; i < length; i++) {
|
|
const by = this.getNodeParameter('by', i) as string;
|
|
|
|
let endpoint;
|
|
|
|
if (by === 'email') {
|
|
const email = this.getNodeParameter('email', i) as string;
|
|
endpoint = `/users/${email}`;
|
|
} else {
|
|
const userId = this.getNodeParameter('userId', i) as string;
|
|
endpoint = `/users/byUserId/${userId}`;
|
|
}
|
|
|
|
responseData = await iterableApiRequest.call(this, 'DELETE', endpoint);
|
|
|
|
if (this.continueOnFail() === false) {
|
|
if (responseData.code !== 'Success') {
|
|
throw new NodeApiError(this.getNode(), responseData);
|
|
}
|
|
}
|
|
|
|
returnData.push(responseData);
|
|
}
|
|
}
|
|
|
|
if (operation === 'get') {
|
|
// https://api.iterable.com/api/docs#users_getUser
|
|
// https://api.iterable.com/api/docs#users_getUserById
|
|
for (let i = 0; i < length; i++) {
|
|
|
|
const by = this.getNodeParameter('by', i) as string;
|
|
|
|
let endpoint;
|
|
|
|
if (by === 'email') {
|
|
const email = this.getNodeParameter('email', i) as string;
|
|
endpoint = `/users/getByEmail`;
|
|
qs.email = email;
|
|
} else {
|
|
const userId = this.getNodeParameter('userId', i) as string;
|
|
endpoint = `/users/byUserId/${userId}`;
|
|
}
|
|
|
|
responseData = await iterableApiRequest.call(this, 'GET', endpoint, {}, qs);
|
|
|
|
if (this.continueOnFail() === false) {
|
|
if (Object.keys(responseData).length === 0) {
|
|
throw new NodeApiError(this.getNode(), responseData,
|
|
{ message: `User not found`, httpCode: '404' },
|
|
);
|
|
}
|
|
}
|
|
|
|
responseData = responseData.user || {};
|
|
returnData.push(responseData);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (resource === 'userList') {
|
|
if (operation === 'add') {
|
|
//https://api.iterable.com/api/docs#lists_subscribe
|
|
const listId = this.getNodeParameter('listId', 0) as string;
|
|
|
|
const identifier = this.getNodeParameter('identifier', 0) as string;
|
|
|
|
const body: IDataObject = {
|
|
listId: parseInt(listId, 10),
|
|
subscribers: [],
|
|
};
|
|
|
|
const subscribers: IDataObject[] = [];
|
|
|
|
for (let i = 0; i < length; i++) {
|
|
|
|
const value = this.getNodeParameter('value', i) as string;
|
|
|
|
if (identifier === 'email') {
|
|
subscribers.push({ email: value });
|
|
} else {
|
|
subscribers.push({ userId: value });
|
|
}
|
|
}
|
|
|
|
body.subscribers = subscribers;
|
|
|
|
responseData = await iterableApiRequest.call(this, 'POST', '/lists/subscribe', body);
|
|
|
|
returnData.push(responseData);
|
|
}
|
|
|
|
if (operation === 'remove') {
|
|
//https://api.iterable.com/api/docs#lists_unsubscribe
|
|
const listId = this.getNodeParameter('listId', 0) as string;
|
|
|
|
const identifier = this.getNodeParameter('identifier', 0) as string;
|
|
|
|
const additionalFields = this.getNodeParameter('additionalFields', 0) as IDataObject;
|
|
|
|
const body: IDataObject = {
|
|
listId: parseInt(listId, 10),
|
|
subscribers: [],
|
|
campaignId: additionalFields.campaignId as number,
|
|
channelUnsubscribe: additionalFields.channelUnsubscribe as boolean,
|
|
};
|
|
|
|
const subscribers: IDataObject[] = [];
|
|
|
|
for (let i = 0; i < length; i++) {
|
|
|
|
const value = this.getNodeParameter('value', i) as string;
|
|
|
|
if (identifier === 'email') {
|
|
subscribers.push({ email: value });
|
|
} else {
|
|
subscribers.push({ userId: value });
|
|
}
|
|
}
|
|
|
|
body.subscribers = subscribers;
|
|
|
|
responseData = await iterableApiRequest.call(this, 'POST', '/lists/unsubscribe', body);
|
|
|
|
returnData.push(responseData);
|
|
}
|
|
}
|
|
return [this.helpers.returnJsonArray(returnData)];
|
|
}
|
|
}
|