@growsalesai/n8n-nodes-ycloud 2.5.0 → 2.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/dist/nodes/YCloud/YCloudAutoResponder.node.d.ts +5 -0
  2. package/dist/nodes/YCloud/YCloudAutoResponder.node.js +236 -0
  3. package/dist/nodes/YCloud/YCloudAutoResponder.node.js.map +1 -0
  4. package/dist/nodes/YCloud/YCloudContactOnboarding.node.d.ts +5 -0
  5. package/dist/nodes/YCloud/YCloudContactOnboarding.node.js +195 -0
  6. package/dist/nodes/YCloud/YCloudContactOnboarding.node.js.map +1 -0
  7. package/dist/nodes/YCloud/YCloudContactUpsert.node.d.ts +5 -0
  8. package/dist/nodes/YCloud/YCloudContactUpsert.node.js +120 -0
  9. package/dist/nodes/YCloud/YCloudContactUpsert.node.js.map +1 -0
  10. package/dist/nodes/YCloud/YCloudInboundRouter.node.d.ts +5 -0
  11. package/dist/nodes/YCloud/YCloudInboundRouter.node.js +100 -0
  12. package/dist/nodes/YCloud/YCloudInboundRouter.node.js.map +1 -0
  13. package/dist/nodes/YCloud/YCloudMessageStatusRouter.node.d.ts +5 -0
  14. package/dist/nodes/YCloud/YCloudMessageStatusRouter.node.js +51 -0
  15. package/dist/nodes/YCloud/YCloudMessageStatusRouter.node.js.map +1 -0
  16. package/dist/nodes/YCloud/YCloudOptHandler.node.d.ts +5 -0
  17. package/dist/nodes/YCloud/YCloudOptHandler.node.js +136 -0
  18. package/dist/nodes/YCloud/YCloudOptHandler.node.js.map +1 -0
  19. package/dist/nodes/YCloud/YCloudTagCampaign.node.d.ts +5 -0
  20. package/dist/nodes/YCloud/YCloudTagCampaign.node.js +178 -0
  21. package/dist/nodes/YCloud/YCloudTagCampaign.node.js.map +1 -0
  22. package/dist/nodes/YCloud/sequences/YCloudAutoResponder.node.d.ts +5 -0
  23. package/dist/nodes/YCloud/sequences/YCloudAutoResponder.node.js +241 -0
  24. package/dist/nodes/YCloud/sequences/YCloudAutoResponder.node.js.map +1 -0
  25. package/dist/nodes/YCloud/sequences/YCloudContactOnboarding.node.d.ts +5 -0
  26. package/dist/nodes/YCloud/sequences/YCloudContactOnboarding.node.js +200 -0
  27. package/dist/nodes/YCloud/sequences/YCloudContactOnboarding.node.js.map +1 -0
  28. package/dist/nodes/YCloud/sequences/YCloudContactUpsert.node.d.ts +5 -0
  29. package/dist/nodes/YCloud/sequences/YCloudContactUpsert.node.js +125 -0
  30. package/dist/nodes/YCloud/sequences/YCloudContactUpsert.node.js.map +1 -0
  31. package/dist/nodes/YCloud/sequences/YCloudInboundRouter.node.d.ts +5 -0
  32. package/dist/nodes/YCloud/sequences/YCloudInboundRouter.node.js +105 -0
  33. package/dist/nodes/YCloud/sequences/YCloudInboundRouter.node.js.map +1 -0
  34. package/dist/nodes/YCloud/sequences/YCloudMessageStatusRouter.node.d.ts +5 -0
  35. package/dist/nodes/YCloud/sequences/YCloudMessageStatusRouter.node.js +56 -0
  36. package/dist/nodes/YCloud/sequences/YCloudMessageStatusRouter.node.js.map +1 -0
  37. package/dist/nodes/YCloud/sequences/YCloudOptHandler.node.d.ts +5 -0
  38. package/dist/nodes/YCloud/sequences/YCloudOptHandler.node.js +141 -0
  39. package/dist/nodes/YCloud/sequences/YCloudOptHandler.node.js.map +1 -0
  40. package/dist/nodes/YCloud/sequences/YCloudTagCampaign.node.d.ts +5 -0
  41. package/dist/nodes/YCloud/sequences/YCloudTagCampaign.node.js +183 -0
  42. package/dist/nodes/YCloud/sequences/YCloudTagCampaign.node.js.map +1 -0
  43. package/package.json +9 -2
