Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import app from "../../robopost.app.mjs";

export default {
key: "robopost-create-video-configuration",
name: "Create Video Configuration",
description: "Create a new faceless video series configuration for generating multiple videos with consistent settings. [See the documentation](https://robopost.app/docs/robopost-api/#videogenerationendpoints)",
version: "0.0.1",
annotations: {
destructiveHint: false,
openWorldHint: true,
readOnlyHint: false,
},
type: "action",
props: {
app,
name: {
propDefinition: [
app,
"name",
],
},
contentType: {
propDefinition: [
app,
"contentType",
],
},
style: {
propDefinition: [
app,
"style",
],
},
voice: {
propDefinition: [
app,
"voice",
],
},
lang: {
propDefinition: [
app,
"lang",
],
},
maxDuration: {
propDefinition: [
app,
"maxDuration",
],
},
},
async run({ $ }) {
const response = await this.app.createVideoConfiguration({
$,
data: {
name: this.name,
content_type: this.contentType,
style: this.style,
voice: this.voice,
lang: this.lang,
max_duration: this.maxDuration,
},
});
$.export("$summary", `Successfully created video series configuration with ID: ${response.id}`);
return response;
},
};
31 changes: 31 additions & 0 deletions components/robopost/actions/generate-video/generate-video.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import app from "../../robopost.app.mjs";

export default {
key: "robopost-generate-video",
name: "Generate Video",
description: "Create a new video generation task from a video series. [See the documentation](https://robopost.app/docs/robopost-api/#videogenerationtasks)",
version: "0.0.1",
annotations: {
destructiveHint: false,
openWorldHint: true,
readOnlyHint: false,
},
type: "action",
props: {
app,
configurationId: {
propDefinition: [
app,
"configurationId",
],
},
},
async run({ $ }) {
const response = await this.app.generateVideo({
$,
configurationId: this.configurationId,
});
$.export("$summary", `Successfully started the task to generate the video. Task ID: ${response.task_id}`);
return response;
},
};
31 changes: 31 additions & 0 deletions components/robopost/actions/get-video-status/get-video-status.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import app from "../../robopost.app.mjs";

