Skip to content

Conversation

@sergio-eliot-rodriguez
Copy link
Collaborator

@sergio-eliot-rodriguez sergio-eliot-rodriguez commented Oct 26, 2025

Resolves #18675

Summary by CodeRabbit

  • New Features

    • Create Post: multi-platform posting (LinkedIn, Facebook, TikTok, Instagram, YouTube, Pinterest, Threads, webhooks) with rich per-platform options, threaded posts, media support, and scheduling
    • Create Video: generate videos from templates with runtime template selector and render/draft controls
    • Media & Video Management: Upload Media, Get Video, Delete Video actions with operation summaries
  • Chores

    • Version bumped to 0.1.0
    • Added platform dependency
@vercel
Copy link

vercel bot commented Oct 26, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Preview Comments Updated (UTC)
pipedream-docs-redirect-do-not-edit Ignored Ignored Oct 26, 2025 4:23pm
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 26, 2025

Walkthrough

Adds a Blotato component with five new action modules (create-post, create-video, delete-video, get-video, upload-media), a revamped app file exposing an internal _makeRequest plus API wrapper methods, and a package.json version/dependency bump.

Changes

Cohort / File(s) Summary
Action modules
components/blotato/actions/create-post/create-post.mjs, components/blotato/actions/create-video/create-video.mjs, components/blotato/actions/delete-video/delete-video.mjs, components/blotato/actions/get-video/get-video.mjs, components/blotato/actions/upload-media/upload-media.mjs
Added five new action exports. Each defines metadata, props, and async run handlers. create-post includes dynamic additionalProps() for many platform-specific fields and JSON parsing of additionalPosts; create-video fetches template options and calls createVideoFromTemplate; delete-video/get-video/upload-media invoke corresponding app methods and export summaries.
App implementation
components/blotato/blotato.app.mjs
Replaced prior authKeys placeholder with _makeRequest() helper and added public API wrapper methods: createPost, createVideoFromTemplate, deleteVideo, getVideo, uploadMedia, listTemplates (and removed authKeys()). Requests target https://backend.blotato.com and use stored API key header.
Package metadata
components/blotato/package.json
Bumped version 0.0.1 → 0.1.0 and added dependency "@pipedream/platform": "^3.1.0".

Sequence Diagram(s)

