@pipedream/freshdesk 0.3.1 → 0.4.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 (39) hide show
  1. package/actions/add-note-to-ticket/add-note-to-ticket.mjs +1 -1
  2. package/actions/add-ticket-tags/add-ticket-tags.mjs +1 -1
  3. package/actions/assign-ticket-to-agent/assign-ticket-to-agent.mjs +1 -1
  4. package/actions/assign-ticket-to-group/assign-ticket-to-group.mjs +1 -1
  5. package/actions/close-ticket/close-ticket.mjs +1 -1
  6. package/actions/create-agent/create-agent.mjs +103 -0
  7. package/actions/create-company/create-company.mjs +1 -1
  8. package/actions/create-contact/create-contact.mjs +1 -1
  9. package/actions/create-solution-article/create-solution-article.mjs +72 -0
  10. package/actions/create-ticket/create-ticket.mjs +1 -1
  11. package/actions/create-ticket-field/create-ticket-field.mjs +109 -0
  12. package/actions/delete-solution-article/delete-solution-article.mjs +44 -0
  13. package/actions/get-contact/get-contact.mjs +26 -0
  14. package/actions/get-solution-article/get-solution-article.mjs +44 -0
  15. package/actions/get-ticket/get-ticket.mjs +1 -1
  16. package/actions/list-agents/list-agents.mjs +66 -0
  17. package/actions/list-all-tickets/list-all-tickets.mjs +1 -1
  18. package/actions/list-category-folders/list-category-folders.mjs +28 -0
  19. package/actions/list-folder-articles/list-folder-articles.mjs +47 -0
  20. package/actions/list-solution-categories/list-solution-categories.mjs +21 -0
  21. package/actions/list-ticket-fields/list-ticket-fields.mjs +32 -0
  22. package/actions/remove-ticket-tags/remove-ticket-tags.mjs +1 -1
  23. package/actions/set-ticket-priority/set-ticket-priority.mjs +1 -1
  24. package/actions/set-ticket-status/set-ticket-status.mjs +1 -1
  25. package/actions/set-ticket-tags/set-ticket-tags.mjs +1 -1
  26. package/actions/update-agent/update-agent.mjs +112 -0
  27. package/actions/update-contact/update-contact.mjs +64 -0
  28. package/actions/update-solution-article/update-solution-article.mjs +84 -0
  29. package/actions/update-ticket/update-ticket.mjs +1 -1
  30. package/actions/update-ticket-field/update-ticket-field.mjs +106 -0
  31. package/common/constants.mjs +38 -0
  32. package/common/utils.mjs +27 -0
  33. package/freshdesk.app.mjs +296 -2
  34. package/package.json +1 -1
  35. package/sources/common/polling.mjs +63 -0
  36. package/sources/contact-updated/contact-updated.mjs +28 -0
  37. package/sources/new-contact/new-contact.mjs +18 -40
  38. package/sources/new-ticket/new-ticket.mjs +18 -43
  39. package/sources/ticket-updated/ticket-updated.mjs +28 -0
package/freshdesk.app.mjs CHANGED
@@ -19,7 +19,6 @@ export default {
19
19
  }));
20
20
  },
21
21
  },
22
-
23
22
  ticketId: {
24
23
  type: "integer",
25
24
  label: "Ticket ID",
@@ -79,7 +78,6 @@ export default {
79
78
  }));
80
79
  },
81
80
  },
82
-
83
81
  ticketStatus: {
84
82
  type: "integer",
85
83
  label: "Status",
@@ -116,6 +114,138 @@ export default {
116
114
  }));
117
115
  },
118
116
  },