@@ -0,0 +1,5 @@
1
+ import type { IExecuteFunctions, INodeExecutionData, INodeType, INodeTypeDescription } from 'n8n-workflow';
2
+ export declare class YCloudAutoResponder implements INodeType {
3
+ description: INodeTypeDescription;
4
+ execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]>;
5
+ }
@@ -0,0 +1,236 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.YCloudAutoResponder = void 0;
4
+ const n8n_workflow_1 = require("n8n-workflow");
5
+ const GenericFunctions_1 = require("./GenericFunctions");
6
+ class YCloudAutoResponder {
7
+ constructor() {
8
+ this.description = {
9
+ displayName: 'YCloud Auto Responder',
10
+ name: 'yCloudAutoResponder',
11
+ icon: 'file:logo-ycloud.png',
12
+ group: ['output'],
13
+ version: 1,
14
+ subtitle: 'Matched / No Match',
15
+ description: 'Retrieves the sender\'s contact profile, checks their tags and custom attributes against a set of rules, and sends the first matching WhatsApp template. Routes to "Matched" or "No Match".',
16
+ defaults: { name: 'YCloud Auto Responder' },
17
+ inputs: [n8n_workflow_1.NodeConnectionTypes.Main],
18
+ outputs: [n8n_workflow_1.NodeConnectionTypes.Main, n8n_workflow_1.NodeConnectionTypes.Main],
19
+ outputNames: ['Matched', 'No Match'],
20
+ credentials: [{ name: 'yCloudApi', required: true }],
21
+ properties: [
22
+ {
23
+ displayName: 'Message Object Field',
24
+ name: 'messageField',
25
+ type: 'string',
26
+ default: 'whatsappInboundMessage',
27
+ description: 'Field in the input item containing the WhatsApp message object (from YCloud Trigger). The "from" field inside is used to look up the contact.',
28
+ },
29
+ {
30
+ displayName: 'From Phone Number',
31
+ name: 'fromPhone',
32
+ type: 'string',
33
+ required: true,
34
+ default: '',
35
+ placeholder: '+16315551111',
36
+ description: 'Your WhatsApp Business phone number used to send the response',
37
+ },
38
+ {
39
+ displayName: 'Response Rules',
40
+ name: 'rules',
41
+ type: 'fixedCollection',
42
+ typeOptions: { multipleValues: true, sortable: true },
43
+ default: { items: [] },
44
+ placeholder: 'Add Rule',
45
+ description: 'Rules are evaluated in order. The first matching rule determines the template sent.',
46
+ options: [
47
+ {
48
+ name: 'items',
49
+ displayName: 'Rule',
50
+ values: [
51
+ {
52
+ displayName: 'Condition Type',
53
+ name: 'conditionType',
54
+ type: 'options',
55
+ default: 'hasTag',
56
+ options: [
57
+ { name: 'Contact Has Tag', value: 'hasTag' },
58
+ { name: 'Contact Attribute Equals', value: 'attributeEquals' },
59
+ { name: 'Match All (default/fallback)', value: 'always' },
60
+ ],
61
+ },
62
+ {
63
+ displayName: 'Tag',
64
+ name: 'tag',
65
+ type: 'string',
66
+ default: '',
67
+ displayOptions: { show: { conditionType: ['hasTag'] } },
68
+ description: 'Contact must have this tag to match',
69
+ },
70
+ {
71
+ displayName: 'Attribute Key',
72
+ name: 'attributeKey',
73
+ type: 'string',
74
+ default: '',
75
+ displayOptions: { show: { conditionType: ['attributeEquals'] } },
76
+ description: 'Custom attribute key to check (e.g. "plan")',
77
+ },
78
+ {
79
+ displayName: 'Attribute Value',
80
+ name: 'attributeValue',
81
+ type: 'string',
82
+ default: '',
83
+ displayOptions: { show: { conditionType: ['attributeEquals'] } },
84
+ description: 'Expected value of the attribute (case-insensitive)',
85
+ },
86
+ {
87
+ displayName: 'Template Name',
88
+ name: 'templateName',
89
+ type: 'string',
90
+ required: true,
91
+ default: '',
92
+ placeholder: 'premium_response',
93
+ description: 'Name of the WhatsApp template to send when this rule matches',
94
+ },
95
+ {
96
+ displayName: 'Template Language',
97
+ name: 'templateLanguage',
98
+ type: 'string',
99
+ default: 'pt_BR',
100
+ description: 'Language code, e.g. pt_BR, en_US',
101
+ },
102
+ {
103
+ displayName: 'Template Body Variables (JSON)',
104
+ name: 'templateVarsJSON',
105
+ type: 'string',
106
+ default: '[]',
107
+ description: 'JSON array of body variable values: ["Name", "Value"]',
108
+ },
109
+ ],
110
+ },
111
+ ],
112
+ },
113
+ {
114
+ displayName: 'Options',
115
+ name: 'options',
116
+ type: 'collection',
117
+ placeholder: 'Add Option',
118
+ default: {},
119
+ options: [
120
+ {
121
+ displayName: 'Filter Unsubscribed',
122
+ name: 'filterUnsubscribed',
123
+ type: 'boolean',
124
+ default: true,
125
+ },
126
+ {
127
+ displayName: 'Reply to Inbound Message',
128
+ name: 'replyToMessage',
129
+ type: 'boolean',
130
+ default: false,
131
+ description: 'Whether to send the response as a reply to the inbound message (sets context.message_id)',
132
+ },
133
+ ],
134
+ },
135
+ ],
136
+ };
137
+ }
138
+ async execute() {
139
+ const items = this.getInputData();
140
+ const matchedItems = [];
141
+ const noMatchItems = [];
142
+ for (let i = 0; i < items.length; i++) {
143
+ try {
144
+ const messageField = this.getNodeParameter('messageField', i);
145
+ const fromPhone = this.getNodeParameter('fromPhone', i);
146
+ const rulesData = this.getNodeParameter('rules', i);
147
+ const rules = rulesData.items || [];
148
+ const options = this.getNodeParameter('options', i);
149
+ const data = items[i].json;
150
+ const message = data[messageField] || {};
151
+ const senderPhone = message.from;
152
+ if (!senderPhone) {
153
+ noMatchItems.push({ json: { ...data, _reason: 'no_sender_phone' }, pairedItem: { item: i } });
154
+ continue;
155
+ }
156
+ const contactResp = await GenericFunctions_1.ycloudApiRequest.call(this, 'GET', '/contact/contacts', {}, { phoneNumber: senderPhone });
157
+ const contact = (contactResp.items || []).find((c) => c.phoneNumber === senderPhone) || {};
158
+ const contactTags = contact.tags || [];
159
+ const contactAttrs = contact.customAttributes || [];
160
+ const attrMap = {};
161
+ for (const attr of contactAttrs) {
162
+ if (attr.key)
163
+ attrMap[attr.key] = (attr.value || '').toLowerCase();
164
+ }
165
+ let matchedRule = null;
166
+ for (const rule of rules) {
167
+ const type = rule.conditionType;
168
+ if (type === 'always') {
169
+ matchedRule = rule;
170
+ break;
171
+ }
172
+ if (type === 'hasTag' && contactTags.includes(rule.tag)) {
173
+ matchedRule = rule;
174
+ break;
175
+ }
176
+ if (type === 'attributeEquals') {
177
+ const key = rule.attributeKey;
178
+ const expectedVal = (rule.attributeValue || '').toLowerCase();
179
+ if (attrMap[key] === expectedVal) {
180
+ matchedRule = rule;
181
+ break;
182
+ }
183
+ }
184
+ }
185
+ if (!matchedRule) {
186
+ noMatchItems.push({ json: { ...data, contact, _reason: 'no_rule_matched' }, pairedItem: { item: i } });
187
+ continue;
188
+ }
189
+ const templateVars = JSON.parse(matchedRule.templateVarsJSON || '[]');
190
+ const components = [];
191
+ if (templateVars.length > 0) {
192
+ components.push({
193
+ type: 'body',
194
+ parameters: templateVars.map((v) => ({ type: 'text', text: v })),
195
+ });
196
+ }
197
+ const messageBody = {
198
+ from: fromPhone,
199
+ to: senderPhone,
200
+ type: 'template',
201
+ filterUnsubscribed: options.filterUnsubscribed !== false,
202
+ template: {
203
+ name: matchedRule.templateName,
204
+ language: { code: matchedRule.templateLanguage || 'pt_BR' },
205
+ ...(components.length > 0 ? { components } : {}),
206
+ },
207
+ };
208
+ if (options.replyToMessage && message.id) {
209
+ messageBody.context = { message_id: message.id };
210
+ }
211
+ const sendResult = await GenericFunctions_1.ycloudApiRequest.call(this, 'POST', '/whatsapp/messages', messageBody);
212
+ matchedItems.push({
213
+ json: {
214
+ message: sendResult,
215
+ contact,
216
+ _rule: matchedRule.conditionType,
217
+ _template: matchedRule.templateName,
218
+ _phone: senderPhone,
219
+ },
220
+ pairedItem: { item: i },
221
+ });
222
+ }
223
+ catch (error) {
224
+ if (this.continueOnFail()) {
225
+ noMatchItems.push({ json: { error: error.message }, pairedItem: { item: i } });
226
+ }
227
+ else {
228
+ throw error;
229
+ }
230
+ }
231
+ }
232
+ return [matchedItems, noMatchItems];
233
+ }
234
+ }
235
+ exports.YCloudAutoResponder = YCloudAutoResponder;
236
+ //# sourceMappingURL=YCloudAutoResponder.node.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"YCloudAutoResponder.node.js","sourceRoot":"","sources":["../../../nodes/YCloud/YCloudAutoResponder.node.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import type { IExecuteFunctions, INodeExecutionData, INodeType, INodeTypeDescription } from 'n8n-workflow';
2
+ export declare class YCloudContactOnboarding implements INodeType {
3
+ description: INodeTypeDescription;
4
+ execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]>;
5
+ }
@@ -0,0 +1,195 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.YCloudContactOnboarding = void 0;
4
+ const n8n_workflow_1 = require("n8n-workflow");
5
+ const GenericFunctions_1 = require("./GenericFunctions");
6
+ class YCloudContactOnboarding {
7
+ constructor() {
8
+ this.description = {
9
+ displayName: 'YCloud Contact Onboarding',
10
+ name: 'yCloudContactOnboarding',
11
+ icon: 'file:logo-ycloud.png',
12
+ group: ['output'],
13
+ version: 1,
14
+ subtitle: 'Send welcome template + tag contact',
15
+ description: 'Sends a welcome WhatsApp template to a new contact and optionally adds an onboarding tag. Designed to follow a "YCloud Trigger" listening for contact.created events.',
16
+ defaults: { name: 'YCloud Contact Onboarding' },
17
+ inputs: [n8n_workflow_1.NodeConnectionTypes.Main],
18
+ outputs: [n8n_workflow_1.NodeConnectionTypes.Main],
19
+ outputNames: ['Success'],
20
+ credentials: [{ name: 'yCloudApi', required: true }],
21
+ properties: [
22
+ {
23
+ displayName: 'Contact Phone Field',
24
+ name: 'contactPhoneField',
25
+ type: 'string',
26
+ default: 'contact.phoneNumber',
27
+ description: 'Dot-path to the phone number in the input item, e.g. "contact.phoneNumber" for contact.created events or just "phoneNumber"',
28
+ },
29
+ {
30
+ displayName: 'Contact ID Field',
31
+ name: 'contactIdField',
32
+ type: 'string',
33
+ default: 'contact.id',
34
+ description: 'Dot-path to the contact ID in the input item. Used to add the welcome tag.',
35
+ },
36
+ {
37
+ displayName: 'From Phone Number',
38
+ name: 'fromPhone',
39
+ type: 'string',
40
+ required: true,
41
+ default: '',
42
+ placeholder: '+16315551111',
43
+ description: 'Your WhatsApp Business phone number registered in YCloud',
44
+ },
45
+ {
46
+ displayName: 'Template Name',
47
+ name: 'templateName',
48
+ type: 'string',
49
+ required: true,
50
+ default: '',
51
+ placeholder: 'welcome_message',
52
+ description: 'Name of the approved WhatsApp template to send',
53
+ },
54
+ {
55
+ displayName: 'Template Language',
56
+ name: 'templateLanguage',
57
+ type: 'string',
58
+ required: true,
59
+ default: 'pt_BR',
60
+ placeholder: 'pt_BR',
61
+ description: 'Language code of the template, e.g. pt_BR, en_US',
62
+ },
63
+ {
64
+ displayName: 'Template Body Variables (JSON)',
65
+ name: 'templateVarsJSON',
66
+ type: 'string',
67
+ typeOptions: { rows: 3 },
68
+ default: '[]',
69
+ description: 'JSON array of string values for template body variables in order: ["John", "Premium"]. Supports expressions.',
70
+ },
71
+ {
72
+ displayName: 'Welcome Tag',
73
+ name: 'welcomeTag',
74
+ type: 'string',
75
+ default: 'onboarded',
76
+ description: 'Tag added to the contact after the welcome message is sent. Leave empty to skip tagging.',
77
+ },
78
+ {
79
+ displayName: 'Options',
80
+ name: 'options',
81
+ type: 'collection',
82
+ placeholder: 'Add Option',
83
+ default: {},
84
+ options: [
85
+ {
86
+ displayName: 'Filter Unsubscribed',
87
+ name: 'filterUnsubscribed',
88
+ type: 'boolean',
89
+ default: true,
90
+ description: 'Skip sending if the contact has opted out of WhatsApp messages',
91
+ },
92
+ {
93
+ displayName: 'Header Media URL or ID',
94
+ name: 'headerMedia',
95
+ type: 'string',
96
+ default: '',
97
+ description: 'URL or media ID for image/video/document header (if your template uses one)',
98
+ },
99
+ ],
100
+ },
101
+ ],
102
+ };
103
+ }
104
+ async execute() {
105
+ const items = this.getInputData();
106
+ const successItems = [];
107
+ for (let i = 0; i < items.length; i++) {
108
+ try {
109
+ const phoneField = this.getNodeParameter('contactPhoneField', i);
110
+ const idField = this.getNodeParameter('contactIdField', i);
111
+ const fromPhone = this.getNodeParameter('fromPhone', i);
112
+ const templateName = this.getNodeParameter('templateName', i);
113
+ const templateLanguage = this.getNodeParameter('templateLanguage', i);
114
+ const templateVarsRaw = this.getNodeParameter('templateVarsJSON', i);
115
+ const welcomeTag = this.getNodeParameter('welcomeTag', i);
116
+ const options = this.getNodeParameter('options', i);
117
+ const getField = (obj, path) => {
118
+ return path.split('.').reduce((acc, key) => {
119
+ if (acc && typeof acc === 'object')
120
+ return acc[key];
121
+ return undefined;
122
+ }, obj);
123
+ };
124
+ const toPhone = getField(items[i].json, phoneField);
125
+ const contactId = getField(items[i].json, idField);
126
+ if (!toPhone) {
127
+ throw new Error(`Phone field "${phoneField}" not found in input item`);
128
+ }
129
+ const templateVars = JSON.parse(templateVarsRaw || '[]');
130
+ const components = [];
131
+ if (options.headerMedia) {
132
+ const headerMedia = options.headerMedia;
133
+ const isUrl = headerMedia.startsWith('http');
134
+ components.push({
135
+ type: 'header',
136
+ parameters: [{ type: 'image', image: isUrl ? { link: headerMedia } : { id: headerMedia } }],
137
+ });
138
+ }
139
+ if (templateVars.length > 0) {
140
+ components.push({
141
+ type: 'body',
142
+ parameters: templateVars.map((v) => ({ type: 'text', text: v })),
143
+ });
144
+ }
145
+ const messageBody = {
146
+ from: fromPhone,
147
+ to: toPhone,
148
+ type: 'template',
149
+ template: {
150
+ name: templateName,
151
+ language: { code: templateLanguage },
152
+ ...(components.length > 0 ? { components } : {}),
153
+ },
154
+ };
155
+ if (options.filterUnsubscribed !== undefined) {
156
+ messageBody.filterUnsubscribed = options.filterUnsubscribed;
157
+ }
158
+ const messageResult = await GenericFunctions_1.ycloudApiRequest.call(this, 'POST', '/whatsapp/messages', messageBody);
159
+ let tagResult = {};
160
+ if (welcomeTag && contactId) {
161
+ const contact = await GenericFunctions_1.ycloudApiRequest.call(this, 'GET', `/contact/contacts/${contactId}`);
162
+ const existingTags = contact.tags || [];
163
+ if (!existingTags.includes(welcomeTag)) {
164
+ tagResult = await GenericFunctions_1.ycloudApiRequest.call(this, 'PATCH', `/contact/contacts/${contactId}`, {
165
+ tags: [...existingTags, welcomeTag],
166
+ });
167
+ }
168
+ else {
169
+ tagResult = contact;
170
+ }
171
+ }
172
+ successItems.push({
173
+ json: {
174
+ message: messageResult,
175
+ contact: tagResult,
176
+ _phone: toPhone,
177
+ _welcomeTag: welcomeTag || null,
178
+ },
179
+ pairedItem: { item: i },
180
+ });
181
+ }
182
+ catch (error) {
183
+ if (this.continueOnFail()) {
184
+ successItems.push({ json: { error: error.message }, pairedItem: { item: i } });
185
+ }
186
+ else {
187
+ throw error;
188
+ }
189
+ }
190
+ }
191
+ return [successItems];
192
+ }
193
+ }
194
+ exports.YCloudContactOnboarding = YCloudContactOnboarding;
195
+ //# sourceMappingURL=YCloudContactOnboarding.node.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"YCloudContactOnboarding.node.js","sourceRoot":"","sources":["../../../nodes/YCloud/YCloudContactOnboarding.node.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import type { IExecuteFunctions, INodeExecutionData, INodeType, INodeTypeDescription } from 'n8n-workflow';
2
+ export declare class YCloudContactUpsert implements INodeType {
3
+ description: INodeTypeDescription;
4
+ execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]>;
5
+ }
@@ -0,0 +1,120 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.YCloudContactUpsert = void 0;
4
+ const n8n_workflow_1 = require("n8n-workflow");
5
+ const GenericFunctions_1 = require("./GenericFunctions");
6
+ class YCloudContactUpsert {
7
+ constructor() {
8
+ this.description = {
9
+ displayName: 'YCloud Contact Upsert',
10
+ name: 'yCloudContactUpsert',
11
+ icon: 'file:logo-ycloud.png',
12
+ group: ['output'],
13
+ version: 1,
14
+ subtitle: 'Found / Created',
15
+ description: 'Looks up a contact by phone number. Routes to "Found" if it exists (optionally updating it), or creates it and routes to "Created".',
16
+ defaults: { name: 'YCloud Contact Upsert' },
17
+ inputs: [n8n_workflow_1.NodeConnectionTypes.Main],
18
+ outputs: [n8n_workflow_1.NodeConnectionTypes.Main, n8n_workflow_1.NodeConnectionTypes.Main],
19
+ outputNames: ['Found', 'Created'],
20
+ credentials: [{ name: 'yCloudApi', required: true }],
21
+ properties: [
22
+ {
23
+ displayName: 'Phone Number',
24
+ name: 'phoneNumber',
25
+ type: 'string',
26
+ required: true,
27
+ default: '',
28
+ placeholder: '+16315551111',
29
+ description: 'Phone number in E.164 format. Supports expressions e.g. {{ $json.phone }}.',
30
+ },
31
+ {
32
+ displayName: 'On Contact Found',
33
+ name: 'ifExists',
34
+ type: 'options',
35
+ default: 'doNothing',
36
+ options: [
37
+ { name: 'Do Nothing — Return Existing Data', value: 'doNothing' },
38
+ { name: 'Update Contact Fields', value: 'update' },
39
+ ],
40
+ description: 'What to do when the contact already exists in YCloud',
41
+ },
42
+ {
43
+ displayName: 'Contact Fields',
44
+ name: 'contactFields',
45
+ type: 'collection',
46
+ placeholder: 'Add Field',
47
+ default: {},
48
+ description: 'Fields to set on create. When "Update Contact Fields" is selected, also applied on update.',
49
+ options: [
50
+ { displayName: 'Country Code', name: 'countryCode', type: 'string', default: '', description: 'ISO 3166-1 alpha-2 country code, e.g. US' },
51
+ {
52
+ displayName: 'Custom Attributes (JSON)',
53
+ name: 'customAttributes',
54
+ type: 'string',
55
+ typeOptions: { rows: 3 },
56
+ default: '',
57
+ description: 'JSON array of custom attributes: [{"key":"plan","value":"premium"}]',
58
+ },
59
+ { displayName: 'Nickname', name: 'nickname', type: 'string', default: '' },
60
+ { displayName: 'Owner Email', name: 'ownerEmail', type: 'string', default: '', placeholder: 'owner@example.com' },
61
+ {
62
+ displayName: 'Tags',
63
+ name: 'tags',
64
+ type: 'string',
65
+ default: '',
66
+ description: 'Comma-separated list of tags, e.g. lead,premium',
67
+ },
68
+ ],
69
+ },
70
+ ],
71
+ };
72
+ }
73
+ async execute() {
74
+ const items = this.getInputData();
75
+ const foundItems = [];
76
+ const createdItems = [];
77
+ for (let i = 0; i < items.length; i++) {
78
+ try {
79
+ const phoneNumber = this.getNodeParameter('phoneNumber', i);
80
+ const ifExists = this.getNodeParameter('ifExists', i);
81
+ const fields = this.getNodeParameter('contactFields', i);
82
+ const body = {};
83
+ if (fields.nickname)
84
+ body.nickname = fields.nickname;
85
+ if (fields.countryCode)
86
+ body.countryCode = fields.countryCode;
87
+ if (fields.ownerEmail)
88
+ body.ownerEmail = fields.ownerEmail;
89
+ if (fields.tags)
90
+ body.tags = fields.tags.split(',').map((t) => t.trim()).filter(Boolean);
91
+ if (fields.customAttributes)
92
+ body.customAttributes = JSON.parse(fields.customAttributes);
93
+ const resp = await GenericFunctions_1.ycloudApiRequest.call(this, 'GET', '/contact/contacts', {}, { phoneNumber });
94
+ const existing = (resp.items || []).find((c) => c.phoneNumber === phoneNumber);
95
+ if (existing) {
96
+ let result = existing;
97
+ if (ifExists === 'update' && Object.keys(body).length > 0) {
98
+ result = await GenericFunctions_1.ycloudApiRequest.call(this, 'PATCH', `/contact/contacts/${existing.id}`, body);
99
+ }
100
+ foundItems.push({ json: result, pairedItem: { item: i } });
101
+ }
102
+ else {
103
+ const created = await GenericFunctions_1.ycloudApiRequest.call(this, 'POST', '/contact/contacts', { phoneNumber, ...body });
104
+ createdItems.push({ json: created, pairedItem: { item: i } });
105
+ }
106
+ }
107
+ catch (error) {
108
+ if (this.continueOnFail()) {
109
+ foundItems.push({ json: { error: error.message }, pairedItem: { item: i } });
110
+ }
111
+ else {
112
+ throw error;
113
+ }
114
+ }
115
+ }
116
+ return [foundItems, createdItems];
117
+ }
118
+ }
119
+ exports.YCloudContactUpsert = YCloudContactUpsert;
120
+ //# sourceMappingURL=YCloudContactUpsert.node.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"YCloudContactUpsert.node.js","sourceRoot":"","sources":["../../../nodes/YCloud/YCloudContactUpsert.node.ts"],"names":[],"mappings":";;;AACA,+CAAmD;AACnD,yDAAsD;AAEtD,MAAa,mBAAmB;IAAhC;QACE,gBAAW,GAAyB;YAClC,WAAW,EAAE,uBAAuB;YACpC,IAAI,EAAE,qBAAqB;YAC3B,IAAI,EAAE,sBAAsB;YAC5B,KAAK,EAAE,CAAC,QAAQ,CAAC;YACjB,OAAO,EAAE,CAAC;YACV,QAAQ,EAAE,iBAAiB;YAC3B,WAAW,EAAE,qIAAqI;YAClJ,QAAQ,EAAE,EAAE,IAAI,EAAE,uBAAuB,EAAE;YAC3C,MAAM,EAAE,CAAC,kCAAmB,CAAC,IAAI,CAAC;YAClC,OAAO,EAAE,CAAC,kCAAmB,CAAC,IAAI,EAAE,kCAAmB,CAAC,IAAI,CAAC;YAC7D,WAAW,EAAE,CAAC,OAAO,EAAE,SAAS,CAAC;YACjC,WAAW,EAAE,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;YACpD,UAAU,EAAE;gBACV;oBACE,WAAW,EAAE,cAAc;oBAC3B,IAAI,EAAE,aAAa;oBACnB,IAAI,EAAE,QAAQ;oBACd,QAAQ,EAAE,IAAI;oBACd,OAAO,EAAE,EAAE;oBACX,WAAW,EAAE,cAAc;oBAC3B,WAAW,EAAE,4EAA4E;iBAC1F;gBACD;oBACE,WAAW,EAAE,kBAAkB;oBAC/B,IAAI,EAAE,UAAU;oBAChB,IAAI,EAAE,SAAS;oBACf,OAAO,EAAE,WAAW;oBACpB,OAAO,EAAE;wBACP,EAAE,IAAI,EAAE,mCAAmC,EAAE,KAAK,EAAE,WAAW,EAAE;wBACjE,EAAE,IAAI,EAAE,uBAAuB,EAAE,KAAK,EAAE,QAAQ,EAAE;qBACnD;oBACD,WAAW,EAAE,sDAAsD;iBACpE;gBACD;oBACE,WAAW,EAAE,gBAAgB;oBAC7B,IAAI,EAAE,eAAe;oBACrB,IAAI,EAAE,YAAY;oBAClB,WAAW,EAAE,WAAW;oBACxB,OAAO,EAAE,EAAE;oBACX,WAAW,EAAE,4FAA4F;oBACzG,OAAO,EAAE;wBACP,EAAE,WAAW,EAAE,cAAc,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,EAAE,WAAW,EAAE,0CAA0C,EAAE;wBAC1I;4BACE,WAAW,EAAE,0BAA0B;4BACvC,IAAI,EAAE,kBAAkB;4BACxB,IAAI,EAAE,QAAQ;4BACd,WAAW,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE;4BACxB,OAAO,EAAE,EAAE;4BACX,WAAW,EAAE,qEAAqE;yBACnF;wBACD,EAAE,WAAW,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,EAAE;wBAC1E,EAAE,WAAW,EAAE,aAAa,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,EAAE,WAAW,EAAE,mBAAmB,EAAE;wBACjH;4BACE,WAAW,EAAE,MAAM;4BACnB,IAAI,EAAE,MAAM;4BACZ,IAAI,EAAE,QAAQ;4BACd,OAAO,EAAE,EAAE;4BACX,WAAW,EAAE,iDAAiD;yBAC/D;qBACF;iBACF;aACF;SACF,CAAC;IA8CJ,CAAC;IA5CC,KAAK,CAAC,OAAO;QACX,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC;QAClC,MAAM,UAAU,GAAyB,EAAE,CAAC;QAC5C,MAAM,YAAY,GAAyB,EAAE,CAAC;QAE9C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACtC,IAAI,CAAC;gBACH,MAAM,WAAW,GAAG,IAAI,CAAC,gBAAgB,CAAC,aAAa,EAAE,CAAC,CAAW,CAAC;gBACtE,MAAM,QAAQ,GAAG,IAAI,CAAC,gBAAgB,CAAC,UAAU,EAAE,CAAC,CAAW,CAAC;gBAChE,MAAM,MAAM,GAAG,IAAI,CAAC,gBAAgB,CAAC,eAAe,EAAE,CAAC,CAAgB,CAAC;gBAExE,MAAM,IAAI,GAAgB,EAAE,CAAC;gBAC7B,IAAI,MAAM,CAAC,QAAQ;oBAAE,IAAI,CAAC,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC;gBACrD,IAAI,MAAM,CAAC,WAAW;oBAAE,IAAI,CAAC,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC;gBAC9D,IAAI,MAAM,CAAC,UAAU;oBAAE,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC;gBAC3D,IAAI,MAAM,CAAC,IAAI;oBAAE,IAAI,CAAC,IAAI,GAAI,MAAM,CAAC,IAAe,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;gBACrG,IAAI,MAAM,CAAC,gBAAgB;oBAAE,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,gBAA0B,CAAC,CAAC;gBAEnG,MAAM,IAAI,GAAG,MAAM,mCAAgB,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,mBAAmB,EAAE,EAAE,EAAE,EAAE,WAAW,EAAE,CAAC,CAAC;gBAChG,MAAM,QAAQ,GAAG,CAAE,IAAI,CAAC,KAAuB,IAAI,EAAE,CAAC,CAAC,IAAI,CACzD,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,KAAK,WAAW,CACrC,CAAC;gBAEF,IAAI,QAAQ,EAAE,CAAC;oBACb,IAAI,MAAM,GAAG,QAAQ,CAAC;oBACtB,IAAI,QAAQ,KAAK,QAAQ,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;wBAC1D,MAAM,GAAG,MAAM,mCAAgB,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,qBAAqB,QAAQ,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,CAAC;oBAChG,CAAC;oBACD,UAAU,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;gBAC7D,CAAC;qBAAM,CAAC;oBACN,MAAM,OAAO,GAAG,MAAM,mCAAgB,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,mBAAmB,EAAE,EAAE,WAAW,EAAE,GAAG,IAAI,EAAE,CAAC,CAAC;oBACzG,YAAY,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,UAAU,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;gBAChE,CAAC;YACH,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,IAAI,IAAI,CAAC,cAAc,EAAE,EAAE,CAAC;oBAC1B,UAAU,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,EAAE,KAAK,EAAG,KAAe,CAAC,OAAO,EAAE,EAAE,UAAU,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;gBAC1F,CAAC;qBAAM,CAAC;oBACN,MAAM,KAAK,CAAC;gBACd,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC;IACpC,CAAC;CACF;AA9GD,kDA8GC"}
@@ -0,0 +1,5 @@
1
+ import type { IExecuteFunctions, INodeExecutionData, INodeType, INodeTypeDescription } from 'n8n-workflow';
2
+ export declare class YCloudInboundRouter implements INodeType {
3
+ description: INodeTypeDescription;
4
+ execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]>;
5
+ }