sequenceDiagram autonumber actor User participant Action as Create Post Action participant App as Blotato App participant API as Blotato API User->>Action: run({ accountId, text, mediaUrls, targetType, ... }) Action->>Action: parse additionalPosts & build content/target Action->>App: _makeRequest(path="/v2/posts", method="POST", data) App->>API: POST https://backend.blotato.com/v2/posts (API key header) API-->>App: 200 { id, status, ... } App-->>Action: response Action->>Action: $.export("summary", "Posted with ID: {{id}}") Action-->>User: return response 
Loading
sequenceDiagram autonumber actor User participant Action as Video/Media Action participant App as Blotato App participant API as Blotato API User->>Action: run({ $ }) Action->>App: call (createVideoFromTemplate / deleteVideo / getVideo / uploadMedia / listTemplates) App->>API: HTTP request to /v2/videos/* or /v2/media API-->>App: response App-->>Action: response Action->>Action: $.export("summary", "Operation complete: {{id/status}}") Action-->>User: return response 
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Areas needing focused review:
    • create-post additionalProps() branching and validation (many platform-specific fields).
    • JSON parsing and error handling of additionalPosts.
    • _makeRequest header/auth handling and path construction in blotato.app.mjs.
    • createVideoFromTemplate and listTemplates options() logic (runtime template fetching).
    • Ensure run methods correctly thread the $ context and export summaries.

Suggested labels

action

Suggested reviewers

  • jcortes
  • lcaresia

Poem

🐰 In code I hop, with joy I write,

Posts and videos take to flight,
Uploads hum and templates gleam,
Blotato helps each social dream,
Five actions ready—hop, delight!

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings, 1 inconclusive)
Check name Status Explanation Resolution
Description Check ⚠️ Warning The pull request description is largely incomplete and does not follow the required template. The description template specifies a required "WHY" section that should be completed by the author, but the provided description only contains "Resolves #18675" without any actual explanation of why these changes were made or what problem they solve. The description lacks the context and justification that should accompany code changes. Add a comprehensive description that includes the required "WHY" section explaining the motivation for adding these Blotato components, what use cases they enable, and how they integrate with the Blotato API. Provide sufficient context for reviewers to understand the purpose and scope of the implementation.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title Check ❓ Inconclusive The title "blotato new components" is generic and lacks specificity about which components were added or what they accomplish. While it refers to a real aspect of the changeset (adding new components for blotato), it does not clearly summarize the primary change with sufficient detail. Terms like "new components" without specifying the five actions being implemented (create-post, create-video, delete-video, get-video, upload-media) make the title overly broad and vague for someone scanning the repository history.
✅ Passed checks (2 passed)
Check name Status Explanation
Linked Issues Check ✅ Passed The pull request successfully implements all five required actions specified in linked issue #18675. The create-post action enables posting to social media platforms, create-video allows creating videos/carousels/graphics, delete-video and get-video provide video lifecycle management, and upload-media handles media file uploads. Additionally, the blotato.app.mjs file provides the necessary helper methods (_makeRequest, createPost, createVideoFromTemplate, deleteVideo, getVideo, uploadMedia, listTemplates) that support these actions, and the package.json is updated with appropriate version and dependency changes to support the new functionality.
Out of Scope Changes Check ✅ Passed All changes in the pull request are directly related to the objectives specified in issue #18675. The five new action modules (create-post, create-video, delete-video, get-video, upload-media) are the primary scope requirements. The supporting changes to blotato.app.mjs (adding _makeRequest and related methods) and package.json (version bump and @pipedream/platform dependency) are necessary infrastructure changes directly supporting the implementation of these actions and are appropriately scoped.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@pipedream-component-development
Copy link
Collaborator

Thank you so much for submitting this! We've added it to our backlog to review, and our team has been notified.

@pipedream-component-development
Copy link
Collaborator

Thanks for submitting this PR! When we review PRs, we follow the Pipedream component guidelines. If you're not familiar, here's a quick checklist:

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (4)
components/blotato/actions/delete-video/delete-video.mjs (1)

25-32: Guard for 204 No Content responses

Delete returns 204 No Content per docs, so response may be empty. Consider not relying on a response body and returning a simple { id: videoId, deleted: true } or nothing. (help.blotato.com)

components/blotato/actions/create-video/create-video.mjs (1)

21-27: Harden options(), JSON parsing, and summary

  • Pass $ in options() and default items to avoid crashes.
  • Catch JSON.parse errors to return a clear message.
  • Optional-chain in $summary to avoid undefined access if API shape changes.

Apply this diff:

 async options() { - const { items } = await this.blotato.listTemplates({ - fields: "id,title,description", - }); - return items.map((template) => ({ - label: template.title || template.id, - value: template.id, - })); + const { items = [] } = await this.blotato.listTemplates({ + $: this, + fields: "id,title,description", + }); + return items.map(({ title, id }) => ({ + label: title || id, + value: id, + })); },
- const inputs = JSON.parse(this.inputs); + let inputs; + try { + inputs = JSON.parse(this.inputs); + } catch (err) { + throw new Error(`Invalid JSON in "Inputs": ${err.message}`); + }
- $.export("$summary", `Successfully created video with ID: ${response.item.id}. Status: ${response.item.status}. To view progress, visit https://my.blotato.com/videos/${response.item.id}`); + $.export("$summary", `Successfully created video with ID: ${response?.item?.id}. Status: ${response?.item?.status}. To view progress, visit https://my.blotato.com/videos/${response?.item?.id}`);

This action targets the “new template system” endpoint (/v2/videos/from-templates), which is documented and matches the payload shape used here. Please confirm that your selected templates’ input schema maps to the stringified JSON you pass as inputs. (help.blotato.com)

Also applies to: 56-56, 66-66

components/blotato/blotato.app.mjs (1)

8-22: Optional: add timeout and baseURL for resilience

Consider setting a sensible default timeout (e.g., 30s) and using baseURL with url: path for clarity. Both are optional improvements for reliability.

- return axios($, { - url: `https://backend.blotato.com${path}`, + return axios($, { + baseURL: "https://backend.blotato.com", + url: path, method, headers: { "blotato-api-key": `${this.$auth.api_key}`, "accept": "*/*", ...headers, }, data, + timeout: 30000, ...opts, });
components/blotato/actions/upload-media/upload-media.mjs (1)

21-25: Consider adding URL format validation.

The url prop accepts any string without validation. While the API will reject invalid URLs, adding client-side validation would improve user experience by catching errors earlier.

