From fc704c01c8895b8f9a9e13416afe33044450959f Mon Sep 17 00:00:00 2001 From: seynadio <79858321+seynadio@users.noreply.github.com> Date: Mon, 14 Jul 2025 10:42:31 +0200 Subject: [PATCH 1/6] fix issues --- .../actions/update-ticket/update-ticket.mjs | 41 ++++++++++++++++--- 1 file changed, 35 insertions(+), 6 deletions(-) diff --git a/components/freshdesk/actions/update-ticket/update-ticket.mjs b/components/freshdesk/actions/update-ticket/update-ticket.mjs index f1dd5c8c1e7df..641b0e3d8d047 100644 --- a/components/freshdesk/actions/update-ticket/update-ticket.mjs +++ b/components/freshdesk/actions/update-ticket/update-ticket.mjs @@ -5,7 +5,7 @@ export default { key: "freshdesk-update-ticket", name: "Update a Ticket", description: "Update status, priority, subject, description, agent, group, etc. [See the documentation](https://developers.freshdesk.com/api/#update_ticket).", - version: "0.0.1", + version: "0.0.2", type: "action", props: { freshdesk, @@ -71,6 +71,19 @@ export default { description: "Used when creating a contact with phone but no email.", optional: true, }, + internalNote: { + type: "boolean", + label: "Internal note (private)", + description: "If enabled, the comment will be added as an internal note (not visible to requester).", + optional: true, + default: false, + }, + noteBody: { + type: "string", + label: "Note Body", + description: "The content of the internal note to add.", + optional: true, + }, type: { type: "string", label: "Type", @@ -95,6 +108,8 @@ export default { const { freshdesk, ticketId, + internalNote, + noteBody, ...fields } = this; @@ -102,21 +117,35 @@ export default { const ticketName = await freshdesk.getTicketName(ticketId); + if (internalNote && noteBody) { + const response = await freshdesk._makeRequest({ + $, + method: "POST", + url: `/tickets/${ticketId}/notes`, + data: { + body: noteBody, + private: true, + }, + }); + + $.export("$summary", `Internal note added to ticket "${ticketName}" (ID: ${ticketId})`); + return response; + } + if (!Object.keys(data).length) { throw new Error("Please provide at least one field to update."); } - + if (data.custom_fields) freshdesk.parseIfJSONString(data.custom_fields); - + const response = await freshdesk._makeRequest({ $, method: "PUT", url: `/tickets/${ticketId}`, data, }); - + $.export("$summary", `Ticket "${ticketName}" (ID: ${this.ticketId}) updated successfully`); return response; }, -}; - +} \ No newline at end of file From 7f304472eec2db81dffd0d50f6cd8ad8039e8f9b Mon Sep 17 00:00:00 2001 From: Job Nijenhuis Date: Fri, 18 Jul 2025 14:03:50 +0200 Subject: [PATCH 2/6] Refactor Freshdesk: Create separate add-note-to-ticket action MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Created dedicated add-note-to-ticket action for better separation of concerns - Removed note functionality from update-ticket action to maintain single responsibility - Added addNoteToTicket method to freshdesk.app.mjs - Bumped update-ticket version to 0.0.3 This provides a cleaner API where each action has a clear, single purpose. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- .../add-note-to-ticket/add-note-to-ticket.mjs | 95 +++++++++++++++++++ .../actions/update-ticket/update-ticket.mjs | 40 +------- components/freshdesk/freshdesk.app.mjs | 10 ++ 3 files changed, 110 insertions(+), 35 deletions(-) create mode 100644 components/freshdesk/actions/add-note-to-ticket/add-note-to-ticket.mjs diff --git a/components/freshdesk/actions/add-note-to-ticket/add-note-to-ticket.mjs b/components/freshdesk/actions/add-note-to-ticket/add-note-to-ticket.mjs new file mode 100644 index 0000000000000..0b1fa21f10e0e --- /dev/null +++ b/components/freshdesk/actions/add-note-to-ticket/add-note-to-ticket.mjs @@ -0,0 +1,95 @@ +import freshdesk from "../../freshdesk.app.mjs"; +import { ConfigurationError } from "@pipedream/platform"; + +export default { + key: "freshdesk-add-note-to-ticket", + name: "Add Note to Ticket", + description: "Add a note or conversation to an existing ticket. [See the documentation](https://developers.freshdesk.com/api/#add_note_to_a_ticket).", + version: "0.0.1", + type: "action", + props: { + freshdesk, + ticketId: { + propDefinition: [ + freshdesk, + "ticketId", + ], + }, + body: { + type: "string", + label: "Note Body", + description: "Content of the note in HTML format", + }, + private: { + type: "boolean", + label: "Private Note", + description: "Set to true if the note is private (internal)", + default: false, + }, + incoming: { + type: "boolean", + label: "Incoming", + description: "Set to true if the note should be marked as incoming (false for outgoing)", + default: false, + optional: true, + }, + user_id: { + propDefinition: [ + freshdesk, + "agentId", + ], + label: "User ID", + description: "ID of the user creating the note (defaults to the API user)", + optional: true, + }, + notify_emails: { + type: "string[]", + label: "Notify Emails", + description: "Array of email addresses to notify about this note", + optional: true, + }, + }, + async run({ $ }) { + const { + freshdesk, + ticketId, + body, + private: isPrivate, + incoming, + user_id, + notify_emails, + } = this; + + if (!body || !body.trim()) { + throw new ConfigurationError("Note body cannot be empty"); + } + + const ticketName = await freshdesk.getTicketName(ticketId); + + const data = { + body, + private: isPrivate, + }; + + if (incoming !== undefined) { + data.incoming = incoming; + } + + if (user_id) { + data.user_id = Number(user_id); + } + + if (notify_emails && notify_emails.length > 0) { + data.notify_emails = notify_emails; + } + + const response = await freshdesk.addNoteToTicket({ + $, + ticketId: Number(ticketId), + data, + }); + + $.export("$summary", `Note added to ticket "${ticketName}" (ID: ${ticketId})`); + return response; + }, +}; diff --git a/components/freshdesk/actions/update-ticket/update-ticket.mjs b/components/freshdesk/actions/update-ticket/update-ticket.mjs index 641b0e3d8d047..92f69c27c4041 100644 --- a/components/freshdesk/actions/update-ticket/update-ticket.mjs +++ b/components/freshdesk/actions/update-ticket/update-ticket.mjs @@ -5,7 +5,7 @@ export default { key: "freshdesk-update-ticket", name: "Update a Ticket", description: "Update status, priority, subject, description, agent, group, etc. [See the documentation](https://developers.freshdesk.com/api/#update_ticket).", - version: "0.0.2", + version: "0.0.3", type: "action", props: { freshdesk, @@ -71,19 +71,6 @@ export default { description: "Used when creating a contact with phone but no email.", optional: true, }, - internalNote: { - type: "boolean", - label: "Internal note (private)", - description: "If enabled, the comment will be added as an internal note (not visible to requester).", - optional: true, - default: false, - }, - noteBody: { - type: "string", - label: "Note Body", - description: "The content of the internal note to add.", - optional: true, - }, type: { type: "string", label: "Type", @@ -108,8 +95,6 @@ export default { const { freshdesk, ticketId, - internalNote, - noteBody, ...fields } = this; @@ -117,35 +102,20 @@ export default { const ticketName = await freshdesk.getTicketName(ticketId); - if (internalNote && noteBody) { - const response = await freshdesk._makeRequest({ - $, - method: "POST", - url: `/tickets/${ticketId}/notes`, - data: { - body: noteBody, - private: true, - }, - }); - - $.export("$summary", `Internal note added to ticket "${ticketName}" (ID: ${ticketId})`); - return response; - } - if (!Object.keys(data).length) { throw new Error("Please provide at least one field to update."); } - + if (data.custom_fields) freshdesk.parseIfJSONString(data.custom_fields); - + const response = await freshdesk._makeRequest({ $, method: "PUT", url: `/tickets/${ticketId}`, data, }); - + $.export("$summary", `Ticket "${ticketName}" (ID: ${this.ticketId}) updated successfully`); return response; }, -} \ No newline at end of file +}; diff --git a/components/freshdesk/freshdesk.app.mjs b/components/freshdesk/freshdesk.app.mjs index fe405b1c37151..774f737965db4 100644 --- a/components/freshdesk/freshdesk.app.mjs +++ b/components/freshdesk/freshdesk.app.mjs @@ -266,5 +266,15 @@ export default { } return input; }, + async addNoteToTicket({ + ticketId, data, ...args + }) { + return this._makeRequest({ + url: `/tickets/${ticketId}/notes`, + method: "post", + data, + ...args, + }); + }, }, }; From 00fe76be5d4a8f603829cf8e5d0c7aca53a95ed3 Mon Sep 17 00:00:00 2001 From: Job Nijenhuis Date: Fri, 18 Jul 2025 14:04:31 +0200 Subject: [PATCH 3/6] Update pnpm-lock.yaml --- pnpm-lock.yaml | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b38fc416d13e0..c93473523dcfd 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9840,8 +9840,7 @@ importers: components/paypro: {} - components/payrexx: - specifiers: {} + components/payrexx: {} components/paystack: dependencies: @@ -15877,14 +15876,6 @@ importers: specifier: ^6.0.0 version: 6.2.0 - modelcontextprotocol/node_modules2/@modelcontextprotocol/sdk/dist/cjs: {} - - modelcontextprotocol/node_modules2/@modelcontextprotocol/sdk/dist/esm: {} - - modelcontextprotocol/node_modules2/zod-to-json-schema/dist/cjs: {} - - modelcontextprotocol/node_modules2/zod-to-json-schema/dist/esm: {} - packages/ai: dependencies: '@pipedream/sdk': From 78031620064261122a6b8c1d7b56e8e0ee6e7701 Mon Sep 17 00:00:00 2001 From: Job <9075380+Afstkla@users.noreply.github.com> Date: Fri, 18 Jul 2025 14:08:16 +0200 Subject: [PATCH 4/6] Update update-ticket.mjs --- components/freshdesk/actions/update-ticket/update-ticket.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/freshdesk/actions/update-ticket/update-ticket.mjs b/components/freshdesk/actions/update-ticket/update-ticket.mjs index 92f69c27c4041..6eb98eef103af 100644 --- a/components/freshdesk/actions/update-ticket/update-ticket.mjs +++ b/components/freshdesk/actions/update-ticket/update-ticket.mjs @@ -5,7 +5,7 @@ export default { key: "freshdesk-update-ticket", name: "Update a Ticket", description: "Update status, priority, subject, description, agent, group, etc. [See the documentation](https://developers.freshdesk.com/api/#update_ticket).", - version: "0.0.3", + version: "0.0.1", type: "action", props: { freshdesk, From 8a0841ebfda69ea0ace6467f92ec760a2da47d68 Mon Sep 17 00:00:00 2001 From: Job Nijenhuis Date: Fri, 18 Jul 2025 14:10:57 +0200 Subject: [PATCH 5/6] whitespace --- components/freshdesk/actions/update-ticket/update-ticket.mjs | 1 + 1 file changed, 1 insertion(+) diff --git a/components/freshdesk/actions/update-ticket/update-ticket.mjs b/components/freshdesk/actions/update-ticket/update-ticket.mjs index 6eb98eef103af..f1dd5c8c1e7df 100644 --- a/components/freshdesk/actions/update-ticket/update-ticket.mjs +++ b/components/freshdesk/actions/update-ticket/update-ticket.mjs @@ -119,3 +119,4 @@ export default { return response; }, }; + From 65ee1163f9d6146814e9b23342fe444bf693b4bb Mon Sep 17 00:00:00 2001 From: Job Nijenhuis Date: Fri, 18 Jul 2025 14:32:33 +0200 Subject: [PATCH 6/6] fix: Address PR review comments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add JSDoc documentation to addNoteToTicket method - Add error handling for missing tickets in getTicketName (returns null for 404) - Add validation for user_id parameter to ensure valid number - Add email validation for notify_emails array - Update ticket name handling to use fallback when null 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- .../add-note-to-ticket/add-note-to-ticket.mjs | 13 +++++++-- .../actions/update-ticket/update-ticket.mjs | 2 +- components/freshdesk/freshdesk.app.mjs | 28 ++++++++++++++++--- 3 files changed, 36 insertions(+), 7 deletions(-) diff --git a/components/freshdesk/actions/add-note-to-ticket/add-note-to-ticket.mjs b/components/freshdesk/actions/add-note-to-ticket/add-note-to-ticket.mjs index 0b1fa21f10e0e..f8fa1cc684abd 100644 --- a/components/freshdesk/actions/add-note-to-ticket/add-note-to-ticket.mjs +++ b/components/freshdesk/actions/add-note-to-ticket/add-note-to-ticket.mjs @@ -64,7 +64,7 @@ export default { throw new ConfigurationError("Note body cannot be empty"); } - const ticketName = await freshdesk.getTicketName(ticketId); + const ticketName = await freshdesk.getTicketName(ticketId) || "Unknown Ticket"; const data = { body, @@ -76,10 +76,19 @@ export default { } if (user_id) { - data.user_id = Number(user_id); + const userId = Number(user_id); + if (isNaN(userId)) { + throw new ConfigurationError("User ID must be a valid number"); + } + data.user_id = userId; } if (notify_emails && notify_emails.length > 0) { + const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; + const invalidEmails = notify_emails.filter((email) => !emailRegex.test(email)); + if (invalidEmails.length > 0) { + throw new ConfigurationError(`Invalid email addresses: ${invalidEmails.join(", ")}`); + } data.notify_emails = notify_emails; } diff --git a/components/freshdesk/actions/update-ticket/update-ticket.mjs b/components/freshdesk/actions/update-ticket/update-ticket.mjs index f1dd5c8c1e7df..2822463ce2aea 100644 --- a/components/freshdesk/actions/update-ticket/update-ticket.mjs +++ b/components/freshdesk/actions/update-ticket/update-ticket.mjs @@ -100,7 +100,7 @@ export default { const data = removeNullEntries(fields); - const ticketName = await freshdesk.getTicketName(ticketId); + const ticketName = await freshdesk.getTicketName(ticketId) || "Unknown Ticket"; if (!Object.keys(data).length) { throw new Error("Please provide at least one field to update."); diff --git a/components/freshdesk/freshdesk.app.mjs b/components/freshdesk/freshdesk.app.mjs index 774f737965db4..8d856e11b80b1 100644 --- a/components/freshdesk/freshdesk.app.mjs +++ b/components/freshdesk/freshdesk.app.mjs @@ -251,10 +251,17 @@ export default { }); }, async getTicketName(ticketId) { - const ticket = await this.getTicket({ - ticketId, - }); - return ticket.subject; + try { + const ticket = await this.getTicket({ + ticketId, + }); + return ticket.subject; + } catch (error) { + if (error.response?.status === 404) { + return null; + } + throw error; + } }, parseIfJSONString(input) { if (typeof input === "string") { @@ -266,6 +273,19 @@ export default { } return input; }, + /** + * Add a note to a Freshdesk ticket + * @param {Object} options - The options object + * @param {number} options.ticketId - The ID of the ticket to add the note to + * @param {Object} options.data - The note data object + * @param {string} options.data.body - Content of the note in HTML format + * @param {boolean} [options.data.private=false] - Whether the note is private + * @param {boolean} [options.data.incoming] - Whether the note is incoming + * @param {number} [options.data.user_id] - ID of the user creating the note + * @param {string[]} [options.data.notify_emails] - Array of email addresses to notify + * @param {...*} args - Additional arguments passed to _makeRequest + * @returns {Promise} The API response containing the created note + */ async addNoteToTicket({ ticketId, data, ...args }) {