117
+ contactId: {
118
+ type: "string",
119
+ label: "Contact ID",
120
+ description: "The ID of a contact",
121
+ async options({
122
+ companyId, page,
123
+ }) {
124
+ const contacts = await this.getContacts({
125
+ params: {
126
+ company_id: companyId,
127
+ page: page + 1,
128
+ },
129
+ });
130
+ return contacts
131
+ .map(({
132
+ id, name, email,
133
+ }) => ({
134
+ label: name || email,
135
+ value: id,
136
+ }));
137
+ },
138
+ },
139
+ ticketFieldId: {
140
+ type: "string",
141
+ label: "Ticket Field ID",
142
+ description: "The ID of a ticket field",
143
+ async options({ page }) {
144
+ const fields = await this.listTicketFields({
145
+ params: {
146
+ page: page + 1,
147
+ },
148
+ });
149
+ return fields.map(({
150
+ id, label,
151
+ }) => ({
152
+ label: label || id,
153
+ value: id,
154
+ }));
155
+ },
156
+ },
157
+ skillIds: {
158
+ type: "string[]",
159
+ label: "Skill IDs",
160
+ description: "Array of skill IDs",
161
+ optional: true,
162
+ async options({ page }) {
163
+ const skills = await this.listSkills({
164
+ params: {
165
+ page: page + 1,
166
+ },
167
+ });
168
+ return skills.map(({
169
+ id, name,
170
+ }) => ({
171
+ label: name || id,
172
+ value: id,
173
+ }));
174
+ },
175
+ },
176
+ roleIds: {
177
+ type: "string[]",
178
+ label: "Role IDs",
179
+ description: "Array of role IDs",
180
+ optional: true,
181
+ async options() {
182
+ const roles = await this.listRoles();
183
+ return roles.map(({
184
+ id, name,
185
+ }) => ({
186
+ label: name || id,
187
+ value: id,
188
+ }));
189
+ },
190
+ },
191
+ categoryId: {
192
+ type: "integer",
193
+ label: "Category ID",
194
+ description: "The ID of a category",
195
+ async options() {
196
+ const categories = await this.listSolutionCategories();
197
+ return categories.map(({
198
+ id, name,
199
+ }) => ({
200
+ label: name || id,
201
+ value: id,
202
+ }));
203
+ },
204
+ },
205
+ folderId: {
206
+ type: "integer",
207
+ label: "Folder ID",
208
+ description: "The ID of a folder",
209
+ async options({ categoryId }) {
210
+ const folders = await this.listCategoryFolders({
211
+ categoryId,
212
+ });
213
+ return folders.map(({
214
+ id, name,
215
+ }) => ({
216
+ label: name || id,
217
+ value: id,
218
+ }));
219
+ },
220
+ },
221
+ articleId: {
222
+ type: "integer",
223
+ label: "Article ID",
224
+ description: "The ID of an article",
225
+ async options({
226
+ page, folderId,
227
+ }) {
228
+ const articles = await this.listFolderArticles({
229
+ folderId,
230
+ params: {
231
+ page: page + 1,
232
+ },
233
+ });
234
+ return articles.map(({
235
+ id, title,
236
+ }) => ({
237
+ label: title || id,
238
+ value: id,
239
+ }));
240
+ },
241
+ },
242
+ maxResults: {
243
+ type: "integer",
244
+ label: "Max Results",
245
+ description: "The maximum number of results to return",
246
+ default: 100,
247
+ optional: true,
248
+ },
119
249
  ticketTags: {
120
250
  type: "string[]",
121
251
  label: "Tags",
@@ -210,6 +340,14 @@ export default {
210
340
  ...args,
211
341
  });
212
342
  },