You could add a validate function to the prop:

 url: { type: "string", label: "URL", description: "The publicly accessible URL of the media to upload. For Google Drive files, use the format: `https://drive.google.com/uc?export=download&id=YOUR_FILE_ID`", + validate: (value) => { + try { + new URL(value); + return true; + } catch { + return "Please provide a valid URL"; + } + }, },
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ff2bfdf and f1e3e31.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (7)
  • components/blotato/actions/create-post/create-post.mjs (1 hunks)
  • components/blotato/actions/create-video/create-video.mjs (1 hunks)
  • components/blotato/actions/delete-video/delete-video.mjs (1 hunks)
  • components/blotato/actions/get-video/get-video.mjs (1 hunks)
  • components/blotato/actions/upload-media/upload-media.mjs (1 hunks)
  • components/blotato/blotato.app.mjs (1 hunks)
  • components/blotato/package.json (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (5)
components/blotato/actions/get-video/get-video.mjs (2)
components/blotato/actions/create-video/create-video.mjs (1)
  • response (58-64)
components/blotato/actions/delete-video/delete-video.mjs (1)
  • response (25-28)
components/blotato/actions/create-video/create-video.mjs (2)
components/blotato/actions/delete-video/delete-video.mjs (1)
  • response (25-28)
components/blotato/actions/get-video/get-video.mjs (1)
  • response (25-28)
components/blotato/actions/create-post/create-post.mjs (1)
components/blotato/actions/upload-media/upload-media.mjs (1)
  • response (30-37)
components/blotato/actions/delete-video/delete-video.mjs (2)
components/blotato/actions/create-post/create-post.mjs (1)
  • response (367-372)
components/blotato/actions/get-video/get-video.mjs (1)
  • response (25-28)
components/blotato/actions/upload-media/upload-media.mjs (1)
components/blotato/actions/create-post/create-post.mjs (1)
  • response (367-372)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: pnpm publish
  • GitHub Check: Lint Code Base
  • GitHub Check: Publish TypeScript components
  • GitHub Check: Verify TypeScript components
🔇 Additional comments (10)
components/blotato/package.json (1)

3-3: Version bump and dependency addition look good

The package version and @pipedream/platform dependency align with the new actions. No issues.

Also applies to: 15-17

components/blotato/actions/delete-video/delete-video.mjs (1)

1-34: API usage and action wiring look correct

Endpoint and header strategy align with Blotato’s Delete Video API. Good use of $summary.

(help.blotato.com)

components/blotato/actions/get-video/get-video.mjs (1)

25-32: LGTM: correct endpoint and read-only semantics

Matches the Find Video endpoint and adheres to readOnly usage.

(help.blotato.com)

components/blotato/blotato.app.mjs (1)

37-52: API paths and headers match docs

  • createVideoFromTemplate → POST /v2/videos/from-templates
  • deleteVideo → DELETE /v2/videos/{id}
  • getVideo → GET /v2/videos/creations/{id}
  • listTemplates → GET /v2/videos/templates

All align with current Blotato docs and header usage (blotato-api-key).

(help.blotato.com)

Also applies to: 53-62, 63-71, 85-97

components/blotato/actions/upload-media/upload-media.mjs (2)

1-13: LGTM!

The import and metadata configuration are properly structured.


39-39: Verify that the API response always includes a url field.

The summary message assumes response.url exists. If the API doesn't return this field, the summary will display "undefined".

Consider adding a defensive check:

-$.export("$summary", `Successfully uploaded media. New URL: ${response.url}`); +$.export("$summary", `Successfully uploaded media${response.url ? `. New URL: ${response.url}` : ""}`);

You can verify the API response structure by checking the Blotato API documentation or running this action with test data.

components/blotato/actions/create-post/create-post.mjs (4)

1-61: LGTM!

The metadata and base props are well-structured with clear descriptions and appropriate constraints. The use of reloadProps: true for dynamic platform-specific fields is a good design choice.


62-267: LGTM!

The dynamic props loading is well-implemented with comprehensive platform-specific configuration. The absence of additional props for Twitter and Bluesky appears intentional, as these platforms work with just the base props.


268-299: LGTM!

The content building logic is solid with proper error handling for JSON parsing. The webhook-to-"other" platform mapping aligns with the API's requirements.


374-374: Verify that the API response always includes a postSubmissionId field.

The summary message assumes response.postSubmissionId exists. If the API doesn't return this field, the summary will display "undefined".

Consider adding a defensive check:

-$.export("$summary", `Successfully submitted post. Post Submission ID: ${response.postSubmissionId}`); +$.export("$summary", `Successfully submitted post${response.postSubmissionId ? `. Post Submission ID: ${response.postSubmissionId}` : ""}`);

You can verify the API response structure by checking the Blotato API documentation or testing the action.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
components/blotato/blotato.app.mjs (1)

23-36: Past review issue remains unaddressed: missing $ parameter and incorrect payload structure.

This method still has the critical issues flagged in the previous review:

  1. Missing $ parameter in the function signature (other methods like createVideoFromTemplate, deleteVideo, getVideo, uploadMedia all accept $)
  2. Incorrect payload structure - the API expects { post, scheduledTime, slot, postDraftId } but this sends { title, content, media, ...args }

The create-post.mjs action (line 366) calls _makeRequest directly with $, but this helper method should also accept and forward $.

Apply the fix from the previous review:

- createPost({ - title, content, media, ...args - } = {}) { - return this._makeRequest({ - method: "POST", - path: "/v2/posts", - data: { - title, - content, - media, - ...args, - }, - }); - }, + createPost({ + $, post, scheduledTime, slot, postDraftId, ...args + } = {}) { + return this._makeRequest({ + $, + method: "POST", + path: "/v2/posts", + data: { + post, + scheduledTime, + slot, + postDraftId, + }, + ...args, + }); + },
🧹 Nitpick comments (1)
components/blotato/actions/upload-media/upload-media.mjs (1)

27-38: Consider defensive access to response.url.

The logic is correct and straightforward. However, Line 35 directly accesses response.url without checking its existence. If the API returns an unexpected format, this could throw an error.

Consider adding a fallback:

- $.export("$summary", `Successfully uploaded media. New URL: ${response.url}`); + $.export("$summary", `Successfully uploaded media${response?.url ? `. New URL: ${response.url}` : ""}`);

Or validate the response before accessing:

 const response = await this.blotato.uploadMedia({ $, url, }); + + if (!response?.url) { + throw new Error("Upload succeeded but no media URL was returned"); + } $.export("$summary", `Successfully uploaded media. New URL: ${response.url}`);
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f1e3e31 and 6ad8c45.

📒 Files selected for processing (2)
  • components/blotato/actions/upload-media/upload-media.mjs (1 hunks)
  • components/blotato/blotato.app.mjs (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
components/blotato/actions/upload-media/upload-media.mjs (4)
components/blotato/actions/create-video/create-video.mjs (1)
  • response (58-64)
components/blotato/actions/get-video/get-video.mjs (1)
  • response (25-28)
components/blotato/actions/delete-video/delete-video.mjs (1)
  • response (25-28)
components/blotato/actions/create-post/create-post.mjs (1)
  • response (367-372)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: pnpm publish
  • GitHub Check: Verify TypeScript components
  • GitHub Check: Publish TypeScript components
  • GitHub Check: Lint Code Base
🔇 Additional comments (7)
components/blotato/actions/upload-media/upload-media.mjs (2)

1-13: LGTM!

The action metadata and structure follow Pipedream conventions correctly. The key naming, version, annotations, and documentation link are all appropriate.


14-26: LGTM!

The props are well-defined with helpful user guidance. The alert about the 200MB limit and the Google Drive URL format example are excellent additions for user experience.

components/blotato/blotato.app.mjs (5)

1-2: LGTM!

The import and _makeRequest helper are well-structured. The default parameter $ = this is a good pattern for allowing callers to optionally pass their own $ context while having a sensible default.

Also applies to: 8-22


37-52: LGTM!

The createVideoFromTemplate method is well-structured with proper $ parameter handling and correct payload structure. The ...args spread is correctly placed to pass through axios options rather than adding to the request body.


53-62: LGTM!

The deleteVideo method is correctly implemented with proper $ parameter handling and appropriate use of videoId in the path. No data payload for DELETE is correct.


63-71: LGTM!

The getVideo method is correctly implemented with proper $ parameter handling and appropriate path construction. The method correctly relies on the default GET from _makeRequest.


72-84: LGTM! Previous review issue resolved.

The uploadMedia method has been correctly updated to address the previous review feedback. It now properly sends { url } in the request body as required by the API specification, and includes the $ parameter. This fix aligns perfectly with the API documentation.

Copy link
Collaborator

@jcortes jcortes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @sergio-eliot-rodriguez lgtm! Ready for QA!

@vunguyenhung vunguyenhung merged commit 53adaf1 into PipedreamHQ:master Oct 28, 2025
9 of 10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

4 participants