export default {
key: "robopost-get-video-status",
name: "Get Video Status",
description: "Check the status of a video generation task. [See the documentation](https://robopost.app/docs/robopost-api/#videogenerationtasks)",
version: "0.0.2",
annotations: {
destructiveHint: false,
openWorldHint: true,
readOnlyHint: true,
},
type: "action",
props: {
app,
taskId: {
propDefinition: [
app,
"taskId",
],
},
},
async run({ $ }) {
const response = await this.app.getVideoStatus({
$,
taskId: this.taskId,
});
$.export("$summary", `The task status is: ${response.status}`);
return response;
Comment on lines +23 to +29
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Consider guarding against undefined status in the summary.

If the API response doesn't include a status field, the summary will display "undefined". Consider adding a fallback.

-    $.export("$summary", `The task status is: ${response.status}`);
+    $.export("$summary", `The task status is: ${response.status ?? "unknown"}`);
📝 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.

Suggested change
async run({ $ }) {
const response = await this.app.getVideoStatus({
$,
taskId: this.taskId,
});
$.export("$summary", `The task status is: ${response.status}`);
return response;
async run({ $ }) {
const response = await this.app.getVideoStatus({
$,
taskId: this.taskId,
});
$.export("$summary", `The task status is: ${response.status ?? "unknown"}`);
return response;
🤖 Prompt for AI Agents
In components/robopost/actions/get-video-status/get-video-status.mjs around
lines 23 to 29, the summary exports response.status directly which can become
"undefined" if the API omits status; update the logic to guard for a missing
response or missing status and use a fallback (e.g., 'unknown' or 'N/A') when
status is falsy or undefined, and ensure you handle a null/undefined response
before accessing .status so the summary always exports a defined string.

},
};
50 changes: 50 additions & 0 deletions components/robopost/common/constants.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
export default {
CONTENT_TYPES: [
"RANDOM_AI_STORY",
"SCARY_STORIES",
"BEDTIME_STORIES",
"INTERESTING_HISTORY",
"URBAN_LEGENDS",
"MOTIVATIONAL",
"FUN_FACTS",
"LONG_FORM_JOKES",
"LIFE_PRO_TIPS",
"ELI5",
"DID_YOU_KNOW",
"PHILOSOPHY",
"RECIPES",
"FITNESS",
"BEAUTY",
"GROWTH_ADVICE",
"PRODUCT_MARKETING",
"CUSTOM",
"BLOG_ARTICLE",
],
STYLE_OPTIONS: [
"DEFAULT",
"REALISM",
"IMPRESSIONISM",
"SURREALISM",
"ABSTRACT",
"ART_NOUVEAU",
"CUBISM",
"POP_ART",
"FUTURISM",
"FANTASY_CONCEPT_ART",
"MINIMALISM",
"WATERCOLOR",
"GOTHIC_MEDIEVAL_ART",
"ANIME",
"COMIC",
],
VOICE_OPTIONS: [
"ALICE",
"BILL",
"SARAH",
"BRIAN",
"LAURA",
"ARIA",
"CALLUM",
"CHARLIE",
],
};
7 changes: 5 additions & 2 deletions components/robopost/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@pipedream/robopost",
"version": "0.0.1",
"version": "0.1.0",
"description": "Pipedream Robopost Components",
"main": "robopost.app.mjs",
"keywords": [
Expand All @@ -11,5 +11,8 @@
"author": "Pipedream <support@pipedream.com> (https://pipedream.com/)",
"publishConfig": {
"access": "public"
},
"dependencies": {
"@pipedream/platform": "^3.1.1"
}
}
}
129 changes: 125 additions & 4 deletions components/robopost/robopost.app.mjs
Original file line number Diff line number Diff line change
@@ -1,11 +1,132 @@
import { axios } from "@pipedream/platform";
import constants from "./common/constants.mjs";

export default {
type: "app",
app: "robopost",
propDefinitions: {},
propDefinitions: {
name: {
type: "string",
label: "Name",
description: "Name of the video series configuration",
},
contentType: {
type: "string",
label: "Content Type",
description: "The type of the content of the video",
options: constants.CONTENT_TYPES,
optional: true,
},
style: {
type: "string",
label: "Style",
description: "The style of the video",
options: constants.STYLE_OPTIONS,
optional: true,
},
voice: {
type: "string",
label: "Voice",
description: "The voice used for the video",
options: constants.VOICE_OPTIONS,
optional: true,
},
lang: {
type: "string",
label: "Language Code",
description: "Language of the video, i.e.: `en`",
optional: true,
},
maxDuration: {
type: "integer",
label: "Max Duration",
description: "Maximum video duration in seconds (5-600)",
optional: true,
},
configurationId: {
type: "string",
label: "Configuration ID",
description: "ID of the configuration for the video generation",
async options() {
const response = await this.getVideoSeries();
return response.map(({
name, id,
}) => ({
label: name,
value: id,
}));
},
Comment on lines +52 to +60
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Add defensive handling for API responses in options().

If getVideoSeries() returns an error or unexpected structure, .map() will throw. Consider wrapping with a try-catch or validating the response type.

     async options() {
-      const response = await this.getVideoSeries();
-      return response.map(({
-        name, id,
-      }) => ({
-        label: name,
-        value: id,
-      }));
+      const response = await this.getVideoSeries();
+      return (response ?? []).map(({
+        name, id,
+      }) => ({
+        label: name,
+        value: id,
+      }));
     },
🤖 Prompt for AI Agents
In components/robopost/robopost.app.mjs around lines 50 to 58, the options()
method assumes getVideoSeries() returns an array and calls .map() directly,
which will throw if the response is an error, null, or not an array. Update
options() to validate and normalize the API response before mapping: await
getVideoSeries() inside a try-catch, verify Array.isArray(response) (or coerce
to [] if falsy), and handle errors by logging/returning an empty array or a safe
default; ensure the map only runs on a confirmed array and that thrown errors
are caught and propagated or converted to a user-friendly error.

},
taskId: {
type: "string",
label: "Task ID",
description: "ID of the task to be checked",
async options() {
const response = await this.getTaskStatus();
return response.map(({
created_at, task_id,
}) => ({
label: created_at,
value: task_id,
}));
},
Comment on lines +66 to +74
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Same defensive handling needed for taskId options().

Apply similar null-coalescing to prevent runtime errors if getTaskStatus() returns an unexpected value.

     async options() {
-      const response = await this.getTaskStatus();
-      return response.map(({
+      const response = await this.getTaskStatus();
+      return (response ?? []).map(({
         created_at, task_id,
       }) => ({
         label: created_at,
         value: task_id,
       }));
     },
📝 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.

Suggested change
async options() {
const response = await this.getTaskStatus();
return response.map(({
created_at, task_id,
}) => ({
label: created_at,
value: task_id,
}));
},
async options() {
const response = await this.getTaskStatus();
return (response ?? []).map(({
created_at, task_id,
}) => ({
label: created_at,
value: task_id,
}));
},
🤖 Prompt for AI Agents
In components/robopost/robopost.app.mjs around lines 64 to 72, options() assumes
getTaskStatus() returns an array and directly calls map, which can throw if the
response is null/undefined or contains null entries; change the code to default
response to an empty array (e.g., response ?? []) before mapping and defensively
handle each item (guard created_at and task_id) so options always returns a safe
array of {label,value} without throwing.

},
},
methods: {
// this.$auth contains connected account data
authKeys() {
console.log(Object.keys(this.$auth));
_baseUrl() {
return "https://public-api.robopost.app/v1";
},
async _makeRequest(opts = {}) {
const {
$ = this,
path,
params,
...otherOpts
} = opts;
return axios($, {
...otherOpts,
url: this._baseUrl() + path,
params: {
apikey: `${this.$auth.api_key}`,
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Remove unnecessary string interpolation.

The template literal is redundant since this.$auth.api_key is already a string.

Apply this diff:

       params: {
-        apikey: `${this.$auth.api_key}`,
+        apikey: this.$auth.api_key,
         ...params,
       },
📝 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.

Suggested change
apikey: `${this.$auth.api_key}`,
params: {
apikey: this.$auth.api_key,
...params,
},
🤖 Prompt for AI Agents
In components/robopost/robopost.app.mjs around line 92, the apikey value uses an
unnecessary template literal (`\`${this.$auth.api_key}\``); replace it with the
direct string property access `this.$auth.api_key` (remove the backticks and
${...}) so the code assigns the API key directly without interpolation.

...params,
},
});
},
async createVideoConfiguration(args = {}) {
return this._makeRequest({
path: "/video-series",
method: "post",
...args,
});
},
async generateVideo({
configurationId, ...args
}) {
return this._makeRequest({
path: `/video-tasks/${configurationId}/generate`,
method: "post",
...args,
});
},
Comment on lines +104 to +112
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Consider validating required parameters.

The method destructures configurationId but doesn't validate it's provided. If undefined, this constructs an invalid URL (/video-tasks/undefined/generate), resulting in unclear API errors.

Adding validation would improve error messages:

 async generateVideo({
   configurationId, ...args
 }) {
+  if (!configurationId) {
+    throw new Error("configurationId is required");
+  }
   return this._makeRequest({
     path: `/video-tasks/${configurationId}/generate`,
     method: "post",
     ...args,
   });
 },
📝 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.

Suggested change
async generateVideo({
configurationId, ...args
}) {
return this._makeRequest({
path: `/video-tasks/${configurationId}/generate`,
method: "post",
...args,
});
},
async generateVideo({
configurationId, ...args
}) {
if (!configurationId) {
throw new Error("configurationId is required");
}
return this._makeRequest({
path: `/video-tasks/${configurationId}/generate`,
method: "post",
...args,
});
},
🤖 Prompt for AI Agents
In components/robopost/robopost.app.mjs around lines 104 to 112, the
generateVideo method destructures configurationId but does not validate it,
which can produce a bad URL like /video-tasks/undefined/generate; add an early
validation that ensures configurationId is present (and optionally of expected
type, e.g., string or number), and if not, throw a clear Error (or return a
rejected Promise) with a descriptive message like "generateVideo:
configurationId is required"; keep the rest of the method unchanged so valid
calls proceed to this._makeRequest.

async getVideoStatus({
taskId, ...args
}) {
return this._makeRequest({
path: `/video-tasks/${taskId}`,
...args,
});
},
Comment on lines +113 to +120
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Consider validating required parameters.

The method destructures taskId but doesn't validate it's provided. If undefined, this constructs an invalid URL (/video-tasks/undefined), resulting in unclear API errors.

Adding validation would improve error messages:

 async getVideoStatus({
   taskId, ...args
 }) {
+  if (!taskId) {
+    throw new Error("taskId is required");
+  }
   return this._makeRequest({
     path: `/video-tasks/${taskId}`,
     ...args,
   });
 },
📝 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.

Suggested change
async getVideoStatus({
taskId, ...args
}) {
return this._makeRequest({
path: `/video-tasks/${taskId}`,
...args,
});
},
async getVideoStatus({
taskId, ...args
}) {
if (!taskId) {
throw new Error("taskId is required");
}
return this._makeRequest({
path: `/video-tasks/${taskId}`,
...args,
});
},
🤖 Prompt for AI Agents
In components/robopost/robopost.app.mjs around lines 113 to 120, the
getVideoStatus method destructures taskId but does not validate it, which can
produce requests to /video-tasks/undefined; add an early validation that ensures
taskId is present and a non-empty string (or valid id type) and if not, throw a
clear Error/TypeError (or return a rejected Promise) with a descriptive message
like "getVideoStatus requires a valid taskId" before calling _makeRequest; this
prevents constructing invalid URLs and gives immediate, actionable errors to
callers.

async getVideoSeries(args = {}) {
return this._makeRequest({
path: "/video-series",
...args,
});
},
async getTaskStatus(args = {}) {
return this._makeRequest({
path: "/video-tasks",
...args,
});
},
},
};
Loading