@replyio/n8n-nodes-reply 0.1.0 → 0.3.0

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 (36) hide show
  1. package/dist/credentials/ReplyApi.credentials.d.ts +4 -1
  2. package/dist/credentials/ReplyApi.credentials.js +4 -1
  3. package/dist/credentials/ReplyApi.credentials.js.map +1 -1
  4. package/dist/nodes/Reply/Reply.node.d.ts +6 -1
  5. package/dist/nodes/Reply/Reply.node.js +21 -0
  6. package/dist/nodes/Reply/Reply.node.js.map +1 -1
  7. package/dist/nodes/Reply/ReplyTrigger.node.js +294 -175
  8. package/dist/nodes/Reply/ReplyTrigger.node.js.map +1 -1
  9. package/dist/nodes/Reply/actions/contact/update.operation.js +31 -1
  10. package/dist/nodes/Reply/actions/contact/update.operation.js.map +1 -1
  11. package/dist/nodes/Reply/actions/contactStatus/index.js +1 -2
  12. package/dist/nodes/Reply/actions/contactStatus/index.js.map +1 -1
  13. package/dist/nodes/Reply/actions/contactStatus/statusHelper.js +8 -4
  14. package/dist/nodes/Reply/actions/contactStatus/statusHelper.js.map +1 -1
  15. package/dist/nodes/Reply/actions/sequence/addContact.operation.js +12 -27
  16. package/dist/nodes/Reply/actions/sequence/addContact.operation.js.map +1 -1
  17. package/dist/nodes/Reply/actions/sequence/index.js +23 -41
  18. package/dist/nodes/Reply/actions/sequence/index.js.map +1 -1
  19. package/dist/nodes/Reply/utils/GenericFunctions.d.ts +1 -0
  20. package/dist/nodes/Reply/utils/GenericFunctions.js +29 -10
  21. package/dist/nodes/Reply/utils/GenericFunctions.js.map +1 -1
  22. package/dist/nodes/Reply/utils/constants.d.ts +36 -49
  23. package/dist/nodes/Reply/utils/constants.js +37 -30
  24. package/dist/nodes/Reply/utils/constants.js.map +1 -1
  25. package/dist/nodes/Reply/utils/validation.d.ts +0 -10
  26. package/dist/nodes/Reply/utils/validation.js +0 -43
  27. package/dist/nodes/Reply/utils/validation.js.map +1 -1
  28. package/dist/package.json +1 -1
  29. package/dist/publicUrls.d.ts +1 -0
  30. package/dist/publicUrls.js +1 -0
  31. package/dist/publicUrls.js.map +1 -1
  32. package/dist/tsconfig.tsbuildinfo +1 -1
  33. package/package.json +1 -1
  34. package/dist/nodes/Reply/triggers/filters.d.ts +0 -6
  35. package/dist/nodes/Reply/triggers/filters.js +0 -53
  36. package/dist/nodes/Reply/triggers/filters.js.map +0 -1
@@ -2,10 +2,32 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ReplyTrigger = void 0;
4
4
  const n8n_workflow_1 = require("n8n-workflow");
5
- const filters_1 = require("./triggers/filters");
6
5
  const GenericFunctions_1 = require("./utils/GenericFunctions");
7
- const validation_1 = require("./utils/validation");
8
6
  const constants_1 = require("./utils/constants");
