Add Activepieces integration for workflow automation

- Add Activepieces fork with SmoothSchedule custom piece
- Create integrations app with Activepieces service layer
- Add embed token endpoint for iframe integration
- Create Automations page with embedded workflow builder
- Add sidebar visibility fix for embed mode
- Add list inactive customers endpoint to Public API
- Include SmoothSchedule triggers: event created/updated/cancelled
- Include SmoothSchedule actions: create/update/cancel events, list resources/services/customers

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
poduck
2025-12-18 22:59:37 -05:00
parent 9848268d34
commit 3aa7199503
16292 changed files with 1284892 additions and 4708 deletions

View File

@@ -0,0 +1,33 @@
{
"extends": [
"../../../../.eslintrc.base.json"
],
"ignorePatterns": [
"!**/*"
],
"overrides": [
{
"files": [
"*.ts",
"*.tsx",
"*.js",
"*.jsx"
],
"rules": {}
},
{
"files": [
"*.ts",
"*.tsx"
],
"rules": {}
},
{
"files": [
"*.js",
"*.jsx"
],
"rules": {}
}
]
}

View File

@@ -0,0 +1,7 @@
# pieces-vadoo-ai
This library was generated with [Nx](https://nx.dev).
## Building
Run `nx build pieces-vadoo-ai` to build the library.

View File

@@ -0,0 +1,10 @@
{
"name": "@activepieces/piece-vadoo-ai",
"version": "0.0.2",
"type": "commonjs",
"main": "./src/index.js",
"types": "./src/index.d.ts",
"dependencies": {
"tslib": "^2.3.0"
}
}

View File

@@ -0,0 +1,65 @@
{
"name": "pieces-vadoo-ai",
"$schema": "../../../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "packages/pieces/community/vadoo-ai/src",
"projectType": "library",
"release": {
"version": {
"manifestRootsToUpdate": [
"dist/{projectRoot}"
],
"currentVersionResolver": "git-tag",
"fallbackCurrentVersionResolver": "disk"
}
},
"tags": [],
"targets": {
"build": {
"executor": "@nx/js:tsc",
"outputs": [
"{options.outputPath}"
],
"options": {
"outputPath": "dist/packages/pieces/community/vadoo-ai",
"tsConfig": "packages/pieces/community/vadoo-ai/tsconfig.lib.json",
"packageJson": "packages/pieces/community/vadoo-ai/package.json",
"main": "packages/pieces/community/vadoo-ai/src/index.ts",
"assets": [
"packages/pieces/community/vadoo-ai/*.md",
{
"input": "packages/pieces/community/vadoo-ai/src/i18n",
"output": "./src/i18n",
"glob": "**/!(i18n.json)"
}
],
"buildableProjectDepsInPackageJsonType": "dependencies",
"updateBuildableProjectDepsInPackageJson": true
},
"dependsOn": [
"^build",
"prebuild"
]
},
"nx-release-publish": {
"options": {
"packageRoot": "dist/{projectRoot}"
}
},
"lint": {
"executor": "@nx/eslint:lint",
"outputs": [
"{options.outputFile}"
]
},
"prebuild": {
"executor": "nx:run-commands",
"options": {
"cwd": "packages/pieces/community/vadoo-ai",
"command": "bun install --no-save --silent"
},
"dependsOn": [
"^build"
]
}
}
}

View File

@@ -0,0 +1,83 @@
{
"You can create API key from [Profile Settings](https://ai.vadoo.tv/profile).": "Sie können API-Schlüssel in [Profileinstellungen](https://ai.vadoo.tv/profile).",
"Generate Video": "Video generieren",
"Generate Podcast": "Podcast generieren",
"Generate AI Image": "Generate AI Image",
"Generate AI Captions": "KI-Untertitel generieren",
"Create an AI-generated video from parameters": "Erstelle ein AI-generiertes Video aus Parametern",
"Generates a podcast-style video.": "Erzeugt ein Video im Podcast-Stil.",
"Generates AI generated image based on prompt for a character.": "Erzeugt ein AI generiertes Bild basierend auf der Prompt für ein Zeichen.",
"Generates AI captions for a video.": "Erzeugt KI-Bildunterschriften für ein Video.",
"Topic": "Thema",
"Custom Prompt": "Benutzerdefinierte Aufforderung",
"Voice": "Stimme",
"Theme": "Thema",
"Style": "Stil",
"Language": "Sprache",
"Duration": "Dauer",
"Aspect Ratio": "Seitenverhältnis",
"Custom Instructions": "Eigene Anweisungen",
"Use AI to Modify Script": "KI zum Ändern des Skripts verwenden",
"Include Voiceover": "Voiceover einbeziehen",
"Caption Size": "Beschriftungsgröße",
"Caption Position": "Position des Titels",
"Blog URL": "Blog-URL",
"Background Music": "Hintergrundmusik",
"Background Music Volume": "Hintergrundmusik Lautstärke",
"Content Source": "Inhaltsquelle",
"Website/PDF URL": "Website/PDF-URL",
"Custom Content": "Eigener Inhalt",
"Host Name": "Hostname",
"Host Voice": "Host-Sprache",
"Guest Name": "Gastname",
"Guest Voice": "Gastsprache",
"Tone": "Ton",
"Character": "Charakter",
"Image Prompt": "Image Prompt",
"Video URL": "Video-URL",
"To create content for AI Video": "Inhalte für KI-Video erstellen",
"Prompt to generate a custom script (required when topic is 'Custom')": "Aufforderung zur Generierung eines benutzerdefinierten Skripts (erforderlich, wenn Thema \"Benutzerdefiniert\" ist)",
"The voice for AI Video": "Die Stimme für KI-Video",
"To display captions with style": "Um Bildunterschriften mit Stil anzuzeigen",
"AI image style": "AI-Bildstil",
"To generate video in language you want": "Um Videos in der gewünschten Sprache zu generieren",
"Video Duration": "Video-Dauer",
"Video aspect ratio": "Video Seitenverhältnis",
"Custom instructions to guide AI (character descriptions, image visuals, background styles, etc.)": "Benutzerdefinierte Anleitung für KI (Zeichenbeschreibungen, Grafiken, Hintergrundstile, usw.)",
"Modify script with AI": "Skript mit KI ändern",
"Include AI voiceover in the video": "KI-Sprachübertragung in das Video einbeziehen",
"Size of captions (take reference values from dashboard)": "Größe der Beschriftungen (Referenzwerte vom Dashboard nehmen)",
"Position of captions (take reference values from dashboard)": "Position der Beschriftungen (Referenzwerte vom Dashboard nehmen)",
"URL input for Blog to Video": "URL-Eingabe für Blog zu Video",
"Background music to use along with the video": "Hintergrundmusik zusammen mit dem Video",
"Background music volume (1-100)": "Hintergrundmusik (1-100)",
"Choose the source of content for the podcast": "Quelle des Inhalts für den Podcast auswählen",
"URL of the website or PDF to create a podcast from": "URL der Webseite oder PDF, um einen Podcast zu erstellen von",
"Custom content for the podcast": "Benutzerdefinierter Inhalt für den Podcast",
"The host name for AI Podcast": "Der Hostname für den KI-Podcast",
"The host voice for AI Podcast": "Die Host-Stimme für KI-Podcast",
"The guest name for AI Podcast": "Der Gastname für den KI-Podcast",
"The guest voice for AI Podcast": "Die Gaststimme für den KI-Podcast",
"Podcast Duration in minutes": "Podcast-Dauer in Minuten",
"Tone of the Podcast": "Ton des Podcasts",
"Select the character to generate an image for": "Wählen Sie das Zeichen, um ein Bild zu generieren für",
"The aspect ratio for the generated image": "Das Seitenverhältnis für das generierte Bild",
"Prompt to generate a character image": "Aufforderung zur Erstellung eines Zeichenbildes",
"URL of the input video to add captions to": "URL des Eingabevideos, um Bildunterschriften hinzuzufügen",
"To generate captions in language you want": "Um Bildunterschriften in der gewünschten Sprache zu generieren",
"30-60 seconds": "30-60 Sekunden",
"60-90 seconds": "60-90 Sekunden",
"90-120 seconds": "90-120 Sekunden",
"5 minutes": "5 Minuten",
"10 minutes": "10 Minuten",
"9:16 (Portrait)": "9:16 (Hochformat)",
"1:1 (Square)": "1:1 (Quare)",
"16:9 (Landscape)": "16:9 (Landscape)",
"Yes": "Ja",
"No": "Nein",
"Custom Text": "Eigener Text",
"1-2 minutes": "1-2 Minuten",
"3-5 minutes": "3-5 Minuten",
"3:4 (Portrait)": "3:4 (Hochformat)",
"4:3 (Landscape)": "4:3 (Landscape)"
}

View File

@@ -0,0 +1,83 @@
{
"You can create API key from [Profile Settings](https://ai.vadoo.tv/profile).": "Puedes crear la clave API desde [Configuración del perfil](https://ai.vadoo.tv/profile).",
"Generate Video": "Generar vídeo",
"Generate Podcast": "Generar Podcast",
"Generate AI Image": "Generate AI Image",
"Generate AI Captions": "Generar subtítulos de IA",
"Create an AI-generated video from parameters": "Crear un vídeo generado por AIs a partir de parámetros",
"Generates a podcast-style video.": "Genera un video al estilo podcast.",
"Generates AI generated image based on prompt for a character.": "Genera una imagen generada por IA basada en el indicador de un personaje.",
"Generates AI captions for a video.": "Genera subtítulos IA para un vídeo.",
"Topic": "Tema",
"Custom Prompt": "Prompt personalizado",
"Voice": "Voz",
"Theme": "Tema",
"Style": "Estilo",
"Language": "Idioma",
"Duration": "Duración",
"Aspect Ratio": "Relación de aspecto",
"Custom Instructions": "Instrucciones personalizadas",
"Use AI to Modify Script": "Usar IA para modificar el script",
"Include Voiceover": "Incluye Voceover",
"Caption Size": "Tamaño del subtítulo",
"Caption Position": "Posición del título",
"Blog URL": "URL del blog",
"Background Music": "Música de fondo",
"Background Music Volume": "Volumen de música en segundo plano",
"Content Source": "Fuente de contenido",
"Website/PDF URL": "Sitio web/URL PDF",
"Custom Content": "Contenido personalizado",
"Host Name": "Nombre de host",
"Host Voice": "Voz del host",
"Guest Name": "Nombre de huésped",
"Guest Voice": "Voz Invitada",
"Tone": "Tono",
"Character": "Carácter",
"Image Prompt": "Image Prompt",
"Video URL": "URL del vídeo",
"To create content for AI Video": "Crear contenido para vídeo AI",
"Prompt to generate a custom script (required when topic is 'Custom')": "Prompt para generar un script personalizado (obligatorio cuando el tema es 'Personalizado')",
"The voice for AI Video": "La voz para vídeo AI",
"To display captions with style": "Mostrar subtítulos con estilo",
"AI image style": "Estilo de imagen IA",
"To generate video in language you want": "Para generar vídeo en el idioma que quieres",
"Video Duration": "Duración del vídeo",
"Video aspect ratio": "Relación de aspecto de vídeo",
"Custom instructions to guide AI (character descriptions, image visuals, background styles, etc.)": "Instrucciones personalizadas para guiar IA (descripciones de caracteres, imágenes visuales, estilos de fondo, etc.)",
"Modify script with AI": "Modificar script con IA",
"Include AI voiceover in the video": "Incluye voz de IA en el video",
"Size of captions (take reference values from dashboard)": "Tamaño de los subtítulos (tomar los valores de referencia del panel)",
"Position of captions (take reference values from dashboard)": "Posición de los títulos (tomar los valores de referencia del panel)",
"URL input for Blog to Video": "Entrada URL para Blog a Video",
"Background music to use along with the video": "Fondo de música para usar junto con el vídeo",
"Background music volume (1-100)": "Volumen de música de fondo (1-100)",
"Choose the source of content for the podcast": "Elija la fuente de contenido para el podcast",
"URL of the website or PDF to create a podcast from": "URL del sitio web o PDF desde el cual crear un podcast",
"Custom content for the podcast": "Contenido personalizado para el podcast",
"The host name for AI Podcast": "El nombre de host para AI Podcast",
"The host voice for AI Podcast": "La voz del anfitrión para Podcast de IA",
"The guest name for AI Podcast": "El nombre de invitado para Podcast de IA",
"The guest voice for AI Podcast": "La voz de invitado para Podcast de IA",
"Podcast Duration in minutes": "Duración del Podcast en minutos",
"Tone of the Podcast": "Tono del Podcast",
"Select the character to generate an image for": "Seleccione el personaje para generar una imagen",
"The aspect ratio for the generated image": "La relación de aspecto para la imagen generada",
"Prompt to generate a character image": "Prompt para generar una imagen de personaje",
"URL of the input video to add captions to": "URL del video de entrada al que agregar subtítulos",
"To generate captions in language you want": "Para generar subtítulos en el idioma que desea",
"30-60 seconds": "30-60 segundos",
"60-90 seconds": "60-90 segundos",
"90-120 seconds": "90-120 segundos",
"5 minutes": "5 minutos",
"10 minutes": "10 minutos",
"9:16 (Portrait)": "9:16 (Retrato)",
"1:1 (Square)": "1:1 (Cuadrado)",
"16:9 (Landscape)": "16:9 (Landscape)",
"Yes": "Sí",
"No": "Nu",
"Custom Text": "Texto personalizado",
"1-2 minutes": "1-2 minutos",
"3-5 minutes": "3-5 minutos",
"3:4 (Portrait)": "3:4 (Retrato)",
"4:3 (Landscape)": "4:3 (Landscape)"
}

View File

@@ -0,0 +1,83 @@
{
"You can create API key from [Profile Settings](https://ai.vadoo.tv/profile).": "Vous pouvez créer une clé API à partir de [Paramètres du profil](https://ai.vadoo.tv/profile).",
"Generate Video": "Générer une vidéo",
"Generate Podcast": "Générer un podcast",
"Generate AI Image": "Generate AI Image",
"Generate AI Captions": "Générer des légendes AI",
"Create an AI-generated video from parameters": "Créer une vidéo générée par l'IA à partir des paramètres",
"Generates a podcast-style video.": "Génère une vidéo de style podcast.",
"Generates AI generated image based on prompt for a character.": "Génère une image générée par l'IA en se basant sur l'invite pour un caractère.",
"Generates AI captions for a video.": "Génère des légendes AI pour une vidéo.",
"Topic": "Sujet",
"Custom Prompt": "Invitation personnalisée",
"Voice": "Voix",
"Theme": "Thème",
"Style": "Style",
"Language": "Langue",
"Duration": "Durée",
"Aspect Ratio": "Ratio d'aspect",
"Custom Instructions": "Instructions personnalisées",
"Use AI to Modify Script": "Utiliser l'IA pour modifier le script",
"Include Voiceover": "Inclure Voiceover",
"Caption Size": "Taille de la légende",
"Caption Position": "Position de la légende",
"Blog URL": "URL du blog",
"Background Music": "Musique d'arrière-plan",
"Background Music Volume": "Volume de la musique de fond",
"Content Source": "Source de contenu",
"Website/PDF URL": "URL du site Web/PDF",
"Custom Content": "Contenu personnalisé",
"Host Name": "Nom de l'hôte",
"Host Voice": "Voix de l'Hôte",
"Guest Name": "Nom de l'invité",
"Guest Voice": "Voix des invités",
"Tone": "Tonalité",
"Character": "Personnage",
"Image Prompt": "Image Prompt",
"Video URL": "URL de la vidéo",
"To create content for AI Video": "Créer du contenu pour la vidéo AI",
"Prompt to generate a custom script (required when topic is 'Custom')": "Demander à générer un script personnalisé (requis lorsque le sujet est « Personnalisé »)",
"The voice for AI Video": "La voix pour la vidéo IA",
"To display captions with style": "Afficher les légendes avec style",
"AI image style": "Style de l'image IA",
"To generate video in language you want": "Pour générer une vidéo dans la langue que vous voulez",
"Video Duration": "Durée de la vidéo",
"Video aspect ratio": "Ratio d'aspect vidéo",
"Custom instructions to guide AI (character descriptions, image visuals, background styles, etc.)": "Instructions personnalisées pour guider l'IA (descriptions de caractères, images visuelles, styles d'arrière-plan, etc.)",
"Modify script with AI": "Modifier le script avec l'IA",
"Include AI voiceover in the video": "Inclure la voix off de l'IA dans la vidéo",
"Size of captions (take reference values from dashboard)": "Taille des légendes (prendre les valeurs de référence du tableau de bord)",
"Position of captions (take reference values from dashboard)": "Position des légendes (prendre les valeurs de référence du tableau de bord)",
"URL input for Blog to Video": "Saisie d'URL pour le blog à la vidéo",
"Background music to use along with the video": "Musique de fond à utiliser avec la vidéo",
"Background music volume (1-100)": "Volume de la musique de fond (1-100)",
"Choose the source of content for the podcast": "Choisir la source du contenu du podcast",
"URL of the website or PDF to create a podcast from": "URL du site Web ou du PDF pour créer un podcast à partir de",
"Custom content for the podcast": "Contenu personnalisé pour le podcast",
"The host name for AI Podcast": "Le nom d'hôte de l'IA Podcast",
"The host voice for AI Podcast": "La voix hôte pour le Podcast IA",
"The guest name for AI Podcast": "Le nom de l'invité pour AI Podcast",
"The guest voice for AI Podcast": "La voix des invités pour le Podcast AI",
"Podcast Duration in minutes": "Durée de Podcast en minutes",
"Tone of the Podcast": "Tonalité du Podcast",
"Select the character to generate an image for": "Sélectionnez le caractère pour générer une image pour",
"The aspect ratio for the generated image": "Ratio d'aspect pour l'image générée",
"Prompt to generate a character image": "Demander à générer une image de caractère",
"URL of the input video to add captions to": "URL de la vidéo d'entrée pour ajouter des légendes à",
"To generate captions in language you want": "Pour générer des légendes dans la langue que vous voulez",
"30-60 seconds": "30-60 secondes",
"60-90 seconds": "60-90 secondes",
"90-120 seconds": "90-120 secondes",
"5 minutes": "5 minutes",
"10 minutes": "10 minutes",
"9:16 (Portrait)": "9:16 (Portrait)",
"1:1 (Square)": "1:1 (Square)",
"16:9 (Landscape)": "16:9 (Landscape)",
"Yes": "Oui",
"No": "Non",
"Custom Text": "Texte personnalisé",
"1-2 minutes": "1-2 minutes",
"3-5 minutes": "3-5 minutes",
"3:4 (Portrait)": "3:4 (Portrait)",
"4:3 (Landscape)": "4:3 (Landscape)"
}

View File

@@ -0,0 +1,83 @@
{
"You can create API key from [Profile Settings](https://ai.vadoo.tv/profile).": "[プロファイル設定](https://ai.vadoo.tv/profile)からAPIキーを作成できます。",
"Generate Video": "ビデオを生成",
"Generate Podcast": "ポッドキャストを生成",
"Generate AI Image": "Generate AI Image",
"Generate AI Captions": "AIキャプションを生成",
"Create an AI-generated video from parameters": "パラメータからAIで生成されたビデオを作成する",
"Generates a podcast-style video.": "Podcast スタイルのビデオを生成します。",
"Generates AI generated image based on prompt for a character.": "文字のプロンプトに基づいてAI生成された画像を生成します。",
"Generates AI captions for a video.": "動画の AI キャプションを生成します。",
"Topic": "トピック",
"Custom Prompt": "カスタムプロンプト表示",
"Voice": "音声",
"Theme": "テーマ",
"Style": "スタイル",
"Language": "言語",
"Duration": "期間",
"Aspect Ratio": "アスペクト比",
"Custom Instructions": "カスタム説明",
"Use AI to Modify Script": "スクリプトを変更するためにAIを使用する",
"Include Voiceover": "ボイスオーバーを含める",
"Caption Size": "キャプションのサイズ",
"Caption Position": "キャプションの位置",
"Blog URL": "ブログURL",
"Background Music": "バックグラウンド音楽",
"Background Music Volume": "バックグラウンドミュージックボリューム",
"Content Source": "コンテンツ ソース",
"Website/PDF URL": "ウェブサイト/PDF URL",
"Custom Content": "カスタムコンテンツ",
"Host Name": "ホスト名",
"Host Voice": "Host Voice",
"Guest Name": "ゲスト名",
"Guest Voice": "ゲストの声",
"Tone": "Tone",
"Character": "文字",
"Image Prompt": "Image Prompt",
"Video URL": "動画の URL",
"To create content for AI Video": "AIビデオ用のコンテンツを作成するには",
"Prompt to generate a custom script (required when topic is 'Custom')": "カスタム スクリプトを生成するためのプロンプト(トピックが 'カスタム' の場合に必要)",
"The voice for AI Video": "AI ビデオの声",
"To display captions with style": "スタイル付きのキャプションを表示するには",
"AI image style": "AI 画像のスタイル",
"To generate video in language you want": "目的の言語でビデオを生成するには",
"Video Duration": "ビデオの持続時間",
"Video aspect ratio": "ビデオアスペクト比",
"Custom instructions to guide AI (character descriptions, image visuals, background styles, etc.)": "AI(文字記述、画像、背景スタイルなど)をガイドするためのカスタム手順",
"Modify script with AI": "AIでスクリプトを変更する",
"Include AI voiceover in the video": "動画にAIのボイスオーバーを含める",
"Size of captions (take reference values from dashboard)": "キャプションのサイズ (ダッシュボードから参照値を取得)",
"Position of captions (take reference values from dashboard)": "キャプションの位置 (ダッシュボードから参照値を取得)",
"URL input for Blog to Video": "動画へのブログのURL入力",
"Background music to use along with the video": "ビデオと一緒に使用するバックグラウンド音楽",
"Background music volume (1-100)": "バックグラウンド音楽の音量 (1-100)",
"Choose the source of content for the podcast": "ポッドキャストのコンテンツのソースを選択します",
"URL of the website or PDF to create a podcast from": "ポッドキャストを作成するウェブサイトまたはPDFのURL",
"Custom content for the podcast": "ポッドキャストのカスタムコンテンツ",
"The host name for AI Podcast": "AI ポッドキャストのホスト名",
"The host voice for AI Podcast": "AIポッドキャストのホストの声",
"The guest name for AI Podcast": "AI ポッドキャストのゲスト名",
"The guest voice for AI Podcast": "AIポッドキャストのゲストの声",
"Podcast Duration in minutes": "ポッドキャスト時間 (分)",
"Tone of the Podcast": "ポッドキャストの音",
"Select the character to generate an image for": "画像を生成する文字を選択してください",
"The aspect ratio for the generated image": "生成された画像のアスペクト比",
"Prompt to generate a character image": "キャラクター画像の生成を促します",
"URL of the input video to add captions to": "字幕を追加するための入力ビデオのURL",
"To generate captions in language you want": "希望の言語でキャプションを生成するには",
"30-60 seconds": "30-60 秒",
"60-90 seconds": "60-90 秒",
"90-120 seconds": "90-120 秒",
"5 minutes": "5分",
"10 minutes": "10分",
"9:16 (Portrait)": "9:16",
"1:1 (Square)": "1:1 (スクエア)",
"16:9 (Landscape)": "16:9 (Landscape)",
"Yes": "はい",
"No": "いいえ",
"Custom Text": "カスタムテキスト",
"1-2 minutes": "1-2 分",
"3-5 minutes": "3-5分",
"3:4 (Portrait)": "3:4 (Portrait)",
"4:3 (Landscape)": "4:3 (Landscape)"
}

View File

@@ -0,0 +1,83 @@
{
"You can create API key from [Profile Settings](https://ai.vadoo.tv/profile).": "Je kunt een API-sleutel maken via [Profielinstellingen](https://ai.vadoo.tv/profile).",
"Generate Video": "Video genereren",
"Generate Podcast": "Podcast genereren",
"Generate AI Image": "Generate AI Image",
"Generate AI Captions": "Genereer AI bijschriften",
"Create an AI-generated video from parameters": "Maak een AI-gegenereerde video van parameters",
"Generates a podcast-style video.": "Genereert een video in podcast-stijl.",
"Generates AI generated image based on prompt for a character.": "Genereert AI gegenereerde afbeelding gebaseerd op de vraag naar een personage.",
"Generates AI captions for a video.": "Genereert AI bijschriften voor een video.",
"Topic": "Onderwerp",
"Custom Prompt": "Aangepaste vraag",
"Voice": "Stem",
"Theme": "Thema",
"Style": "CSS",
"Language": "Taal",
"Duration": "Tijdsduur",
"Aspect Ratio": "Verhouding beeldverhouding",
"Custom Instructions": "Aangepaste instructies",
"Use AI to Modify Script": "Gebruik AI om Script te wijzigen",
"Include Voiceover": "Voiceover opnemen",
"Caption Size": "Formaat bijschrift",
"Caption Position": "Positie bijschrift",
"Blog URL": "Blog URL",
"Background Music": "Muziek achtergrond",
"Background Music Volume": "Muziek achtergrond achtergrond",
"Content Source": "Content bron",
"Website/PDF URL": "Website/PDF URL",
"Custom Content": "Aangepaste inhoud",
"Host Name": "Host Naam",
"Host Voice": "Spraak Host",
"Guest Name": "Naam gast",
"Guest Voice": "Gast spraak",
"Tone": "Toon",
"Character": "Karakter",
"Image Prompt": "Image Prompt",
"Video URL": "Video URL",
"To create content for AI Video": "Om inhoud te maken voor AI Video",
"Prompt to generate a custom script (required when topic is 'Custom')": "Vraag om een aangepast script te genereren (vereist wanneer het topic 'Aangepast')",
"The voice for AI Video": "De stem voor de AI Video",
"To display captions with style": "Bijschriften met stijl weergeven",
"AI image style": "AI afbeeldingsstijl",
"To generate video in language you want": "Video genereren in de taal die u wilt",
"Video Duration": "Video Duur",
"Video aspect ratio": "Video beeldverhouding",
"Custom instructions to guide AI (character descriptions, image visuals, background styles, etc.)": "Aangepaste instructies voor handleiding AI (tekenbeschrijvingen, afbeeldingen, achtergrondstijlen, etc.)",
"Modify script with AI": "Script wijzigen met AI",
"Include AI voiceover in the video": "Voeg AI voiceover toe in de video",
"Size of captions (take reference values from dashboard)": "Grootte van bijschriften (neem referentie waarden van dashboard)",
"Position of captions (take reference values from dashboard)": "Positie van bijschriften (neem referentiewaarden van dashboard)",
"URL input for Blog to Video": "URL-invoer voor Blog naar Video",
"Background music to use along with the video": "Achtergrondmuziek om samen met de video te gebruiken",
"Background music volume (1-100)": "Volume achtergrondmuziek (1-100)",
"Choose the source of content for the podcast": "Kies de bron van inhoud voor podcast",
"URL of the website or PDF to create a podcast from": "URL van de website of PDF om een podcast aan te maken van",
"Custom content for the podcast": "Aangepaste inhoud voor podcast",
"The host name for AI Podcast": "De hostnaam voor AI Podcast",
"The host voice for AI Podcast": "De gastheer voor AI Podcast",
"The guest name for AI Podcast": "De gast naam voor AI Podcast",
"The guest voice for AI Podcast": "De gast voor AI Podcast",
"Podcast Duration in minutes": "Podcast duur in minuten",
"Tone of the Podcast": "Tone van de Podcast",
"Select the character to generate an image for": "Selecteer het teken om een afbeelding te genereren voor",
"The aspect ratio for the generated image": "De beeldverhouding voor de gegenereerde afbeelding",
"Prompt to generate a character image": "Vragen om een karakterafbeelding te genereren",
"URL of the input video to add captions to": "URL van de input video om bijschriften aan toe te voegen",
"To generate captions in language you want": "Om bijschriften te genereren in de taal die je wilt",
"30-60 seconds": "30-60 seconden",
"60-90 seconds": "60-90 seconden",
"90-120 seconds": "90-120 seconden",
"5 minutes": "5 minuten",
"10 minutes": "10 minuten",
"9:16 (Portrait)": "9:16 (Portrait)",
"1:1 (Square)": "1:1 (Zeil)",
"16:9 (Landscape)": "16:9 (Landscape)",
"Yes": "ja",
"No": "Neen",
"Custom Text": "Aangepaste tekst",
"1-2 minutes": "1-2 minuten",
"3-5 minutes": "3-5 minuten",
"3:4 (Portrait)": "3:4 (Portrait)",
"4:3 (Landscape)": "4:3 (Landscape)"
}

View File

@@ -0,0 +1,83 @@
{
"You can create API key from [Profile Settings](https://ai.vadoo.tv/profile).": "Você pode criar uma chave de API de [Configurações do Perfil](https://ai.vadoo.tv/profile).",
"Generate Video": "Gerar Vídeo",
"Generate Podcast": "Gerar Podcast",
"Generate AI Image": "Generate AI Image",
"Generate AI Captions": "Gerar legendas AI",
"Create an AI-generated video from parameters": "Criar um vídeo gerado pela IA a partir de parâmetros",
"Generates a podcast-style video.": "Gera um vídeo no estilo podcast.",
"Generates AI generated image based on prompt for a character.": "Gera uma imagem gerada pela AI com base no prompt para um personagem.",
"Generates AI captions for a video.": "Gera legendas IA para um vídeo.",
"Topic": "Tópico",
"Custom Prompt": "Solicitação personalizada",
"Voice": "Voz",
"Theme": "Tema",
"Style": "Estilo",
"Language": "IDIOMA",
"Duration": "Duração",
"Aspect Ratio": "Proporção da proporção",
"Custom Instructions": "Instruções personalizadas",
"Use AI to Modify Script": "Use AI para modificar o script",
"Include Voiceover": "Incluir Voiceover",
"Caption Size": "Tamanho da legenda",
"Caption Position": "Posição da legenda",
"Blog URL": "URL do Blog",
"Background Music": "Música de fundo",
"Background Music Volume": "Volume de música de fundo",
"Content Source": "Fonte do Conteúdo",
"Website/PDF URL": "Website/URL PDF",
"Custom Content": "Conteúdo personalizado",
"Host Name": "Nome do Servidor",
"Host Voice": "Hospedar Voz",
"Guest Name": "Nome do Visitante",
"Guest Voice": "Voz do convidado",
"Tone": "Tom",
"Character": "Personagem",
"Image Prompt": "Image Prompt",
"Video URL": "URL do vídeo",
"To create content for AI Video": "Para criar conteúdo para Vídeo IA",
"Prompt to generate a custom script (required when topic is 'Custom')": "Solicitar a geração de um script personalizado (obrigatório quando o tópico é 'Personalizado')",
"The voice for AI Video": "A voz para Vídeo de IA",
"To display captions with style": "Para exibir legendas com estilo",
"AI image style": "Estilo de imagem IA",
"To generate video in language you want": "Para gerar vídeo no idioma que quiser",
"Video Duration": "Duração do Vídeo",
"Video aspect ratio": "Proporção do vídeo",
"Custom instructions to guide AI (character descriptions, image visuals, background styles, etc.)": "Instruções personalizadas para guiar AI (descrições de caracteres, imagens visuais, estilos de fundo, etc.)",
"Modify script with AI": "Modificar script com IA",
"Include AI voiceover in the video": "Incluir narração de IA no vídeo",
"Size of captions (take reference values from dashboard)": "Tamanho das legendas (pegar valores de referência do painel)",
"Position of captions (take reference values from dashboard)": "Posição das legendas (tomar valores de referência a partir do painel)",
"URL input for Blog to Video": "Entrada de URL para o Blog para Vídeo",
"Background music to use along with the video": "Música de fundo a ser usada junto com o vídeo",
"Background music volume (1-100)": "Volume da música de fundo (1-100)",
"Choose the source of content for the podcast": "Escolha a fonte do conteúdo para o podcast",
"URL of the website or PDF to create a podcast from": "URL do site ou PDF para criar um podcast a partir de",
"Custom content for the podcast": "Conteúdo personalizado para o podcast",
"The host name for AI Podcast": "O nome do host para o Podcast IA",
"The host voice for AI Podcast": "A voz hospedeira para Podcast de IA",
"The guest name for AI Podcast": "O nome do convidado do Podcast IA",
"The guest voice for AI Podcast": "A voz convidado do Podcast IA",
"Podcast Duration in minutes": "Duração do Podcast em minutos",
"Tone of the Podcast": "Tom do Podcast",
"Select the character to generate an image for": "Selecione o personagem para gerar uma imagem para",
"The aspect ratio for the generated image": "A proporção de aspecto para a imagem gerada",
"Prompt to generate a character image": "Solicitar a geração de uma imagem de caractere",
"URL of the input video to add captions to": "URL da entrada de vídeo para adicionar legendas",
"To generate captions in language you want": "Para gerar legendas no idioma que quiser",
"30-60 seconds": "30-60 segundos",
"60-90 seconds": "60-90 segundos",
"90-120 seconds": "90-120 segundos",
"5 minutes": "5 minutos",
"10 minutes": "10 minutos",
"9:16 (Portrait)": "9:16 (Retrato)",
"1:1 (Square)": "1:1 (Quadrado)",
"16:9 (Landscape)": "16:9 (Landscape)",
"Yes": "sim",
"No": "Não",
"Custom Text": "Texto Personalizado",
"1-2 minutes": "1-2 minutos",
"3-5 minutes": "3-5 minutos",
"3:4 (Portrait)": "3:4 (Retrato)",
"4:3 (Landscape)": "4:3 (Landscape)"
}

View File

@@ -0,0 +1,83 @@
{
"You can create API key from [Profile Settings](https://ai.vadoo.tv/profile).": "You can create API key from [Profile Settings](https://ai.vadoo.tv/profile).",
"Generate Video": "Generate Video",
"Generate Podcast": "Generate Podcast",
"Generate AI Image": "Generate AI Image",
"Generate AI Captions": "Generate AI Captions",
"Create an AI-generated video from parameters": "Create an AI-generated video from parameters",
"Generates a podcast-style video.": "Generates a podcast-style video.",
"Generates AI generated image based on prompt for a character.": "Generates AI generated image based on prompt for a character.",
"Generates AI captions for a video.": "Generates AI captions for a video.",
"Topic": "Topic",
"Custom Prompt": "Custom Prompt",
"Voice": "Voice",
"Theme": "Theme",
"Style": "Style",
"Language": "Language",
"Duration": "Duration",
"Aspect Ratio": "Aspect Ratio",
"Custom Instructions": "Custom Instructions",
"Use AI to Modify Script": "Use AI to Modify Script",
"Include Voiceover": "Include Voiceover",
"Caption Size": "Caption Size",
"Caption Position": "Caption Position",
"Blog URL": "Blog URL",
"Background Music": "Background Music",
"Background Music Volume": "Background Music Volume",
"Content Source": "Content Source",
"Website/PDF URL": "Website/PDF URL",
"Custom Content": "Custom Content",
"Host Name": "Host Name",
"Host Voice": "Host Voice",
"Guest Name": "Guest Name",
"Guest Voice": "Guest Voice",
"Tone": "Tone",
"Character": "Character",
"Image Prompt": "Image Prompt",
"Video URL": "Video URL",
"To create content for AI Video": "To create content for AI Video",
"Prompt to generate a custom script (required when topic is 'Custom')": "Prompt to generate a custom script (required when topic is 'Custom')",
"The voice for AI Video": "The voice for AI Video",
"To display captions with style": "To display captions with style",
"AI image style": "AI image style",
"To generate video in language you want": "To generate video in language you want",
"Video Duration": "Video Duration",
"Video aspect ratio": "Video aspect ratio",
"Custom instructions to guide AI (character descriptions, image visuals, background styles, etc.)": "Custom instructions to guide AI (character descriptions, image visuals, background styles, etc.)",
"Modify script with AI": "Modify script with AI",
"Include AI voiceover in the video": "Include AI voiceover in the video",
"Size of captions (take reference values from dashboard)": "Size of captions (take reference values from dashboard)",
"Position of captions (take reference values from dashboard)": "Position of captions (take reference values from dashboard)",
"URL input for Blog to Video": "URL input for Blog to Video",
"Background music to use along with the video": "Background music to use along with the video",
"Background music volume (1-100)": "Background music volume (1-100)",
"Choose the source of content for the podcast": "Choose the source of content for the podcast",
"URL of the website or PDF to create a podcast from": "URL of the website or PDF to create a podcast from",
"Custom content for the podcast": "Custom content for the podcast",
"The host name for AI Podcast": "The host name for AI Podcast",
"The host voice for AI Podcast": "The host voice for AI Podcast",
"The guest name for AI Podcast": "The guest name for AI Podcast",
"The guest voice for AI Podcast": "The guest voice for AI Podcast",
"Podcast Duration in minutes": "Podcast Duration in minutes",
"Tone of the Podcast": "Tone of the Podcast",
"Select the character to generate an image for": "Select the character to generate an image for",
"The aspect ratio for the generated image": "The aspect ratio for the generated image",
"Prompt to generate a character image": "Prompt to generate a character image",
"URL of the input video to add captions to": "URL of the input video to add captions to",
"To generate captions in language you want": "To generate captions in language you want",
"30-60 seconds": "30-60 seconds",
"60-90 seconds": "60-90 seconds",
"90-120 seconds": "90-120 seconds",
"5 minutes": "5 minutes",
"10 minutes": "10 minutes",
"9:16 (Portrait)": "9:16 (Portrait)",
"1:1 (Square)": "1:1 (Square)",
"16:9 (Landscape)": "16:9 (Landscape)",
"Yes": "Yes",
"No": "No",
"Custom Text": "Custom Text",
"1-2 minutes": "1-2 minutes",
"3-5 minutes": "3-5 minutes",
"3:4 (Portrait)": "3:4 (Portrait)",
"4:3 (Landscape)": "4:3 (Landscape)"
}

View File

@@ -0,0 +1,83 @@
{
"You can create API key from [Profile Settings](https://ai.vadoo.tv/profile).": "You can create API key from [Profile Settings](https://ai.vadoo.tv/profile).",
"Generate Video": "Generate Video",
"Generate Podcast": "Generate Podcast",
"Generate AI Image": "Generate AI Image",
"Generate AI Captions": "Generate AI Captions",
"Create an AI-generated video from parameters": "Create an AI-generated video from parameters",
"Generates a podcast-style video.": "Generates a podcast-style video.",
"Generates AI generated image based on prompt for a character.": "Generates AI generated image based on prompt for a character.",
"Generates AI captions for a video.": "Generates AI captions for a video.",
"Topic": "Topic",
"Custom Prompt": "Custom Prompt",
"Voice": "Voice",
"Theme": "Theme",
"Style": "Style",
"Language": "Language",
"Duration": "期限",
"Aspect Ratio": "Aspect Ratio",
"Custom Instructions": "Custom Instructions",
"Use AI to Modify Script": "Use AI to Modify Script",
"Include Voiceover": "Include Voiceover",
"Caption Size": "Caption Size",
"Caption Position": "Caption Position",
"Blog URL": "博客网址",
"Background Music": "Background Music",
"Background Music Volume": "Background Music Volume",
"Content Source": "Content Source",
"Website/PDF URL": "Website/PDF URL",
"Custom Content": "Custom Content",
"Host Name": "Host Name",
"Host Voice": "Host Voice",
"Guest Name": "Guest Name",
"Guest Voice": "Guest Voice",
"Tone": "Tone",
"Character": "Character",
"Image Prompt": "Image Prompt",
"Video URL": "Video URL",
"To create content for AI Video": "To create content for AI Video",
"Prompt to generate a custom script (required when topic is 'Custom')": "Prompt to generate a custom script (required when topic is 'Custom')",
"The voice for AI Video": "The voice for AI Video",
"To display captions with style": "To display captions with style",
"AI image style": "AI image style",
"To generate video in language you want": "To generate video in language you want",
"Video Duration": "Video Duration",
"Video aspect ratio": "Video aspect ratio",
"Custom instructions to guide AI (character descriptions, image visuals, background styles, etc.)": "Custom instructions to guide AI (character descriptions, image visuals, background styles, etc.)",
"Modify script with AI": "Modify script with AI",
"Include AI voiceover in the video": "Include AI voiceover in the video",
"Size of captions (take reference values from dashboard)": "Size of captions (take reference values from dashboard)",
"Position of captions (take reference values from dashboard)": "Position of captions (take reference values from dashboard)",
"URL input for Blog to Video": "URL input for Blog to Video",
"Background music to use along with the video": "Background music to use along with the video",
"Background music volume (1-100)": "Background music volume (1-100)",
"Choose the source of content for the podcast": "Choose the source of content for the podcast",
"URL of the website or PDF to create a podcast from": "URL of the website or PDF to create a podcast from",
"Custom content for the podcast": "Custom content for the podcast",
"The host name for AI Podcast": "The host name for AI Podcast",
"The host voice for AI Podcast": "The host voice for AI Podcast",
"The guest name for AI Podcast": "The guest name for AI Podcast",
"The guest voice for AI Podcast": "The guest voice for AI Podcast",
"Podcast Duration in minutes": "Podcast Duration in minutes",
"Tone of the Podcast": "Tone of the Podcast",
"Select the character to generate an image for": "Select the character to generate an image for",
"The aspect ratio for the generated image": "The aspect ratio for the generated image",
"Prompt to generate a character image": "Prompt to generate a character image",
"URL of the input video to add captions to": "URL of the input video to add captions to",
"To generate captions in language you want": "To generate captions in language you want",
"30-60 seconds": "30-60 seconds",
"60-90 seconds": "60-90 seconds",
"90-120 seconds": "90-120 seconds",
"5 minutes": "5 minutes",
"10 minutes": "10 minutes",
"9:16 (Portrait)": "9:16 (Portrait)",
"1:1 (Square)": "1:1 (Square)",
"16:9 (Landscape)": "16:9 (Landscape)",
"Yes": "Yes",
"No": "No",
"Custom Text": "Custom Text",
"1-2 minutes": "1-2 minutes",
"3-5 minutes": "3-5 minutes",
"3:4 (Portrait)": "3:4 (Portrait)",
"4:3 (Landscape)": "4:3 (Landscape)"
}

View File

@@ -0,0 +1,28 @@
import { createPiece, PieceAuth } from '@activepieces/pieces-framework';
import { generateVideo } from './lib/actions/generate-video';
import { generatePodcast } from './lib/actions/generate-podcast';
import { generateAiImage } from './lib/actions/generate-ai-image';
import { generateAiCaptions } from './lib/actions/generate-ai-captions';
import { PieceCategory } from '@activepieces/shared';
export const vadooAiAuth = PieceAuth.SecretText({
displayName: 'API Key',
required: true,
description: `You can create API key from [Profile Settings](https://ai.vadoo.tv/profile).`,
});
export const vadooAi = createPiece({
displayName: 'Vadoo AI',
auth: vadooAiAuth,
minimumSupportedRelease: '0.36.1',
logoUrl: 'https://cdn.activepieces.com/pieces/vadoo-ai.png',
categories: [PieceCategory.ARTIFICIAL_INTELLIGENCE],
authors: ['fortunamide'],
actions: [
generateVideo,
generatePodcast,
generateAiImage,
generateAiCaptions,
],
triggers: [],
});

View File

@@ -0,0 +1,163 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { vadooAiAuth } from '../../index';
import {
httpClient,
HttpMethod,
propsValidation,
} from '@activepieces/pieces-common';
import { generateAiCaptionsSchema } from '../schemas';
import { isEmpty } from '@activepieces/shared';
export const generateAiCaptions = createAction({
auth: vadooAiAuth,
name: 'generate_ai_captions',
displayName: 'Generate AI Captions',
description: 'Generates AI captions for a video.',
props: {
url: Property.ShortText({
displayName: 'Video URL',
description: 'URL of the input video to add captions to',
required: true,
}),
theme: Property.Dropdown({
auth: vadooAiAuth,
displayName: 'Theme',
description: 'To display captions with style',
required: false,
refreshers: [],
options: async ({ auth }) => {
if (!auth) {
return {
disabled: true,
options: [],
placeholder: 'Please authenticate first',
};
}
try {
const response = await httpClient.sendRequest({
method: HttpMethod.GET,
url: 'https://viralapi.vadoo.tv/api/get_themes',
headers: {
'X-API-KEY': auth.secret_text,
},
});
const themes = response.body as string[];
return {
disabled: false,
options: themes.map((theme) => ({
label: theme,
value: theme,
})),
};
} catch (error) {
return {
disabled: true,
options: [],
placeholder: 'Failed to load themes.',
};
}
},
}),
language: Property.Dropdown({
auth: vadooAiAuth,
displayName: 'Language',
description: 'To generate captions in language you want',
required: false,
refreshers: [],
options: async ({ auth }) => {
if (!auth) {
return {
disabled: true,
options: [],
placeholder: 'Please authenticate first',
};
}
try {
const response = await httpClient.sendRequest({
method: HttpMethod.GET,
url: 'https://viralapi.vadoo.tv/api/get_languages',
headers: {
'X-API-KEY': auth.secret_text,
},
});
const languages = response.body as string[];
return {
disabled: false,
options: languages.map((language) => ({
label: language,
value: language,
})),
};
} catch (error) {
return {
disabled: true,
options: [],
placeholder: 'Failed to load languages',
};
}
},
}),
},
async run(context) {
// Validate props with Zod schema
await propsValidation.validateZod(
context.propsValue,
generateAiCaptionsSchema
);
const { url, theme, language } = context.propsValue;
// Build request body, only including non-empty values
const requestBody: Record<string, any> = {
url: url,
};
if (theme) requestBody['theme'] = theme;
if (language) requestBody['language'] = language;
const response = await httpClient.sendRequest<{ vid: number }>({
method: HttpMethod.POST,
url: 'https://viralapi.vadoo.tv/api/add_captions',
headers: {
'X-API-KEY': context.auth.secret_text,
'Content-Type': 'application/json',
},
body: requestBody,
});
if (isEmpty(response.body) || isEmpty(response.body.vid)) {
throw new Error('Failed to generate captions.');
}
const videoId = response.body.vid;
let status = 'pending';
const timeoutAt = Date.now() + 5 * 60 * 1000;
do {
await new Promise((resolve) => setTimeout(resolve, 5000));
const pollRes = await httpClient.sendRequest<{
url: string;
status: string;
}>({
method: HttpMethod.GET,
url: 'https://viralapi.vadoo.tv/api/get_video_url',
headers: {
'X-API-KEY': context.auth.secret_text,
'Content-Type': 'application/json',
},
queryParams: {
id: videoId.toString(),
},
});
status = pollRes.body.status;
if (status === 'complete') return pollRes.body;
} while (status !== 'complete' && Date.now() < timeoutAt);
throw new Error('Generate Caption timed out or failed.');
},
});

View File

@@ -0,0 +1,141 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { vadooAiAuth } from '../../index';
import {
httpClient,
HttpMethod,
propsValidation,
} from '@activepieces/pieces-common';
import { generateAiImageSchema } from '../schemas';
import { isEmpty } from '@activepieces/shared';
export const generateAiImage = createAction({
auth: vadooAiAuth,
name: 'generate_ai_image',
displayName: 'Generate AI Image',
description: 'Generates AI generated image based on prompt for a character.',
props: {
id: Property.Dropdown({
auth: vadooAiAuth,
displayName: 'Character',
description: 'Select the character to generate an image for',
required: true,
refreshers: [],
options: async ({ auth }) => {
if (!auth) {
return {
disabled: true,
options: [],
placeholder: 'Please authenticate first',
};
}
try {
const response = await httpClient.sendRequest({
method: HttpMethod.GET,
url: 'https://viralapi.vadoo.tv/api/get_all_characters',
headers: {
'X-API-KEY': auth.secret_text,
},
});
const characters = response.body as Array<{
id: number;
name: string;
url: string;
createdAt: string;
}>;
return {
disabled: false,
options: characters.map((character) => ({
label: `${character.name} (ID: ${character.id})`,
value: character.id.toString(),
})),
};
} catch (error) {
return {
disabled: true,
options: [],
placeholder: 'Failed to load characters',
};
}
},
}),
ratio: Property.StaticDropdown({
displayName: 'Aspect Ratio',
description: 'The aspect ratio for the generated image',
required: true,
options: {
options: [
{ label: '9:16 (Portrait)', value: '9:16' },
{ label: '1:1 (Square)', value: '1:1' },
{ label: '16:9 (Landscape)', value: '16:9' },
{ label: '3:4 (Portrait)', value: '3:4' },
{ label: '4:3 (Landscape)', value: '4:3' },
],
},
}),
prompt: Property.LongText({
displayName: 'Image Prompt',
description: 'Prompt to generate a character image',
required: true,
}),
},
async run(context) {
// Validate props with Zod schema
await propsValidation.validateZod(
context.propsValue,
generateAiImageSchema
);
const { id, ratio, prompt } = context.propsValue;
// Build request body
const requestBody: Record<string, any> = {
id: parseInt(id as string, 10),
ratio: ratio,
prompt: prompt,
};
const response = await httpClient.sendRequest<{ id: number }>({
method: HttpMethod.POST,
url: 'https://viralapi.vadoo.tv/api/generate_character_image',
headers: {
'X-API-KEY': context.auth.secret_text,
'Content-Type': 'application/json',
},
body: requestBody,
});
if (isEmpty(response.body) || isEmpty(response.body.id)) {
throw new Error('Failed to generate image.');
}
const imageId = response.body.id;
let status = 'pending';
const timeoutAt = Date.now() + 5 * 60 * 1000;
do {
await new Promise((resolve) => setTimeout(resolve, 5000));
const pollRes = await httpClient.sendRequest<{
url: string;
status: string;
}>({
method: HttpMethod.GET,
url: 'https://viralapi.vadoo.tv/api/get_character_image',
headers: {
'X-API-KEY': context.auth.secret_text,
'Content-Type': 'application/json',
},
queryParams: {
id: imageId.toString(),
},
});
status = pollRes.body.status;
if (status === 'complete') return pollRes.body;
} while (status !== 'complete' && Date.now() < timeoutAt);
throw new Error('Generate Image timed out or failed.');
},
});

View File

@@ -0,0 +1,366 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { vadooAiAuth } from '../../index';
import {
httpClient,
HttpMethod,
propsValidation,
} from '@activepieces/pieces-common';
import { generatePodcastSchema } from '../schemas';
import { isEmpty } from '@activepieces/shared';
export const generatePodcast = createAction({
auth: vadooAiAuth,
name: 'generate_podcast',
displayName: 'Generate Podcast',
description: 'Generates a podcast-style video.',
props: {
content_source: Property.StaticDropdown({
displayName: 'Content Source',
description: 'Choose the source of content for the podcast',
required: true,
options: {
options: [
{ label: 'Website/PDF URL', value: 'url' },
{ label: 'Custom Text', value: 'text' },
],
},
}),
url: Property.ShortText({
displayName: 'Website/PDF URL',
description: 'URL of the website or PDF to create a podcast from',
required: false,
}),
text: Property.LongText({
displayName: 'Custom Content',
description: 'Custom content for the podcast',
required: false,
}),
name1: Property.ShortText({
displayName: 'Host Name',
description: 'The host name for AI Podcast',
required: true,
}),
voice1: Property.Dropdown({
auth: vadooAiAuth,
displayName: 'Host Voice',
description: 'The host voice for AI Podcast',
required: false,
refreshers: [],
options: async ({ auth }) => {
if (!auth) {
return {
disabled: true,
options: [],
placeholder: 'Please authenticate first',
};
}
try {
const response = await httpClient.sendRequest({
method: HttpMethod.GET,
url: 'https://viralapi.vadoo.tv/api/get_voices',
headers: {
'X-API-KEY': auth.secret_text,
},
timeout: 10000, // 10 second timeout
});
if (response.body && Array.isArray(response.body)) {
const voices = response.body as string[];
return {
disabled: false,
options: voices.map((voice) => ({
label: voice,
value: voice,
})),
};
} else {
// Fallback to default voices if API response is unexpected
return {
disabled: false,
options: [
{ label: 'Charlie', value: 'Charlie' },
{ label: 'George', value: 'George' },
{ label: 'Callum', value: 'Callum' },
{ label: 'Sarah', value: 'Sarah' },
{ label: 'Laura', value: 'Laura' },
{ label: 'Charlotte', value: 'Charlotte' },
],
};
}
} catch (error) {
// Fallback to default voices on error
return {
disabled: false,
options: [
{ label: 'Charlie', value: 'Charlie' },
{ label: 'George', value: 'George' },
{ label: 'Callum', value: 'Callum' },
{ label: 'Sarah', value: 'Sarah' },
{ label: 'Laura', value: 'Laura' },
{ label: 'Charlotte', value: 'Charlotte' },
],
};
}
},
}),
name2: Property.ShortText({
displayName: 'Guest Name',
description: 'The guest name for AI Podcast',
required: true,
}),
voice2: Property.Dropdown({
auth: vadooAiAuth,
displayName: 'Guest Voice',
description: 'The guest voice for AI Podcast',
required: false,
refreshers: [],
options: async ({ auth }) => {
if (!auth) {
return {
disabled: true,
options: [],
placeholder: 'Please authenticate first',
};
}
try {
const response = await httpClient.sendRequest({
method: HttpMethod.GET,
url: 'https://viralapi.vadoo.tv/api/get_voices',
headers: {
'X-API-KEY': auth.secret_text,
},
timeout: 10000, // 10 second timeout
});
if (response.body && Array.isArray(response.body)) {
const voices = response.body as string[];
return {
disabled: false,
options: voices.map((voice) => ({
label: voice,
value: voice,
})),
};
} else {
// Fallback to default voices if API response is unexpected
return {
disabled: false,
options: [
{ label: 'Charlie', value: 'Charlie' },
{ label: 'George', value: 'George' },
{ label: 'Callum', value: 'Callum' },
{ label: 'Sarah', value: 'Sarah' },
{ label: 'Laura', value: 'Laura' },
{ label: 'Charlotte', value: 'Charlotte' },
],
};
}
} catch (error) {
// Fallback to default voices on error
return {
disabled: false,
options: [
{ label: 'Charlie', value: 'Charlie' },
{ label: 'George', value: 'George' },
{ label: 'Callum', value: 'Callum' },
{ label: 'Sarah', value: 'Sarah' },
{ label: 'Laura', value: 'Laura' },
{ label: 'Charlotte', value: 'Charlotte' },
],
};
}
},
}),
theme: Property.Dropdown({
auth: vadooAiAuth,
displayName: 'Theme',
description: 'To display captions with style',
required: false,
refreshers: [],
options: async ({ auth }) => {
if (!auth) {
return {
disabled: true,
options: [],
placeholder: 'Please authenticate first',
};
}
try {
const response = await httpClient.sendRequest({
method: HttpMethod.GET,
url: 'https://viralapi.vadoo.tv/api/get_themes',
headers: {
'X-API-KEY': auth.secret_text,
},
});
const themes = response.body as string[];
return {
disabled: false,
options: themes.map((theme) => ({
label: theme,
value: theme,
})),
};
} catch (error) {
return {
disabled: true,
options: [],
placeholder: 'Failed to load themes',
};
}
},
}),
language: Property.Dropdown({
auth: vadooAiAuth,
displayName: 'Language',
description: 'To generate video in language you want',
required: false,
refreshers: [],
options: async ({ auth }) => {
if (!auth) {
return {
disabled: true,
options: [],
placeholder: 'Please authenticate first',
};
}
try {
const response = await httpClient.sendRequest({
method: HttpMethod.GET,
url: 'https://viralapi.vadoo.tv/api/get_languages',
headers: {
'X-API-KEY': auth.secret_text,
},
});
const languages = response.body as string[];
return {
disabled: false,
options: languages.map((language) => ({
label: language,
value: language,
})),
};
} catch (error) {
return {
disabled: true,
options: [],
placeholder: 'Failed to load languages',
};
}
},
}),
duration: Property.StaticDropdown({
displayName: 'Duration',
description: 'Podcast Duration in minutes',
required: false,
defaultValue: '1-2',
options: {
options: [
{ label: '1-2 minutes', value: '1-2' },
{ label: '3-5 minutes', value: '3-5' },
],
},
}),
tone: Property.ShortText({
displayName: 'Tone',
description: 'Tone of the Podcast',
required: false,
defaultValue: 'Friendly',
}),
},
async run(context) {
// Validate props with Zod schema
await propsValidation.validateZod(
context.propsValue,
generatePodcastSchema
);
const {
content_source,
url,
text,
name1,
voice1,
name2,
voice2,
theme,
language,
duration,
tone,
} = context.propsValue;
// Validate content source requirements
if (content_source === 'url' && !url) {
throw new Error(
"URL is required when content source is 'Website/PDF URL'"
);
}
if (content_source === 'text' && !text) {
throw new Error(
"Custom text is required when content source is 'Custom Text'"
);
}
// Build request body, only including non-empty values
const requestBody: Record<string, any> = {
name1: name1,
name2: name2,
};
if (url && content_source === 'url') requestBody['url'] = url;
if (text && content_source === 'text') requestBody['text'] = text;
if (voice1) requestBody['voice1'] = voice1;
if (voice2) requestBody['voice2'] = voice2;
if (theme) requestBody['theme'] = theme;
if (language) requestBody['language'] = language;
if (duration) requestBody['duration'] = duration;
if (tone) requestBody['tone'] = tone;
const response = await httpClient.sendRequest<{ vid: number }>({
method: HttpMethod.POST,
url: 'https://viralapi.vadoo.tv/api/generate_podcast',
headers: {
'X-API-KEY': context.auth.secret_text,
'Content-Type': 'application/json',
},
body: requestBody,
});
if (isEmpty(response.body) || isEmpty(response.body.vid)) {
throw new Error('Failed to generate podcast.');
}
const videoId = response.body.vid;
let status = 'pending';
const timeoutAt = Date.now() + 5 * 60 * 1000;
do {
await new Promise((resolve) => setTimeout(resolve, 5000));
const pollRes = await httpClient.sendRequest<{
url: string;
status: string;
}>({
method: HttpMethod.GET,
url: 'https://viralapi.vadoo.tv/api/get_video_url',
headers: {
'X-API-KEY': context.auth.secret_text,
'Content-Type': 'application/json',
},
queryParams: {
id: videoId.toString(),
},
});
status = pollRes.body.status;
if (status === 'complete') return pollRes.body;
} while (status !== 'complete' && Date.now() < timeoutAt);
throw new Error('Generate Podcast timed out or failed.');
},
});

View File

@@ -0,0 +1,435 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { vadooAiAuth } from '../../index';
import {
httpClient,
HttpMethod,
propsValidation,
} from '@activepieces/pieces-common';
import { generateVideoSchema } from '../schemas';
import { isEmpty } from '@activepieces/shared';
export const generateVideo = createAction({
auth: vadooAiAuth,
name: 'generate_video',
displayName: 'Generate Video',
description: 'Create an AI-generated video from parameters',
props: {
topic: Property.Dropdown({
auth: vadooAiAuth,
displayName: 'Topic',
description: 'To create content for AI Video',
required: false,
refreshers: [],
options: async ({ auth }) => {
if (!auth) {
return {
disabled: true,
options: [],
placeholder: 'Please authenticate first',
};
}
try {
const response = await httpClient.sendRequest({
method: HttpMethod.GET,
url: 'https://viralapi.vadoo.tv/api/get_topics',
headers: {
'X-API-KEY': auth.secret_text,
},
});
const topics = response.body as string[];
const options = topics.map((topic) => ({
label: topic,
value: topic,
}));
// Add Custom option
options.push({ label: 'Custom', value: 'Custom' });
return {
disabled: false,
options: options,
};
} catch (error) {
return {
disabled: true,
options: [],
placeholder: 'Failed to load topics',
};
}
},
}),
prompt: Property.LongText({
displayName: 'Custom Prompt',
description:
"Prompt to generate a custom script (required when topic is 'Custom')",
required: false,
}),
voice: Property.Dropdown({
auth: vadooAiAuth,
displayName: 'Voice',
description: 'The voice for AI Video',
required: false,
refreshers: [],
options: async ({ auth }) => {
if (!auth) {
return {
disabled: true,
options: [],
placeholder: 'Please authenticate first',
};
}
try {
const response = await httpClient.sendRequest({
method: HttpMethod.GET,
url: 'https://viralapi.vadoo.tv/api/get_voices',
headers: {
'X-API-KEY': auth.secret_text,
},
timeout: 10000, // 10 second timeout
});
if (response.body && Array.isArray(response.body)) {
const voices = response.body as string[];
return {
disabled: false,
options: voices.map((voice) => ({
label: voice,
value: voice,
})),
};
} else {
// Fallback to default voices if API response is unexpected
return {
disabled: false,
options: [
{ label: 'Charlie', value: 'Charlie' },
{ label: 'George', value: 'George' },
{ label: 'Callum', value: 'Callum' },
{ label: 'Sarah', value: 'Sarah' },
{ label: 'Laura', value: 'Laura' },
{ label: 'Charlotte', value: 'Charlotte' },
],
};
}
} catch (error) {
// Fallback to default voices on error
return {
disabled: false,
options: [
{ label: 'Charlie', value: 'Charlie' },
{ label: 'George', value: 'George' },
{ label: 'Callum', value: 'Callum' },
{ label: 'Sarah', value: 'Sarah' },
{ label: 'Laura', value: 'Laura' },
{ label: 'Charlotte', value: 'Charlotte' },
],
};
}
},
}),
theme: Property.Dropdown({
auth: vadooAiAuth,
displayName: 'Theme',
description: 'To display captions with style',
required: false,
refreshers: [],
options: async ({ auth }) => {
if (!auth) {
return {
disabled: true,
options: [],
placeholder: 'Please authenticate first',
};
}
try {
const response = await httpClient.sendRequest({
method: HttpMethod.GET,
url: 'https://viralapi.vadoo.tv/api/get_themes',
headers: {
'X-API-KEY': auth.secret_text,
},
});
const themes = response.body as string[];
return {
disabled: false,
options: themes.map((theme) => ({
label: theme,
value: theme,
})),
};
} catch (error) {
return {
disabled: true,
options: [],
placeholder: 'Failed to load themes',
};
}
},
}),
style: Property.ShortText({
displayName: 'Style',
description: 'AI image style',
required: false,
defaultValue: 'None',
}),
language: Property.Dropdown({
auth: vadooAiAuth,
displayName: 'Language',
description: 'To generate video in language you want',
required: false,
refreshers: [],
options: async ({ auth }) => {
if (!auth) {
return {
disabled: true,
options: [],
placeholder: 'Please authenticate first',
};
}
try {
const response = await httpClient.sendRequest({
method: HttpMethod.GET,
url: 'https://viralapi.vadoo.tv/api/get_languages',
headers: {
'X-API-KEY': auth.secret_text,
},
});
const languages = response.body as string[];
return {
disabled: false,
options: languages.map((language) => ({
label: language,
value: language,
})),
};
} catch (error) {
return {
disabled: true,
options: [],
placeholder: 'Failed to load languages',
};
}
},
}),
duration: Property.StaticDropdown({
displayName: 'Duration',
description: 'Video Duration',
required: false,
defaultValue: '30-60',
options: {
options: [
{ label: '30-60 seconds', value: '30-60' },
{ label: '60-90 seconds', value: '60-90' },
{ label: '90-120 seconds', value: '90-120' },
{ label: '5 minutes', value: '5 min' },
{ label: '10 minutes', value: '10 min' },
],
},
}),
aspect_ratio: Property.StaticDropdown({
displayName: 'Aspect Ratio',
description: 'Video aspect ratio',
required: false,
defaultValue: '9:16',
options: {
options: [
{ label: '9:16 (Portrait)', value: '9:16' },
{ label: '1:1 (Square)', value: '1:1' },
{ label: '16:9 (Landscape)', value: '16:9' },
],
},
}),
custom_instruction: Property.LongText({
displayName: 'Custom Instructions',
description:
'Custom instructions to guide AI (character descriptions, image visuals, background styles, etc.)',
required: false,
}),
use_ai: Property.StaticDropdown({
displayName: 'Use AI to Modify Script',
description: 'Modify script with AI',
required: false,
defaultValue: '1',
options: {
options: [
{ label: 'Yes', value: '1' },
{ label: 'No', value: '0' },
],
},
}),
include_voiceover: Property.StaticDropdown({
displayName: 'Include Voiceover',
description: 'Include AI voiceover in the video',
required: false,
defaultValue: '1',
options: {
options: [
{ label: 'Yes', value: '1' },
{ label: 'No', value: '0' },
],
},
}),
size: Property.ShortText({
displayName: 'Caption Size',
description: 'Size of captions (take reference values from dashboard)',
required: false,
}),
ypos: Property.ShortText({
displayName: 'Caption Position',
description:
'Position of captions (take reference values from dashboard)',
required: false,
}),
url: Property.ShortText({
displayName: 'Blog URL',
description: 'URL input for Blog to Video',
required: false,
}),
bg_music: Property.Dropdown({
auth: vadooAiAuth,
displayName: 'Background Music',
description: 'Background music to use along with the video',
required: false,
refreshers: [],
options: async ({ auth }) => {
if (!auth) {
return {
disabled: true,
options: [],
placeholder: 'Please authenticate first',
};
}
try {
const response = await httpClient.sendRequest({
method: HttpMethod.GET,
url: 'https://viralapi.vadoo.tv/api/get_background_music',
headers: {
'X-API-KEY': auth.secret_text,
},
});
const music = response.body as string[];
return {
disabled: false,
options: music.map((track) => ({
label: track,
value: track,
})),
};
} catch (error) {
return {
disabled: true,
options: [],
placeholder: 'Failed to load background music',
};
}
},
}),
bg_music_volume: Property.Number({
displayName: 'Background Music Volume',
description: 'Background music volume (1-100)',
required: false,
}),
},
async run(context) {
// Validate props with Zod schema
await propsValidation.validateZod(context.propsValue, generateVideoSchema);
const {
topic,
prompt,
voice,
theme,
style,
language,
duration,
aspect_ratio,
custom_instruction,
use_ai,
include_voiceover,
size,
ypos,
url,
bg_music,
bg_music_volume,
} = context.propsValue;
// Validate custom prompt when topic is "Custom"
if (topic === 'Custom' && !prompt) {
throw new Error(
"Custom prompt is required when topic is set to 'Custom'"
);
}
// Build request body, only including non-empty values
const requestBody: Record<string, any> = {};
if (topic) requestBody['topic'] = topic;
if (prompt) requestBody['prompt'] = prompt;
if (voice) requestBody['voice'] = voice;
if (theme) requestBody['theme'] = theme;
if (style) requestBody['style'] = style;
if (language) requestBody['language'] = language;
if (duration) requestBody['duration'] = duration;
if (aspect_ratio) requestBody['aspect_ratio'] = aspect_ratio;
if (custom_instruction)
requestBody['custom_instruction'] = custom_instruction;
if (use_ai) requestBody['use_ai'] = use_ai;
if (include_voiceover) requestBody['include_voiceover'] = include_voiceover;
if (size) requestBody['size'] = size;
if (ypos) requestBody['ypos'] = ypos;
if (url) requestBody['url'] = url;
if (bg_music) requestBody['bg_music'] = bg_music;
if (bg_music_volume)
requestBody['bg_music_volume'] = bg_music_volume.toString();
const response = await httpClient.sendRequest<{ vid: number }>({
method: HttpMethod.POST,
url: 'https://viralapi.vadoo.tv/api/generate_video',
headers: {
'X-API-KEY': context.auth.secret_text,
'Content-Type': 'application/json',
},
body: requestBody,
});
if (isEmpty(response.body) || isEmpty(response.body.vid)) {
throw new Error('Failed to generate video.');
}
const videoId = response.body.vid;
let status = 'pending';
const timeoutAt = Date.now() + 5 * 60 * 1000;
do {
await new Promise((resolve) => setTimeout(resolve, 5000));
const pollRes = await httpClient.sendRequest<{
url: string;
status: string;
}>({
method: HttpMethod.GET,
url: 'https://viralapi.vadoo.tv/api/get_video_url',
headers: {
'X-API-KEY': context.auth.secret_text,
'Content-Type': 'application/json',
},
queryParams: {
id: videoId.toString(),
},
});
status = pollRes.body.status;
if (status === 'complete') return pollRes.body;
} while (status !== 'complete' && Date.now() < timeoutAt);
throw new Error('Generate Video timed out or failed.');
},
});

View File

@@ -0,0 +1,85 @@
import { z } from 'zod';
export const GenerateVideoRequestSchema = z.object({
topic: z.string().optional(),
prompt: z.string().optional(),
voice: z.string().optional(),
theme: z.string().optional(),
style: z.string().optional(),
language: z.string().optional(),
duration: z.enum(['30-60', '60-90', '90-120', '5 min', '10 min']).optional(),
aspect_ratio: z.enum(['9:16', '1:1', '16:9']).optional(),
custom_instruction: z.string().optional(),
use_ai: z.enum(['1', '0']).optional(),
include_voiceover: z.enum(['1', '0']).optional(),
size: z.string().optional(),
ypos: z.string().optional(),
url: z.string().url().optional().or(z.literal('')),
bg_music: z.string().optional(),
bg_music_volume: z.number().min(1).max(100).optional()
});
export const GeneratePodcastRequestSchema = z.object({
content_source: z.enum(['url', 'text']),
url: z.string().url().optional().or(z.literal('')),
text: z.string().optional(),
name1: z.string().min(1),
voice1: z.string().optional(),
name2: z.string().min(1),
voice2: z.string().optional(),
theme: z.string().optional(),
language: z.string().optional(),
duration: z.enum(['1-2', '3-5']).optional(),
tone: z.string().optional()
});
export const VadooApiResponseSchema = z.object({
vid: z.number()
});
// Export the object schemas for use with propsValidation.validateZod
export const generateVideoSchema = {
topic: z.string().optional(),
prompt: z.string().optional(),
voice: z.string().optional(),
theme: z.string().optional(),
style: z.string().optional(),
language: z.string().optional(),
duration: z.enum(['30-60', '60-90', '90-120', '5 min', '10 min']).optional(),
aspect_ratio: z.enum(['9:16', '1:1', '16:9']).optional(),
custom_instruction: z.string().optional(),
use_ai: z.enum(['1', '0']).optional(),
include_voiceover: z.enum(['1', '0']).optional(),
size: z.string().optional(),
ypos: z.string().optional(),
url: z.string().url().optional().or(z.literal('')),
bg_music: z.string().optional(),
bg_music_volume: z.number().min(1).max(100).optional()
};
export const generatePodcastSchema = {
content_source: z.enum(['url', 'text']),
url: z.string().url().optional().or(z.literal('')),
text: z.string().optional(),
name1: z.string().min(1),
voice1: z.string().optional(),
name2: z.string().min(1),
voice2: z.string().optional(),
theme: z.string().optional(),
language: z.string().optional(),
duration: z.enum(['1-2', '3-5']).optional(),
tone: z.string().optional()
};
export const generateAiImageSchema = {
id: z.string().min(1),
ratio: z.enum(['9:16', '1:1', '16:9', '3:4', '4:3']),
style: z.string().optional(),
prompt: z.string().min(1)
};
export const generateAiCaptionsSchema = {
url: z.string().url(),
theme: z.string().optional(),
language: z.string().optional()
};

View File

@@ -0,0 +1,20 @@
{
"extends": "../../../../tsconfig.base.json",
"compilerOptions": {
"module": "commonjs",
"forceConsistentCasingInFileNames": true,
"strict": true,
"importHelpers": true,
"noImplicitOverride": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"noPropertyAccessFromIndexSignature": true
},
"files": [],
"include": [],
"references": [
{
"path": "./tsconfig.lib.json"
}
]
}

View File

@@ -0,0 +1,9 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../../../dist/out-tsc",
"declaration": true,
"types": ["node"]
},
"include": ["src/**/*.ts"]
}