343
+ async getContact({
344
+ contactId, ...args
345
+ }) {
346
+ return this._makeRequest({
347
+ url: `/contacts/${contactId}`,
348
+ ...args,
349
+ });
350
+ },
213
351
  async getContacts(args) {
214
352
  return this._makeRequest({
215
353
  url: "/contacts",
@@ -223,6 +361,15 @@ export default {
223
361
  ...args,
224
362
  });
225
363
  },
364
+ async updateContact({
365
+ contactId, ...args
366
+ }) {
367
+ return this._makeRequest({
368
+ url: `/contacts/${contactId}`,
369
+ method: "put",
370
+ ...args,
371
+ });
372
+ },
226
373
  async createTicket(args) {
227
374
  return this._makeRequest({
228
375
  url: "/tickets",
@@ -250,6 +397,119 @@ export default {
250
397
  ...args,
251
398
  });
252
399
  },
400
+ async listTicketFields(args) {
401
+ return this._makeRequest({
402
+ url: "/ticket_fields",
403
+ ...args,
404
+ });
405
+ },
406
+ async createTicketField(args) {
407
+ return this._makeRequest({
408
+ url: "/admin/ticket_fields",
409
+ method: "post",
410
+ ...args,
411
+ });
412
+ },
413
+ async updateTicketField({
414
+ ticketFieldId, ...args
415
+ }) {
416
+ return this._makeRequest({
417
+ url: `/admin/ticket_fields/${ticketFieldId}`,
418
+ method: "put",
419
+ ...args,
420
+ });
421
+ },
422
+ async listAgents(args) {
423
+ return this._makeRequest({
424
+ url: "/agents",
425
+ ...args,
426
+ });
427
+ },
428
+ async createAgent(args) {
429
+ return this._makeRequest({
430
+ url: "/agents",
431
+ method: "post",
432
+ ...args,
433
+ });
434
+ },
435
+ async updateAgent({
436
+ agentId, ...args
437
+ }) {
438
+ return this._makeRequest({
439
+ url: `/agents/${agentId}`,
440
+ method: "put",
441
+ ...args,
442
+ });
443
+ },
444
+ async listSkills(args) {
445
+ return this._makeRequest({
446
+ url: "/admin/skills",
447
+ ...args,
448
+ });
449
+ },
450
+ async listRoles(args) {
451
+ return this._makeRequest({
452
+ url: "/roles",
453
+ ...args,
454
+ });
455
+ },
456
+ async listSolutionCategories(args) {
457
+ return this._makeRequest({
458
+ url: "/solutions/categories",
459
+ ...args,
460
+ });
461
+ },
462
+ async listCategoryFolders({
463
+ categoryId, ...args
464
+ }) {
465
+ return this._makeRequest({
466
+ url: `/solutions/categories/${categoryId}/folders`,
467
+ ...args,
468
+ });
469
+ },
470
+ async listFolderArticles({
471
+ folderId, ...args
472
+ }) {
473
+ return this._makeRequest({
474
+ url: `/solutions/folders/${folderId}/articles`,
475
+ ...args,
476
+ });
477
+ },
478
+ async getArticle({
479
+ articleId, ...args
480
+ }) {
481
+ return this._makeRequest({
482
+ url: `/solutions/articles/${articleId}`,
483
+ ...args,
484
+ });
485
+ },
486
+ async createArticle({
487
+ folderId, ...args
488
+ }) {
489
+ return this._makeRequest({
490
+ url: `/solutions/folders/${folderId}/articles`,
491
+ method: "post",
492
+ ...args,
493
+ });
494
+ },
495
+ async updateArticle({
496
+ articleId, ...args
497
+ }) {
498
+ return this._makeRequest({
499
+ url: `/solutions/articles/${articleId}`,
500
+ method: "put",
501
+ ...args,
502
+ });
503
+ },
504
+ async deleteArticle({
505
+ articleId, ...args
506
+ }) {
507
+ return this._makeRequest({
508
+ url: `/solutions/articles/${articleId}`,
509
+ method: "delete",
510
+ ...args,
511
+ });
512
+ },
253
513
  async listTickets(args) {
254
514
  return this._makeRequest({
255
515
  url: "/tickets",
@@ -375,5 +635,39 @@ export default {
375
635
  ...args,
376
636
  });
377
637
  },
638
+ async *paginate({
639
+ fn, args, max,
640
+ }) {
641
+ args = {
642
+ ...args,
643
+ params: {
644
+ ...args?.params,
645
+ page: 1,
646
+ per_page: 100,
647
+ },
648
+ };
649
+ let total, count = 0;
650
+ do {
651
+ const results = await fn(args);
652
+ total = results?.length;
653
+ if (!total) {
654
+ return;
655
+ }
656
+ for (const result of results) {
657
+ yield result;
658
+ if (max && ++count >= max) {
659
+ return;
660
+ }
661
+ }
662
+ args.params.page += 1;
663
+ } while (total === args.params.per_page);
664
+ },
665
+ async getPaginatedResources(opts) {
666
+ const results = [];
667
+ for await (const result of this.paginate(opts)) {
668
+ results.push(result);
669
+ }
670
+ return results;
671
+ },
378
672
  },
379
673
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pipedream/freshdesk",
3
- "version": "0.3.1",
3
+ "version": "0.4.0",
4
4
  "description": "Pipedream Freshdesk Components",
5
5
  "main": "freshdesk.app.mjs",
6
6
  "keywords": [
@@ -0,0 +1,63 @@
1
+ import freshdesk from "../../freshdesk.app.mjs";
2
+ import { DEFAULT_POLLING_SOURCE_TIMER_INTERVAL } from "@pipedream/platform";
3
+ import moment from "moment";
4
+
5
+ export default {
6
+ props: {
7
+ freshdesk,
8
+ timer: {
9
+ type: "$.interface.timer",
10
+ default: {
11
+ intervalSeconds: DEFAULT_POLLING_SOURCE_TIMER_INTERVAL,
12
+ },
13
+ },
14
+ db: "$.service.db",
15
+ },
16
+ methods: {
17
+ getResourceFn() {
18
+ throw new Error("getResourceFn is not implemented");
19
+ },
20
+ getTsField() {
21
+ throw new Error("getTsField is not implemented");
22
+ },
23
+ generateMeta() {
24
+ throw new Error("generateMeta is not implemented");
25
+ },
26
+ },
27
+ async run() {
28
+ const data = [];
29
+ let lastDateChecked = this.freshdesk.getLastDateChecked(this.db);
30
+ if (!lastDateChecked) {
31
+ lastDateChecked = new Date().toISOString();
32
+ this.freshdesk.setLastDateChecked(this.db, lastDateChecked);
33
+ }
34
+ let maxTs = lastDateChecked;
35
+
36
+ const resourceFn = this.getResourceFn();
37
+ const tsField = this.getTsField();
38
+
39
+ const formatedDate = lastDateChecked.substr(
40
+ 0,
41
+ (lastDateChecked + "T").indexOf("T"),
42
+ );
43
+ const results = await resourceFn({
44
+ query: `"${tsField}:>'${formatedDate}'"`,
45
+ page: 1,
46
+ });
47
+ for await (const result of results) {
48
+ data.push(result);
49
+ }
50
+
51
+ data &&
52
+ data.reverse().forEach((item) => {
53
+ if (moment(item[tsField]).isAfter(lastDateChecked)) {
54
+ if (moment(item[tsField]).isAfter(maxTs)) {
55
+ maxTs = item[tsField];
56
+ }
57
+ this.$emit(item, this.generateMeta(item));
58
+ }
59
+ });
60
+
61
+ this.freshdesk.setLastDateChecked(this.db, maxTs);
62
+ },
63
+ };
@@ -0,0 +1,28 @@
1
+ import common from "../common/polling.mjs";
2
+
3
+ export default {
4
+ ...common,
5
+ key: "freshdesk-contact-updated",
6
+ name: "Contact Updated",
7
+ description: "Emit new event when a contact is updated. [See the documentation](https://developers.freshdesk.com/api/#filter_contacts)",
8
+ version: "0.0.1",
9
+ type: "source",
10
+ dedupe: "unique",
11
+ methods: {
12
+ ...common.methods,
13
+ getResourceFn() {
14
+ return this.freshdesk.filterContacts;
15
+ },
16
+ getTsField() {
17
+ return "updated_at";
18
+ },
19
+ generateMeta(item) {
20
+ const ts = Date.parse(item.updated_at);
21
+ return {
22
+ id: `${item.id}-${ts}`,
23
+ summary: `Contact Updated (ID: ${item.id})`,
24
+ ts,
25
+ };
26
+ },
27
+ },
28
+ };
@@ -1,49 +1,27 @@
1
- import freshdesk from "../../freshdesk.app.mjs";
2
- import moment from "moment";
3
- import { DEFAULT_POLLING_SOURCE_TIMER_INTERVAL } from "@pipedream/platform";
1
+ import common from "../common/polling.mjs";
4
2
 
5
3
  export default {
4
+ ...common,
6
5
  key: "freshdesk-new-contact",
7
6
  name: "New Contact Created",
8
7
  description: "Emit new event when a contact is created. [See the documentation](https://developers.freshdesk.com/api/#filter_contacts)",
9
- version: "0.0.7",
8
+ version: "0.0.8",
10
9
  type: "source",
11
- props: {
12
- freshdesk,
13
- timer: {
14
- type: "$.interface.timer",
15
- default: {
16
- intervalSeconds: DEFAULT_POLLING_SOURCE_TIMER_INTERVAL,
17
- },
18
- },
19
- db: "$.service.db",
20
- },
21
10
  dedupe: "unique",
22
- async run() {
23
- const data = [];
24
- let lastDateChecked = this.freshdesk.getLastDateChecked(this.db);
25
- if (!lastDateChecked) {
26
- lastDateChecked = new Date().toISOString();
27
- this.freshdesk.setLastDateChecked(this.db, lastDateChecked);
28
- }
29
- const formatedDate = lastDateChecked.substr(0, (lastDateChecked + "T").indexOf("T"));
30
- const contacts = await this.freshdesk.filterContacts({
31
- query: `"created_at:>'${formatedDate}'"`,
32
- page: 1,
33
- });
34
- for await (const contact of contacts) {
35
- data.push(contact);
36
- }
37
- data && data.reverse().forEach((contact) => {
38
- this.freshdesk.setLastDateChecked(this.db, contact.created_at);
39
- if (moment(contact.created_at).isAfter(lastDateChecked)) {
40
- this.$emit(contact,
41
- {
42
- id: contact.id,
43
- summary: `New Contact: "${contact.name}"`,
44
- ts: Date.parse(contact.created_at),
45
- });
46
- }
47
- });
11
+ methods: {
12
+ ...common.methods,
13
+ getResourceFn() {
14
+ return this.freshdesk.filterContacts;
15
+ },
16
+ getTsField() {
17
+ return "created_at";
18
+ },
19
+ generateMeta(item) {
20
+ return {
21
+ id: item.id,
22
+ summary: `New Contact: "${item.name}"`,
23
+ ts: Date.parse(item.created_at),
24
+ };
25
+ },
48
26
  },
49
27
  };
@@ -1,52 +1,27 @@
1
- import freshdesk from "../../freshdesk.app.mjs";
2
- import moment from "moment";
3
- import { DEFAULT_POLLING_SOURCE_TIMER_INTERVAL } from "@pipedream/platform";
1
+ import common from "../common/polling.mjs";
4
2
 
5
3
  export default {
4
+ ...common,
6
5
  key: "freshdesk-new-ticket",
7
6
  name: "New Ticket Created",
8
7
  description: "Emit new event when a ticket is created. [See the documentation](https://developers.freshdesk.com/api/#filter_tickets)",
9
- version: "0.0.7",
8
+ version: "0.0.8",
10
9
  type: "source",
11
- props: {
12
- freshdesk,
13
- timer: {
14
- type: "$.interface.timer",
15
- default: {
16
- intervalSeconds: DEFAULT_POLLING_SOURCE_TIMER_INTERVAL,
17
- },
18
- },
19
- db: "$.service.db",
20
- },
21
10
  dedupe: "unique",
22
- async run() {
23
- const data = [];
24
- let lastDateChecked = this.freshdesk.getLastDateChecked(this.db);
25
- if (!lastDateChecked) {
26
- lastDateChecked = new Date().toISOString();
27
- this.freshdesk.setLastDateChecked(this.db, lastDateChecked);
28
- }
29
- const formatedDate = lastDateChecked.substr(
30
- 0,
31
- (lastDateChecked + "T").indexOf("T"),
32
- );
33
- const tickets = await this.freshdesk.filterTickets({
34
- query: `"created_at:>'${formatedDate}'"`,
35
- page: 1,
36
- });
37
- for await (const ticket of tickets) {
38
- data.push(ticket);
39
- }
40
- data &&
41
- data.reverse().forEach((ticket) => {
42
- this.freshdesk.setLastDateChecked(this.db, ticket.created_at);
43
- if (moment(ticket.created_at).isAfter(lastDateChecked)) {
44
- this.$emit(ticket, {
45
- id: ticket.id,
46
- summary: `New Ticket (ID: ${ticket.id})`,
47
- ts: Date.parse(ticket.created_at),
48
- });
49
- }
50
- });
11
+ methods: {
12
+ ...common.methods,
13
+ getResourceFn() {
14
+ return this.freshdesk.filterTickets;
15
+ },
16
+ getTsField() {
17
+ return "created_at";
18
+ },
19
+ generateMeta(item) {
20
+ return {
21
+ id: item.id,
22
+ summary: `New Ticket (ID: ${item.id})`,
23
+ ts: Date.parse(item.created_at),
24
+ };
25
+ },
51
26
  },
52
27
  };
@@ -0,0 +1,28 @@
1
+ import common from "../common/polling.mjs";
2
+
3
+ export default {
4
+ ...common,
5
+ key: "freshdesk-ticket-updated",
6
+ name: "Ticket Updated",
7
+ description: "Emit new event when a ticket is updated. [See the documentation](https://developers.freshdesk.com/api/#filter_tickets)",
8
+ version: "0.0.1",
9
+ type: "source",
10
+ dedupe: "unique",
11
+ methods: {
12
+ ...common.methods,
13
+ getResourceFn() {
14
+ return this.freshdesk.filterTickets;
15
+ },
16
+ getTsField() {
17
+ return "updated_at";
18
+ },
19
+ generateMeta(item) {
20
+ const ts = Date.parse(item.updated_at);
21
+ return {
22
+ id: `${item.id}-${ts}`,
23
+ summary: `Ticket Updated (ID: ${item.id})`,
24
+ ts,
25
+ };
26
+ },
27
+ },
28
+ };