7
+ function expandEvents(events) {
8
+ if (events.includes(constants_1.SELECT_ALL_VALUES.ALL)) {
9
+ return [...constants_1.ALL_TRIGGER_EVENTS];
10
+ }
11
+ const expanded = [];
12
+ for (const event of events) {
13
+ if (event === constants_1.SELECT_ALL_VALUES.EMAIL) {
14
+ expanded.push(...constants_1.ALL_EMAIL_EVENTS);
15
+ }
16
+ else if (event === constants_1.SELECT_ALL_VALUES.LINKEDIN) {
17
+ expanded.push(...constants_1.ALL_LINKEDIN_EVENTS);
18
+ }
19
+ else if (event === constants_1.SELECT_ALL_VALUES.SEQUENCE) {
20
+ expanded.push(...constants_1.ALL_SEQUENCE_EVENTS);
21
+ }
22
+ else if (event === constants_1.SELECT_ALL_VALUES.ACCOUNT_HEALTH) {
23
+ expanded.push(...constants_1.ALL_ACCOUNT_HEALTH_EVENTS);
24
+ }
25
+ else {
26
+ expanded.push(event);
27
+ }
28
+ }
29
+ return [...new Set(expanded)];
30
+ }
9
31
  class ReplyTrigger {
10
32
  constructor() {
11
33
  this.description = {
@@ -14,8 +36,8 @@ class ReplyTrigger {
14
36
  icon: { light: 'file:../../icons/reply.svg', dark: 'file:../../icons/reply.dark.svg' },
15
37
  group: ['trigger'],
16
38
  version: 1,
17
- subtitle: '={{$parameter["events"].join(", ")}}',
18
- description: 'Triggers when Reply.io events occur. All events include contact_fields and sequence_fields. See https://apidocs.reply.io for full payload details.',
39
+ subtitle: '={{$parameter["triggerOn"] + ": " + $parameter["events"].join(", ")}}',
40
+ description: 'Starts the workflow when Reply.io events occur',
19
41
  defaults: {
20
42
  name: 'Reply Trigger',
21
43
  },
@@ -38,131 +60,260 @@ class ReplyTrigger {
38
60
  ],
39
61
  properties: [
40
62
  {
41
- displayName: 'Payload Structure',
42
- name: 'payloadNotice',
43
- type: 'notice',
44
- default: '',
45
- description: 'All events include contact_fields (ID, email, name, company) and sequence_fields (ID, step_number). Event-specific fields are listed in each option description below.',
46
- },
47
- {
48
- displayName: 'Events',
49
- name: 'events',
50
- type: 'multiOptions',
63
+ displayName: 'Trigger On',
64
+ name: 'triggerOn',
65
+ type: 'options',
66
+ default: 'All',
51
67
  required: true,
52
- default: [constants_1.EMAIL_EVENTS.REPLIED],
53
- description: 'The events to listen for',
54
68
  options: [
55
69
  {
56
- name: 'Contact Called',
57
- value: constants_1.CONTACT_EVENTS.CALLED,
58
- description: 'Cloud call made or logged. Fields: from_number, duration, recording_url, disposition, resolution.',
70
+ name: 'Account Health Events',
71
+ value: 'AccountHealth',
72
+ description: 'Email account status events',
73
+ action: 'On Account Health events',
59
74
  },
60
75
  {
61
- name: 'Contact Finished',
62
- value: constants_1.CONTACT_EVENTS.FINISHED,
63
- description: 'Prospect finishes sequence. Fields: finished_date, finish_reason (0=Replied, 1=Bounced, 2=Manual, 5=Called, 6=Opt-out, 7=Meeting).',
76
+ name: 'All Events',
77
+ value: 'All',
78
+ description: 'Trigger on any Reply.io event',
79
+ action: 'On All events',
64
80
  },
65
81
  {
66
- name: 'Contact Opted Out',
67
- value: constants_1.CONTACT_EVENTS.OPTED_OUT,
68
- description: 'Person opts out of communication',
82
+ name: 'Email Events',
83
+ value: 'Email',
84
+ description: 'Email sending and tracking events',
85
+ action: 'On Email events',
69
86
  },
70
87
  {
71
- name: 'Email Account Connection Lost',
72
- value: constants_1.ACCOUNT_HEALTH_EVENTS.EMAIL_CONNECTION_LOST,
73
- description: 'Email account connection lost. Fields: email_account_id, email_from.',
88
+ name: 'LinkedIn Events',
89
+ value: 'LinkedIn',
90
+ description: 'LinkedIn outreach events',
91
+ action: 'On LinkedIn events',
74
92
  },
75
93
  {
76
- name: 'Email Account Error',
77
- value: constants_1.ACCOUNT_HEALTH_EVENTS.EMAIL_ERROR,
78
- description: 'Email provider error. Fields: email_account_id, email_account_error.',
94
+ name: 'Sequence Events',
95
+ value: 'Sequence',
96
+ description: 'Contact lifecycle events',
97
+ action: 'On Sequence events',
98
+ },
99
+ ],
100
+ },
101
+ {
102
+ displayName: 'Events',
103
+ name: 'events',
104
+ type: 'multiOptions',
105
+ required: true,
106
+ default: [constants_1.SELECT_ALL_VALUES.ALL],
107
+ displayOptions: {
108
+ show: {
109
+ triggerOn: ['All'],
110
+ },
111
+ },
112
+ options: [
113
+ {
114
+ name: '*',
115
+ value: constants_1.SELECT_ALL_VALUES.ALL,
116
+ description: 'All events across all categories',
117
+ action: 'On All events',
118
+ },
119
+ ],
120
+ },
121
+ {
122
+ displayName: 'Events',
123
+ name: 'events',
124
+ type: 'multiOptions',
125
+ required: true,
126
+ default: [],
127
+ displayOptions: {
128
+ show: {
129
+ triggerOn: ['Email'],
130
+ },
131
+ },
132
+ options: [
133
+ {
134
+ name: '*',
135
+ value: constants_1.SELECT_ALL_VALUES.EMAIL,
136
+ description: 'All email events',
137
+ action: 'On All Email events',
79
138
  },
80
139
  {
81
140
  name: 'Email Bounced',
82
- value: constants_1.EMAIL_EVENTS.BOUNCED,
83
- description: 'Email delivery failed. Fields: bounce_type (Hard/Soft), bounce_date, sent_email_id.',
141
+ value: constants_1.EMAIL_EVENTS.EMAIL_BOUNCED,
142
+ description: 'Email delivery failed',
143
+ action: 'On email bounced',
84
144
  },
85
145
  {
86
146
  name: 'Email Link Clicked',
87
- value: constants_1.EMAIL_EVENTS.LINK_CLICKED,
147
+ value: constants_1.EMAIL_EVENTS.EMAIL_LINK_CLICKED,
88
148
  description: 'Link clicked in email',
149
+ action: 'On email link clicked',
89
150
  },
90
151
  {
91
152
  name: 'Email Opened',
92
- value: constants_1.EMAIL_EVENTS.OPENED,
93
- description: 'Email opened. Fields: email_open_date, sent_email_id, opens_count.',
153
+ value: constants_1.EMAIL_EVENTS.EMAIL_OPENED,
154
+ description: 'Email opened by recipient',
155
+ action: 'On email opened',
94
156
  },
95
157
  {
96
158
  name: 'Email Replied',
97
- value: constants_1.EMAIL_EVENTS.REPLIED,
98
- description: 'First reply or status set to Replied. Fields: reply_message_id, reply_date, reason (1=Email, 2=Manual).',
159
+ value: constants_1.EMAIL_EVENTS.EMAIL_REPLIED,
160
+ description: 'First reply received',
161
+ action: 'On email replied',
99
162
  },
100
163
  {
101
164
  name: 'Email Sent',
102
- value: constants_1.EMAIL_EVENTS.SENT,
103
- description: 'Email sent. Fields: sent_email_date, sent_email_id, email_account_id, sent_message_url.',
165
+ value: constants_1.EMAIL_EVENTS.EMAIL_SENT,
166
+ description: 'Email sent to recipient',
167
+ action: 'On email sent',
168
+ },
169
+ {
170
+ name: 'Reply Categorized',
171
+ value: constants_1.EMAIL_EVENTS.REPLY_CATEGORIZED,
172
+ description: 'Email reply categorized in inbox',
173
+ action: 'On reply categorized',
174
+ },
175
+ ],
176
+ },
177
+ {
178
+ displayName: 'Events',
179
+ name: 'events',
180
+ type: 'multiOptions',
181
+ required: true,
182
+ default: [],
183
+ displayOptions: {
184
+ show: {
185
+ triggerOn: ['LinkedIn'],
186
+ },
187
+ },
188
+ options: [
189
+ {
190
+ name: '*',
191
+ value: constants_1.SELECT_ALL_VALUES.LINKEDIN,
192
+ description: 'All LinkedIn events',
193
+ action: 'On All LinkedIn events',
104
194
  },
105
195
  {
106
- name: 'LinkedIn Connection Request Accepted',
107
- value: constants_1.LINKEDIN_EVENTS.CONNECTION_REQUEST_ACCEPTED,
108
- description: 'Connection request accepted. Fields: sender_linkedin_account_id.',
196
+ name: 'LinkedIn Connection Accepted',
197
+ value: constants_1.LINKEDIN_EVENTS.LINKEDIN_CONNECTION_REQUEST_ACCEPTED,
198
+ description: 'Connection request accepted',
199
+ action: 'On LinkedIn connection accepted',
109
200
  },
110
201
  {
111
- name: 'LinkedIn Connection Request Sent',
112
- value: constants_1.LINKEDIN_EVENTS.CONNECTION_REQUEST_SENT,
113
- description: 'Connection request sent. Fields: sender_linkedin_account_id, initial_message.',
202
+ name: 'LinkedIn Connection Sent',
203
+ value: constants_1.LINKEDIN_EVENTS.LINKEDIN_CONNECTION_REQUEST_SENT,
204
+ description: 'Connection request sent',
205
+ action: 'On LinkedIn connection sent',
114
206
  },
115
207
  {
116
208
  name: 'LinkedIn Message Replied',
117
- value: constants_1.LINKEDIN_EVENTS.MESSAGE_REPLIED,
118
- description: 'First LinkedIn reply. Fields: sender_linkedin_account_id, sequence_name, linkedin_message_id.',
209
+ value: constants_1.LINKEDIN_EVENTS.LINKEDIN_MESSAGE_REPLIED,
210
+ description: 'First LinkedIn reply received',
211
+ action: 'On LinkedIn message replied',
119
212
  },
120
213
  {
121
214
  name: 'LinkedIn Message Sent',
122
- value: constants_1.LINKEDIN_EVENTS.MESSAGE_SENT,
123
- description: 'LinkedIn message sent. Fields: is_inmail (true/false), sender_linkedin_account_id, initial_message.',
215
+ value: constants_1.LINKEDIN_EVENTS.LINKEDIN_MESSAGE_SENT,
216
+ action: 'On LinkedIn message sent',
124
217
  },
125
218
  {
126
219
  name: 'LinkedIn Reply Categorized',
127
- value: constants_1.LINKEDIN_EVENTS.REPLY_CATEGORIZED,
128
- description: 'LinkedIn reply categorized with inbox category',
129
- },
130
- {
131
- name: 'Reply Categorized',
132
- value: constants_1.REPLY_EVENTS.CATEGORIZED,
133
- description: 'Email reply categorized (not for Uncategorized). Note: sequence_fields.ID empty after first reply.',
220
+ value: constants_1.LINKEDIN_EVENTS.LINKEDIN_REPLY_CATEGORIZED,
221
+ action: 'On LinkedIn reply categorized',
134
222
  },
135
223
  ],
136
224
  },
137
225
  {
138
- displayName: 'Include Email URL',
139
- name: 'includeEmailUrl',
140
- type: 'boolean',
141
- default: false,
142
- description: 'Whether to include the email URL in the webhook payload',
143
- },
144
- {
145
- displayName: 'Include Prospect Custom Fields',
146
- name: 'includeProspectCustomFields',
147
- type: 'boolean',
148
- default: false,
149
- description: 'Whether to include prospect custom fields in the webhook payload',
226
+ displayName: 'Events',
227
+ name: 'events',
228
+ type: 'multiOptions',
229
+ required: true,
230
+ default: [],
231
+ displayOptions: {
232
+ show: {
233
+ triggerOn: ['Sequence'],
234
+ },
235
+ },
236
+ options: [
237
+ {
238
+ name: '*',
239
+ value: constants_1.SELECT_ALL_VALUES.SEQUENCE,
240
+ description: 'All sequence events',
241
+ action: 'On All Sequence events',
242
+ },
243
+ {
244
+ name: 'Contact Called',
245
+ value: constants_1.SEQUENCE_EVENTS.CONTACT_CALLED,
246
+ description: 'Cloud call made or logged',
247
+ action: 'On contact called',
248
+ },
249
+ {
250
+ name: 'Contact Finished',
251
+ value: constants_1.SEQUENCE_EVENTS.CONTACT_FINISHED,
252
+ description: 'Contact finished sequence',
253
+ action: 'On contact finished',
254
+ },
255
+ {
256
+ name: 'Contact Opted Out',
257
+ value: constants_1.SEQUENCE_EVENTS.CONTACT_OPTED_OUT,
258
+ description: 'Contact opted out of communication',
259
+ action: 'On contact opted out',
260
+ },
261
+ ],
150
262
  },
151
263
  {
152
- displayName: 'Sequence IDs',
153
- name: 'sequenceIds',
154
- type: 'string',
155
- default: '',
156
- description: 'Filter events by sequence IDs (comma-separated). Leave empty to receive events from all sequences.',
157
- placeholder: 'e.g., 123, 456, 789',
264
+ displayName: 'Events',
265
+ name: 'events',
266
+ type: 'multiOptions',
267
+ required: true,
268
+ default: [],
269
+ displayOptions: {
270
+ show: {
271
+ triggerOn: ['AccountHealth'],
272
+ },
273
+ },
274
+ options: [
275
+ {
276
+ name: '*',
277
+ value: constants_1.SELECT_ALL_VALUES.ACCOUNT_HEALTH,
278
+ description: 'All account health events',
279
+ action: 'On All Account Health events',
280
+ },
281
+ {
282
+ name: 'Email Account Connection Lost',
283
+ value: constants_1.ACCOUNT_HEALTH_EVENTS.EMAIL_CONNECTION_LOST,
284
+ description: 'Email account disconnected',
285
+ action: 'On email account connection lost',
286
+ },
287
+ {
288
+ name: 'Email Account Error',
289
+ value: constants_1.ACCOUNT_HEALTH_EVENTS.EMAIL_ERROR,
290
+ description: 'Email account error occurred',
291
+ action: 'On email account error',
292
+ },
293
+ ],
158
294
  },
159
295
  {
160
- displayName: 'Email Accounts',
161
- name: 'emailAccounts',
162
- type: 'string',
163
- default: '',
164
- description: 'Filter events by email accounts (comma-separated). Leave empty to monitor all accounts.',
165
- placeholder: 'e.g., sales@company.com, outreach@company.com',
296
+ displayName: 'Options',
297
+ name: 'options',
298
+ type: 'collection',
299
+ placeholder: 'Add Option',
300
+ default: {},
301
+ options: [
302
+ {
303
+ displayName: 'Include Email URL',
304
+ name: 'includeEmailUrl',
305
+ type: 'boolean',
306
+ default: false,
307
+ description: 'Whether to include the email URL in the webhook payload',
308
+ },
309
+ {
310
+ displayName: 'Include Prospect Custom Fields',
311
+ name: 'includeProspectCustomFields',
312
+ type: 'boolean',
313
+ default: false,
314
+ description: 'Whether to include prospect custom fields in the webhook payload',
315
+ },
316
+ ],
166
317
  },
167
318
  ],
168
319
  };
@@ -171,100 +322,92 @@ class ReplyTrigger {
171
322
  async checkExists() {
172
323
  const webhookData = this.getWorkflowStaticData('node');
173
324
  const webhookUrl = this.getNodeWebhookUrl('default');
174
- const events = this.getNodeParameter('events', []);
325
+ const rawEvents = this.getNodeParameter('events', []);
326
+ const events = expandEvents(rawEvents);
175
327
  const registeredEvents = webhookData.registeredEvents || [];
176
328
  const registeredWebhookIds = webhookData.webhookIds || [];
329
+ if (registeredWebhookIds.length === 0 || registeredEvents.length === 0) {
330
+ return false;
331
+ }
177
332
  const allRegistered = events.every((e) => registeredEvents.includes(e));
178
- if (allRegistered && registeredEvents.length === events.length && registeredWebhookIds.length > 0) {
179
- return true;
333
+ if (!allRegistered || registeredEvents.length !== events.length) {
334
+ return false;
180
335
  }
181
336
  let existingWebhooks = [];
182
337
  try {
183
- const response = await GenericFunctions_1.replyApiRequest.call(this, 'GET', '/v2/webhooks');
184
- existingWebhooks = (response === null || response === void 0 ? void 0 : response.items) || response || [];
338
+ const response = await GenericFunctions_1.replyWebhookApiRequest.call(this, 'GET', '/v2/webhooks');
339
+ existingWebhooks =
340
+ (response === null || response === void 0 ? void 0 : response.items) ||
341
+ response ||
342
+ [];
185
343
  }
186
344
  catch {
345
+ return false;
187
346
  }
188
- const existingWebhookMap = new Map();
189
- for (const wh of existingWebhooks) {
190
- if (wh.url === webhookUrl && wh.event && wh.id) {
191
- existingWebhookMap.set(String(wh.event), String(wh.id));
192
- }
347
+ const activeWebhooksForEvents = existingWebhooks.filter((wh) => events.includes(String(wh.event)) && wh.url === webhookUrl && !wh.isDisabled);
348
+ const eventsWithActiveWebhook = activeWebhooksForEvents.map((wh) => String(wh.event));
349
+ return events.every((e) => eventsWithActiveWebhook.includes(e));
350
+ },
351
+ async create() {
352
+ const webhookData = this.getWorkflowStaticData('node');
353
+ const webhookUrl = this.getNodeWebhookUrl('default');
354
+ const rawEvents = this.getNodeParameter('events', []);
355
+ const events = expandEvents(rawEvents);
356
+ const options = this.getNodeParameter('options', {});
357
+ const includeEmailUrl = options.includeEmailUrl || false;
358
+ const includeProspectCustomFields = options.includeProspectCustomFields || false;
359
+ let existingWebhooks = [];
360
+ try {
361
+ const response = await GenericFunctions_1.replyWebhookApiRequest.call(this, 'GET', '/v2/webhooks');
362
+ existingWebhooks =
363
+ (response === null || response === void 0 ? void 0 : response.items) ||
364
+ response ||
365
+ [];
193
366
  }
194
- const eventsToRemove = registeredEvents.filter((e) => !events.includes(e));
195
- for (const event of eventsToRemove) {
196
- const webhookId = existingWebhookMap.get(event);
197
- if (webhookId) {
198
- try {
199
- await GenericFunctions_1.replyApiRequest.call(this, 'DELETE', `/v2/webhooks/${webhookId}`);
200
- }
201
- catch {
202
- }
203
- }
367
+ catch {
368
+ existingWebhooks = [];
204
369
  }
205
- const includeEmailUrl = this.getNodeParameter('includeEmailUrl', false);
206
- const includeProspectCustomFields = this.getNodeParameter('includeProspectCustomFields', false);
207
- const newWebhookIds = [];
208
- const newRegisteredEvents = [];
370
+ const webhookIds = [];
209
371
  for (const event of events) {
210
- const existingId = existingWebhookMap.get(event);
211
- if (existingId) {
212
- newWebhookIds.push(existingId);
213
- newRegisteredEvents.push(event);
214
- continue;
215
- }
216
- const body = {
217
- event,
218
- url: webhookUrl,
219
- };
220
- if (includeEmailUrl || includeProspectCustomFields) {
221
- body.includeEmailUrl = includeEmailUrl;
222
- body.includeProspectCustomFields = includeProspectCustomFields;
372
+ const existingWebhook = existingWebhooks.find((wh) => wh.event === event && wh.url === webhookUrl);
373
+ if (existingWebhook && existingWebhook.id) {
374
+ if (existingWebhook.isDisabled) {
375
+ await GenericFunctions_1.replyWebhookApiRequest.call(this, 'PATCH', `/v2/webhooks/${existingWebhook.id}`, {
376
+ isDisabled: false,
377
+ payload: {
378
+ includeEmailUrl,
379
+ includeProspectCustomFields,
380
+ },
381
+ });
382
+ }
383
+ webhookIds.push(String(existingWebhook.id));
223
384
  }
224
- try {
225
- const response = await GenericFunctions_1.replyApiRequest.call(this, 'POST', '/v2/webhooks', body);
385
+ else {
386
+ const body = {
387
+ event,
388
+ url: webhookUrl,
389
+ isDisabled: false,
390
+ payload: {
391
+ includeEmailUrl,
392
+ includeProspectCustomFields,
393
+ },
394
+ };
395
+ const response = await GenericFunctions_1.replyWebhookApiRequest.call(this, 'POST', '/v2/webhooks', body);
226
396
  const webhookId = response === null || response === void 0 ? void 0 : response.id;
227
397
  if (webhookId) {
228
- newWebhookIds.push(String(webhookId));
398
+ webhookIds.push(String(webhookId));
229
399
  }
230
- newRegisteredEvents.push(event);
231
- }
232
- catch (error) {
233
- const errorMessage = error.message || '';
234
- if (errorMessage.includes('already') || errorMessage.includes('exists')) {
235
- const foundId = existingWebhookMap.get(event);
236
- if (foundId) {
237
- newWebhookIds.push(foundId);
238
- }
239
- newRegisteredEvents.push(event);
240
- continue;
241
- }
242
- throw error;
243
- }
244
- }
245
- webhookData.webhookIds = newWebhookIds;
246
- webhookData.registeredEvents = newRegisteredEvents;
247
- for (const id of newWebhookIds) {
248
- try {
249
- await GenericFunctions_1.replyApiRequest.call(this, 'POST', `/v2/webhooks/${id}/test`);
250
- }
251
- catch {
252
400
  }
253
401
  }
254
- return true;
255
- },
256
- async create() {
402
+ webhookData.webhookIds = webhookIds;
403
+ webhookData.registeredEvents = [...events];
257
404
  return true;
258
405
  },
259
406
  async delete() {
260
407
  const webhookData = this.getWorkflowStaticData('node');
261
408
  const webhookIds = webhookData.webhookIds || [];
262
409
  for (const id of webhookIds) {
263
- try {
264
- await GenericFunctions_1.replyApiRequest.call(this, 'DELETE', `/v2/webhooks/${id}`);
265
- }
266
- catch {
267
- }
410
+ await GenericFunctions_1.replyWebhookApiRequest.call(this, 'DELETE', `/v2/webhooks/${id}`);
268
411
  }
269
412
  delete webhookData.webhookIds;
270
413
  delete webhookData.registeredEvents;
@@ -274,31 +417,7 @@ class ReplyTrigger {
274
417
  };
275
418
  }
276
419
  async webhook() {
277
- var _a;
278
420
  const bodyData = this.getBodyData();
279
- const selectedEvents = this.getNodeParameter('events', []);
280
- const sequenceIdsRaw = this.getNodeParameter('sequenceIds', '');
281
- const emailAccountsRaw = this.getNodeParameter('emailAccounts', '');
282
- const eventType = ((_a = bodyData.event) === null || _a === void 0 ? void 0 : _a.type) || bodyData.eventType || '';
283
- if (selectedEvents.length > 0 && !selectedEvents.includes(eventType)) {
284
- return {
285
- noWebhookResponse: true,
286
- };
287
- }
288
- const sequenceIds = sequenceIdsRaw
289
- .split(',')
290
- .map((s) => parseInt(s.trim(), 10))
291
- .filter((n) => !isNaN(n));
292
- const emailAccounts = emailAccountsRaw
293
- .split(',')
294
- .map((s) => s.trim())
295
- .filter((s) => s.length > 0);
296
- const filters = (0, validation_1.validateTriggerFilters)({ sequenceIds, emailAccounts });
297
- if (!(0, filters_1.matchesTriggerFilters)(bodyData, filters)) {
298
- return {
299
- noWebhookResponse: true,
300
- };
301
- }
302
421
  return {
303
422
  workflowData: [[{ json: bodyData }]],
304
423
  };