-
Notifications
You must be signed in to change notification settings - Fork 5.4k
Hubspot - Conversations support #17601
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Hubspot - Conversations support #17601
Conversation
- Add conversation API methods to HubSpot app (getConversationThread, getConversationMessages, sendConversationMessage, addConversationComment) - Add threadId prop definition for conversation threads - Create send-conversation-message action for regular messages - Create add-conversation-comment action for internal notes (COMMENT type) - Add webhook sources for conversation messages and internal comments - Update package version to 1.2.5 - Support HubSpot Conversations API v3 endpoints
WalkthroughThe changes introduce new capabilities for both Freshdesk and HubSpot integrations. Freshdesk's update-ticket action now supports adding internal notes. For HubSpot, new actions and sources allow sending messages, adding internal comments to conversation threads, and emitting events for new messages or internal notes. Supporting API methods and property definitions were added to the HubSpot app module. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant FreshdeskAction
participant FreshdeskAPI
User->>FreshdeskAction: Run update-ticket with internalNote/noteBody
alt internalNote is true and noteBody provided
FreshdeskAction->>FreshdeskAPI: POST /tickets/{ticketId}/notes (private note)
FreshdeskAPI-->>FreshdeskAction: Note creation response
FreshdeskAction-->>User: Return note response
else
FreshdeskAction->>FreshdeskAPI: PUT /tickets/{ticketId} (update fields)
FreshdeskAPI-->>FreshdeskAction: Ticket update response
FreshdeskAction-->>User: Return update response
end
sequenceDiagram
participant User
participant HubSpotAction
participant HubSpotApp
participant HubSpotAPI
User->>HubSpotAction: Add comment/send message to thread
HubSpotAction->>HubSpotApp: addConversationComment/sendConversationMessage
HubSpotApp->>HubSpotAPI: POST /conversations/v3/conversations/threads/{threadId}/messages
HubSpotAPI-->>HubSpotApp: API response
HubSpotApp-->>HubSpotAction: Return response
HubSpotAction-->>User: Return result
sequenceDiagram
participant HubSpotSource
participant HubSpotApp
participant HubSpotAPI
participant Workflow
HubSpotSource->>HubSpotApp: getConversationMessages/addConversationComment (polling)
HubSpotApp->>HubSpotAPI: GET /conversations/v3/conversations/threads/{threadId}/messages
HubSpotAPI-->>HubSpotApp: Messages/comments data
HubSpotApp-->>HubSpotSource: Data
HubSpotSource-->>Workflow: Emit event if new message/comment found
Poem
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
components/hubspot/actions/add-conversation-comment/add-conversation-comment.mjsOops! Something went wrong! :( ESLint: 8.57.1 Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'jsonc-eslint-parser' imported from /eslint.config.mjs components/freshdesk/actions/update-ticket/update-ticket.mjsOops! Something went wrong! :( ESLint: 8.57.1 Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'jsonc-eslint-parser' imported from /eslint.config.mjs components/hubspot/actions/send-conversation-message/send-conversation-message.mjsOops! Something went wrong! :( ESLint: 8.57.1 Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'jsonc-eslint-parser' imported from /eslint.config.mjs
✨ Finishing Touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
The latest updates on your projects. Learn more about Vercel for Git ↗︎ |
Thank you so much for submitting this! We've added it to our backlog to review, and our team has been notified. |
@seynadio is attempting to deploy a commit to the Pipedreamers Team on Vercel. A member of the Team first needs to authorize it. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (7)
components/freshdesk/actions/update-ticket/update-ticket.mjs
(3 hunks)components/hubspot/actions/add-conversation-comment/add-conversation-comment.mjs
(1 hunks)components/hubspot/actions/send-conversation-message/send-conversation-message.mjs
(1 hunks)components/hubspot/hubspot.app.mjs
(2 hunks)components/hubspot/package.json
(1 hunks)components/hubspot/sources/new-conversation-comment/new-conversation-comment.mjs
(1 hunks)components/hubspot/sources/new-conversation-message/new-conversation-message.mjs
(1 hunks)
🧰 Additional context used
🧠 Learnings (5)
components/hubspot/package.json (1)
Learnt from: jcortes
PR: PipedreamHQ/pipedream#14935
File: components/sailpoint/package.json:15-18
Timestamp: 2024-12-12T19:23:09.039Z
Learning: When developing Pipedream components, do not add built-in Node.js modules like `fs` to `package.json` dependencies, as they are native modules provided by the Node.js runtime.
components/hubspot/actions/send-conversation-message/send-conversation-message.mjs (3)
Learnt from: GTFalcao
PR: PipedreamHQ/pipedream#12731
File: components/hackerone/actions/get-members/get-members.mjs:3-28
Timestamp: 2024-07-04T18:11:59.822Z
Learning: When exporting a summary message in the `run` method of an action, ensure the message is correctly formatted. For example, in the `hackerone-get-members` action, the correct format is `Successfully retrieved ${response.data.length} members`.
Learnt from: GTFalcao
PR: PipedreamHQ/pipedream#12731
File: components/hackerone/actions/get-members/get-members.mjs:3-28
Timestamp: 2024-10-08T15:33:38.240Z
Learning: When exporting a summary message in the `run` method of an action, ensure the message is correctly formatted. For example, in the `hackerone-get-members` action, the correct format is `Successfully retrieved ${response.data.length} members`.
Learnt from: jcortes
PR: PipedreamHQ/pipedream#14467
File: components/gainsight_px/actions/create-account/create-account.mjs:4-6
Timestamp: 2024-10-30T15:24:39.294Z
Learning: In `components/gainsight_px/actions/create-account/create-account.mjs`, the action name should be "Create Account" instead of "Create Memory".
components/hubspot/sources/new-conversation-message/new-conversation-message.mjs (4)
Learnt from: GTFalcao
PR: PipedreamHQ/pipedream#15376
File: components/monday/sources/name-updated/name-updated.mjs:6-6
Timestamp: 2025-01-23T03:55:15.166Z
Learning: Source names in Monday.com components don't need to start with "New" if they emit events for updated items (e.g., "Name Updated", "Column Value Updated") rather than new items. This follows the component guidelines exception where the "New" prefix is only required when emits are limited to new items.
Learnt from: GTFalcao
PR: PipedreamHQ/pipedream#12697
File: components/salesforce_rest_api/sources/common-webhook-methods.mjs:1-71
Timestamp: 2024-07-24T02:06:47.016Z
Learning: The `common-webhook-methods.mjs` object is designed to be extended, similar to an abstract class, and intentionally does not implement certain methods like `generateWebhookMeta` and `getEventType` to enforce implementation in subclasses.
Learnt from: GTFalcao
PR: PipedreamHQ/pipedream#12697
File: components/salesforce_rest_api/sources/common-webhook-methods.mjs:1-71
Timestamp: 2024-10-08T15:33:38.240Z
Learning: The `common-webhook-methods.mjs` object is designed to be extended, similar to an abstract class, and intentionally does not implement certain methods like `generateWebhookMeta` and `getEventType` to enforce implementation in subclasses.
Learnt from: GTFalcao
PR: PipedreamHQ/pipedream#14265
File: components/the_magic_drip/sources/common.mjs:35-43
Timestamp: 2024-10-10T19:18:27.998Z
Learning: In `components/the_magic_drip/sources/common.mjs`, when processing items in `getAndProcessData`, `savedIds` is intentionally updated with IDs of both emitted and non-emitted items to avoid emitting retroactive events upon first deployment and ensure only new events are emitted as they occur.
components/hubspot/sources/new-conversation-comment/new-conversation-comment.mjs (4)
Learnt from: GTFalcao
PR: PipedreamHQ/pipedream#15376
File: components/monday/sources/name-updated/name-updated.mjs:6-6
Timestamp: 2025-01-23T03:55:15.166Z
Learning: Source names in Monday.com components don't need to start with "New" if they emit events for updated items (e.g., "Name Updated", "Column Value Updated") rather than new items. This follows the component guidelines exception where the "New" prefix is only required when emits are limited to new items.
Learnt from: GTFalcao
PR: PipedreamHQ/pipedream#14265
File: components/the_magic_drip/sources/common.mjs:35-43
Timestamp: 2024-10-10T19:18:27.998Z
Learning: In `components/the_magic_drip/sources/common.mjs`, when processing items in `getAndProcessData`, `savedIds` is intentionally updated with IDs of both emitted and non-emitted items to avoid emitting retroactive events upon first deployment and ensure only new events are emitted as they occur.
Learnt from: GTFalcao
PR: PipedreamHQ/pipedream#12697
File: components/salesforce_rest_api/sources/common-webhook-methods.mjs:1-71
Timestamp: 2024-07-24T02:06:47.016Z
Learning: The `common-webhook-methods.mjs` object is designed to be extended, similar to an abstract class, and intentionally does not implement certain methods like `generateWebhookMeta` and `getEventType` to enforce implementation in subclasses.
Learnt from: GTFalcao
PR: PipedreamHQ/pipedream#12697
File: components/salesforce_rest_api/sources/common-webhook-methods.mjs:1-71
Timestamp: 2024-10-08T15:33:38.240Z
Learning: The `common-webhook-methods.mjs` object is designed to be extended, similar to an abstract class, and intentionally does not implement certain methods like `generateWebhookMeta` and `getEventType` to enforce implementation in subclasses.
components/hubspot/hubspot.app.mjs (3)
Learnt from: GTFalcao
PR: PipedreamHQ/pipedream#12697
File: components/salesforce_rest_api/sources/common-webhook-methods.mjs:1-71
Timestamp: 2024-10-08T15:33:38.240Z
Learning: The `common-webhook-methods.mjs` object is designed to be extended, similar to an abstract class, and intentionally does not implement certain methods like `generateWebhookMeta` and `getEventType` to enforce implementation in subclasses.
Learnt from: GTFalcao
PR: PipedreamHQ/pipedream#12697
File: components/salesforce_rest_api/sources/common-webhook-methods.mjs:1-71
Timestamp: 2024-07-24T02:06:47.016Z
Learning: The `common-webhook-methods.mjs` object is designed to be extended, similar to an abstract class, and intentionally does not implement certain methods like `generateWebhookMeta` and `getEventType` to enforce implementation in subclasses.
Learnt from: GTFalcao
PR: PipedreamHQ/pipedream#16954
File: components/salesloft/salesloft.app.mjs:14-23
Timestamp: 2025-06-04T17:52:05.780Z
Learning: In the Salesloft API integration (components/salesloft/salesloft.app.mjs), the _makeRequest method returns response.data which directly contains arrays for list endpoints like listPeople, listCadences, listUsers, and listAccounts. The propDefinitions correctly call .map() directly on these responses without needing to destructure a nested data property.
🔇 Additional comments (14)
components/hubspot/package.json (1)
3-3
: LGTM: Appropriate version bumpThe version increment from 1.2.4 to 1.2.5 correctly reflects the addition of new conversation features while maintaining backward compatibility.
components/freshdesk/actions/update-ticket/update-ticket.mjs (4)
8-8
: LGTM: Appropriate version bumpThe version increment correctly reflects the addition of new internal note functionality.
74-86
: LGTM: Well-structured internal note propertiesThe new properties are properly defined with appropriate types, labels, and descriptions. The boolean default for
internalNote
and optional nature of both properties provide good user experience.
120-133
: Consider design limitation: exclusive operation modeThe current implementation uses an early return when adding internal notes, which means users cannot both add an internal note AND update ticket fields in a single action execution. This might be a limitation depending on use case requirements.
Consider whether this exclusive behavior is intentional or if users might need to perform both operations simultaneously.
121-132
: LGTM: Correct API implementation and summary formattingThe internal note API call follows the established pattern, correctly sets the note as private, and uses proper summary message formatting as per the learning guidelines.
components/hubspot/actions/send-conversation-message/send-conversation-message.mjs (1)
1-60
: LGTM —sendConversationMessage
method verified
- Confirmed that
sendConversationMessage
is implemented incomponents/hubspot/hubspot.app.mjs
.- No further changes required; action structure and summary formatting are correct.
components/hubspot/actions/add-conversation-comment/add-conversation-comment.mjs (1)
1-43
: Approve HubSpot Add Conversation Comment action (method verified)I’ve confirmed that the
addConversationComment
method exists incomponents/hubspot/hubspot.app.mjs
and matches the expected signature and API call structure. The action implementation is consistent and ready to merge.components/hubspot/sources/new-conversation-message/new-conversation-message.mjs (3)
5-6
: LGTM: Appropriate source naming conventionThe source name "New Conversation Message" correctly follows the convention where sources emitting events for new items should start with "New" as per the learning guidelines.
13-41
: LGTM: Well-designed filtering propertiesThe threadId and messageType properties provide excellent filtering capabilities:
- Optional threadId for specific conversation filtering
- messageType options are comprehensive (All, Regular Messages, Internal Comments)
- Proper default values and descriptions
45-62
: LGTM: Solid helper methods implementationThe helper methods are well-implemented:
getTs()
properly parses timestampsgenerateMeta()
creates appropriate metadata with correct message type labelingisRelevant()
implements comprehensive filtering logiccomponents/hubspot/hubspot.app.mjs (2)
127-131
: LGTM: Clean property definition for conversation thread ID.The threadId property definition is correctly implemented with appropriate type, label, and description.
1150-1207
: Ignore missingapi
parameter for conversation endpointsThe HubSpot client’s
makeRequest
helper falls back to using the base URL plus whatever you put inendpoint
(e.g./conversations/v3/...
), so you don’t need to supply anapi
key here—and in fact there is noAPI_PATH.CONVERSATIONS_V3
defined incomponents/hubspot/common/constants.mjs
. The existing methods correctly call:
GET https://api.hubapi.com/conversations/v3/conversations/threads/{threadId}
GET https://api.hubapi.com/conversations/v3/conversations/threads/{threadId}/messages
POST https://api.hubapi.com/conversations/v3/conversations/threads/{threadId}/messages
As for
sendConversationMessage
vs.addConversationComment
, they both POST to the same endpoint by design; you distinguish a regular message from an internal comment via the request payload (e.g. anisInternal
flag), not via separate routes.Likely an incorrect or invalid review comment.
components/hubspot/sources/new-conversation-comment/new-conversation-comment.mjs (2)
1-21
: LGTM: Well-structured component setup with appropriate props.The component correctly extends the common base and includes the necessary threadId prop for filtering specific conversation threads.
22-47
: LGTM: Helper methods are correctly implemented.The
getTs
,generateMeta
, andisRelevant
methods properly handle comment processing with appropriate filtering logic for timestamp, thread ID, and comment type.
async processResults(after, params) { | ||
// Note: This is a placeholder implementation | ||
// In a real implementation, you would need to: | ||
// 1. List conversation threads | ||
// 2. For each thread, get messages | ||
// 3. Filter based on timestamp and props | ||
// 4. Process events | ||
|
||
// For now, we'll use a webhook-based approach | ||
// This source would need to be enhanced with actual API calls | ||
// to poll for new messages if HubSpot doesn't provide webhooks | ||
|
||
console.log("Conversation message polling not yet implemented - use webhooks instead"); | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Implement proper processResults functionality
The processResults
method is incomplete with just placeholder comments and a console.log statement. This needs to be implemented properly:
- Remove the console.log statement (inappropriate for production)
- Implement actual API calls to fetch conversation messages
- Either implement polling logic or properly set up webhook handling
- async processResults(after, params) {
- // Note: This is a placeholder implementation
- // In a real implementation, you would need to:
- // 1. List conversation threads
- // 2. For each thread, get messages
- // 3. Filter based on timestamp and props
- // 4. Process events
-
- // For now, we'll use a webhook-based approach
- // This source would need to be enhanced with actual API calls
- // to poll for new messages if HubSpot doesn't provide webhooks
-
- console.log("Conversation message polling not yet implemented - use webhooks instead");
- },
+ async processResults(after, params) {
+ // TODO: Implement actual message fetching logic
+ // This would typically involve:
+ // 1. Fetching conversation threads (with threadId filter if specified)
+ // 2. Getting messages from each thread
+ // 3. Filtering messages based on timestamp and messageType
+ // 4. Emitting events for relevant messages
+
+ throw new Error("Polling implementation not yet complete - this source requires webhook configuration");
+ },
Would you like me to help implement the proper polling logic or webhook setup for this source?
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
async processResults(after, params) { | |
// Note: This is a placeholder implementation | |
// In a real implementation, you would need to: | |
// 1. List conversation threads | |
// 2. For each thread, get messages | |
// 3. Filter based on timestamp and props | |
// 4. Process events | |
// For now, we'll use a webhook-based approach | |
// This source would need to be enhanced with actual API calls | |
// to poll for new messages if HubSpot doesn't provide webhooks | |
console.log("Conversation message polling not yet implemented - use webhooks instead"); | |
}, | |
async processResults(after, params) { | |
// TODO: Implement actual message fetching logic | |
// This would typically involve: | |
// 1. Fetching conversation threads (with threadId filter if specified) | |
// 2. Getting messages from each thread | |
// 3. Filtering messages based on timestamp and messageType | |
// 4. Emitting events for relevant messages | |
throw new Error("Polling implementation not yet complete - this source requires webhook configuration"); | |
}, |
🤖 Prompt for AI Agents
In
components/hubspot/sources/new-conversation-message/new-conversation-message.mjs
around lines 70 to 83, the processResults method currently only contains
placeholder comments and a console.log statement. Remove the console.log and
replace it with actual API calls to list conversation threads and fetch messages
for each thread. Implement filtering based on timestamps and relevant
properties, then process the resulting events. Depending on the design, either
add polling logic to regularly fetch new messages or integrate webhook handling
to receive updates in real time.
async processResults(after, params) { | ||
// Note: This is a placeholder implementation | ||
// In a real implementation, you would need to: | ||
// 1. List conversation threads | ||
// 2. For each thread, get messages | ||
// 3. Filter for COMMENT type messages | ||
// 4. Process events | ||
|
||
// For now, we'll use a webhook-based approach | ||
// This source would need to be enhanced with actual API calls | ||
// to poll for new comments if HubSpot doesn't provide webhooks | ||
|
||
console.log("Conversation comment polling not yet implemented - use webhooks instead"); | ||
}, | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Complete the polling implementation or provide webhook alternative.
The processResults
method is incomplete with only placeholder comments. This makes the component non-functional for users who expect polling-based event emission.
Consider implementing the actual polling logic using the new HubSpot app methods:
async processResults(after, params) {
- // Note: This is a placeholder implementation
- // In a real implementation, you would need to:
- // 1. List conversation threads
- // 2. For each thread, get messages
- // 3. Filter for COMMENT type messages
- // 4. Process events
-
- // For now, we'll use a webhook-based approach
- // This source would need to be enhanced with actual API calls
- // to poll for new comments if HubSpot doesn't provide webhooks
-
- console.log("Conversation comment polling not yet implemented - use webhooks instead");
+ try {
+ // If threadId is specified, only check that thread
+ if (this.threadId) {
+ const { results: messages } = await this.hubspot.getConversationMessages({
+ threadId: this.threadId,
+ ...params,
+ });
+
+ if (messages) {
+ for (const message of messages) {
+ if (this.isRelevant(message, after)) {
+ this.$emit(message, this.generateMeta(message));
+ }
+ }
+ }
+ } else {
+ // Note: This would require a method to list all conversation threads
+ // which may not be efficient for polling
+ console.log("Polling all threads not implemented - consider specifying threadId or use webhooks");
+ }
+ } catch (error) {
+ console.error("Error fetching conversation comments:", error);
+ }
},
Would you like me to help implement the complete polling logic or create a webhook-based alternative?
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
async processResults(after, params) { | |
// Note: This is a placeholder implementation | |
// In a real implementation, you would need to: | |
// 1. List conversation threads | |
// 2. For each thread, get messages | |
// 3. Filter for COMMENT type messages | |
// 4. Process events | |
// For now, we'll use a webhook-based approach | |
// This source would need to be enhanced with actual API calls | |
// to poll for new comments if HubSpot doesn't provide webhooks | |
console.log("Conversation comment polling not yet implemented - use webhooks instead"); | |
}, | |
}, | |
async processResults(after, params) { | |
try { | |
// If threadId is specified, only check that thread | |
if (this.threadId) { | |
const { results: messages } = await this.hubspot.getConversationMessages({ | |
threadId: this.threadId, | |
...params, | |
}); | |
if (messages) { | |
for (const message of messages) { | |
if (this.isRelevant(message, after)) { | |
this.$emit(message, this.generateMeta(message)); | |
} | |
} | |
} | |
} else { | |
// Note: This would require a method to list all conversation threads | |
// which may not be efficient for polling | |
console.log("Polling all threads not implemented - consider specifying threadId or use webhooks"); | |
} | |
} catch (error) { | |
console.error("Error fetching conversation comments:", error); | |
} | |
}, |
🤖 Prompt for AI Agents
In
components/hubspot/sources/new-conversation-comment/new-conversation-comment.mjs
around lines 48 to 62, the processResults method is currently a placeholder
without actual polling or webhook logic, making it non-functional. To fix this,
implement the polling logic by listing conversation threads, retrieving messages
for each thread, filtering for COMMENT type messages, and processing those
events accordingly. Alternatively, if HubSpot supports webhooks, implement a
webhook-based event listener to handle new comments in real-time. Choose one
approach and replace the placeholder with the complete functional code.
Closing this PR and replacing with #17607 which has only the HubSpot changes (no accidental Freshdesk changes) and improved implementation with proper polling logic and validation |
WHY
Summary by CodeRabbit
New Features
Chores