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:
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"extends": ["../../../../.eslintrc.json"],
|
||||
"ignorePatterns": ["!**/*"],
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
|
||||
"rules": {}
|
||||
},
|
||||
{
|
||||
"files": ["*.ts", "*.tsx"],
|
||||
"rules": {}
|
||||
},
|
||||
{
|
||||
"files": ["*.js", "*.jsx"],
|
||||
"rules": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
# pieces-sendpulse
|
||||
|
||||
This library was generated with [Nx](https://nx.dev).
|
||||
|
||||
## Building
|
||||
|
||||
Run `nx build pieces-sendpulse` to build the library.
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"name": "@activepieces/piece-sendpulse",
|
||||
"version": "0.0.8",
|
||||
"type": "commonjs",
|
||||
"main": "./src/index.js",
|
||||
"types": "./src/index.d.ts",
|
||||
"dependencies": {
|
||||
"tslib": "^2.3.0"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
{
|
||||
"name": "pieces-sendpulse",
|
||||
"$schema": "../../../../node_modules/nx/schemas/project-schema.json",
|
||||
"sourceRoot": "packages/pieces/community/sendpulse/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/sendpulse",
|
||||
"tsConfig": "packages/pieces/community/sendpulse/tsconfig.lib.json",
|
||||
"packageJson": "packages/pieces/community/sendpulse/package.json",
|
||||
"main": "packages/pieces/community/sendpulse/src/index.ts",
|
||||
"assets": [
|
||||
"packages/pieces/community/sendpulse/*.md",
|
||||
{
|
||||
"input": "packages/pieces/community/sendpulse/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/sendpulse",
|
||||
"command": "bun install --no-save --silent"
|
||||
},
|
||||
"dependsOn": [
|
||||
"^build"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
{
|
||||
"Client ID": "Kunden-ID",
|
||||
"Client Secret": "Kundengeheimnis",
|
||||
"Enter your SendPulse client credentials": "Geben Sie Ihre SendPulse Client-Zugangsdaten ein",
|
||||
"Add Subscriber": "Abonnent hinzufügen",
|
||||
"Change Variable for Subscriber": "Variable für Abonnenten ändern",
|
||||
"Delete Contact": "Kontakt löschen",
|
||||
"Unsubscribe User": "Benutzer abbestellen",
|
||||
"Update Subscriber": "Abonnent aktualisieren",
|
||||
"Custom API Call": "Eigener API-Aufruf",
|
||||
"Add subscriber to mailing list": "Abonnent zur Mailingliste hinzufügen",
|
||||
"Update subscriber variable": "Abonnenten-Variable aktualisieren",
|
||||
"Permanently delete contact from all mailing lists": "Kontakt dauerhaft von allen Mailinglisten löschen",
|
||||
"Remove subscribers from mailing list": "Abonnenten von der Mailingliste entfernen",
|
||||
"Update subscriber details and variables": "Abonnenten-Details und Variablen aktualisieren",
|
||||
"Make a custom API call to a specific endpoint": "Einen benutzerdefinierten API-Aufruf an einen bestimmten Endpunkt machen",
|
||||
"Mailing List": "Mailingliste",
|
||||
"Email Address": "E-Mail-Adresse",
|
||||
"Variables": "Variablen",
|
||||
"Tag IDs": "Tag-IDs",
|
||||
"Variable Name": "Variablenname",
|
||||
"Variable Value": "Variablenwert",
|
||||
"Email Addresses": "E-Mail-Adressen",
|
||||
"Phone Number": "Telefonnummer",
|
||||
"Method": "Methode",
|
||||
"Headers": "Kopfzeilen",
|
||||
"Query Parameters": "Abfrageparameter",
|
||||
"Body": "Körper",
|
||||
"Response is Binary ?": "Antwort ist binär?",
|
||||
"No Error on Failure": "Kein Fehler bei Fehler",
|
||||
"Timeout (in seconds)": "Timeout (in Sekunden)",
|
||||
"Select one of your SendPulse mailing lists": "Wählen Sie eine Ihrer SendPulse Mailinglisten",
|
||||
"Subscriber email address": "E-Mail Adresse des Abonnenten",
|
||||
"Optional subscriber variables (e.g., name, phone)": "Optionale Abonnentenvariablen (z.B. Name, Telefon)",
|
||||
"Optional tag IDs to assign": "Optionale Tag-IDs zum Zuweisen",
|
||||
"Select variable to update": "Wählen Sie die zu aktualisierende Variable",
|
||||
"New value for the variable": "Neuer Wert für die Variable",
|
||||
"Email address to delete from all mailing lists": "E-Mail-Adresse, die von allen Mailinglisten gelöscht werden soll",
|
||||
"Email addresses to unsubscribe (max 100)": "E-Mail-Adressen zum Abbestellen (max. 100)",
|
||||
"Email address of the subscriber to update": "E-Mail-Adresse des zu aktualisierenden Abonnenten",
|
||||
"New phone number (optional)": "Neue Telefonnummer (optional)",
|
||||
"Subscriber variables to update (e.g., name, custom fields)": "Abonnenten-Variablen zum Aktualisieren (z. B. Name, benutzerdefinierte Felder)",
|
||||
"Authorization headers are injected automatically from your connection.": "Autorisierungs-Header werden automatisch von Ihrer Verbindung injiziert.",
|
||||
"Enable for files like PDFs, images, etc..": "Aktivieren für Dateien wie PDFs, Bilder, etc..",
|
||||
"GET": "ERHALTEN",
|
||||
"POST": "POST",
|
||||
"PATCH": "PATCH",
|
||||
"PUT": "PUT",
|
||||
"DELETE": "LÖSCHEN",
|
||||
"HEAD": "HEAD",
|
||||
"New Subscriber": "Neuer Abonnent",
|
||||
"New Unsubscriber": "Neuer Abmelder",
|
||||
"Updated Subscriber": "Abonnent aktualisiert",
|
||||
"Fires when new subscriber is added": "Feuert wenn neuer Abonnent hinzugefügt wird",
|
||||
"Fires when subscriber unsubscribes": "Löscht ab, wenn Abonnent abbestellt wird",
|
||||
"Fires when subscriber details change (polling)": "Feuer, wenn Abonnentendetails geändert werden (Umfrage)"
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
{
|
||||
"Client ID": "ID de cliente",
|
||||
"Client Secret": "Cliente secreto",
|
||||
"Enter your SendPulse client credentials": "Introduzca sus credenciales de cliente de SendPulse",
|
||||
"Add Subscriber": "Añadir suscriptor",
|
||||
"Change Variable for Subscriber": "Cambiar variable para el suscriptor",
|
||||
"Delete Contact": "Eliminar contacto",
|
||||
"Unsubscribe User": "Darse de baja de usuario",
|
||||
"Update Subscriber": "Actualizar suscriptor",
|
||||
"Custom API Call": "Llamada API personalizada",
|
||||
"Add subscriber to mailing list": "Añadir suscriptor a la lista de correo",
|
||||
"Update subscriber variable": "Actualizar variable de suscriptor",
|
||||
"Permanently delete contact from all mailing lists": "Borrar permanentemente el contacto de todas las listas de correo",
|
||||
"Remove subscribers from mailing list": "Eliminar suscriptores de la lista de correo",
|
||||
"Update subscriber details and variables": "Actualizar detalles del suscriptor y variables",
|
||||
"Make a custom API call to a specific endpoint": "Hacer una llamada API personalizada a un extremo específico",
|
||||
"Mailing List": "Lista de correo",
|
||||
"Email Address": "Dirección de email",
|
||||
"Variables": "Variables",
|
||||
"Tag IDs": "ID de etiqueta",
|
||||
"Variable Name": "Nombre variable",
|
||||
"Variable Value": "Valor variable",
|
||||
"Email Addresses": "Direcciones de email",
|
||||
"Phone Number": "Número de teléfono",
|
||||
"Method": "Método",
|
||||
"Headers": "Encabezados",
|
||||
"Query Parameters": "Parámetros de consulta",
|
||||
"Body": "Cuerpo",
|
||||
"Response is Binary ?": "¿Respuesta es binaria?",
|
||||
"No Error on Failure": "No hay ningún error en fallo",
|
||||
"Timeout (in seconds)": "Tiempo de espera (en segundos)",
|
||||
"Select one of your SendPulse mailing lists": "Seleccione una de sus listas de correo de SendPulse",
|
||||
"Subscriber email address": "Dirección de correo del suscriptor",
|
||||
"Optional subscriber variables (e.g., name, phone)": "Variables opcionales de suscriptores (por ejemplo, nombre, teléfono)",
|
||||
"Optional tag IDs to assign": "ID de etiqueta opcional a asignar",
|
||||
"Select variable to update": "Seleccione la variable a actualizar",
|
||||
"New value for the variable": "Nuevo valor para la variable",
|
||||
"Email address to delete from all mailing lists": "Dirección de correo electrónico a eliminar de todas las listas de correo",
|
||||
"Email addresses to unsubscribe (max 100)": "Direcciones de correo para darse de baja (máx. 100)",
|
||||
"Email address of the subscriber to update": "Dirección de correo electrónico del suscriptor a actualizar",
|
||||
"New phone number (optional)": "Nuevo número de teléfono (opcional)",
|
||||
"Subscriber variables to update (e.g., name, custom fields)": "Variables de suscriptores a actualizar (por ejemplo, nombre, campos personalizados)",
|
||||
"Authorization headers are injected automatically from your connection.": "Las cabeceras de autorización se inyectan automáticamente desde tu conexión.",
|
||||
"Enable for files like PDFs, images, etc..": "Activar para archivos como PDFs, imágenes, etc.",
|
||||
"GET": "RECOGER",
|
||||
"POST": "POST",
|
||||
"PATCH": "PATCH",
|
||||
"PUT": "PUT",
|
||||
"DELETE": "BORRAR",
|
||||
"HEAD": "LIMPIO",
|
||||
"New Subscriber": "Nuevo suscriptor",
|
||||
"New Unsubscriber": "Nuevo desuscriptor",
|
||||
"Updated Subscriber": "Suscriptor actualizado",
|
||||
"Fires when new subscriber is added": "Dispara cuando se añade un nuevo suscriptor",
|
||||
"Fires when subscriber unsubscribes": "Se activa cuando los suscriptores se dan de baja",
|
||||
"Fires when subscriber details change (polling)": "Dispara cuando los detalles del suscriptor cambian (encuesta)"
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
{
|
||||
"Client ID": "ID client",
|
||||
"Client Secret": "Clé secrète du client",
|
||||
"Enter your SendPulse client credentials": "Entrez vos identifiants de client SendPulse",
|
||||
"Add Subscriber": "Ajouter un abonné",
|
||||
"Change Variable for Subscriber": "Modifier la variable pour l'abonné",
|
||||
"Delete Contact": "Supprimer le contact",
|
||||
"Unsubscribe User": "Se désabonner de l'utilisateur",
|
||||
"Update Subscriber": "Mettre à jour l'abonné",
|
||||
"Custom API Call": "Appel d'API personnalisé",
|
||||
"Add subscriber to mailing list": "Ajouter un abonné à la liste de diffusion",
|
||||
"Update subscriber variable": "Mettre à jour la variable d'abonné",
|
||||
"Permanently delete contact from all mailing lists": "Supprimer définitivement le contact de toutes les listes de diffusion",
|
||||
"Remove subscribers from mailing list": "Retirer les abonnés de la liste de diffusion",
|
||||
"Update subscriber details and variables": "Mettre à jour les détails de l'abonné et les variables",
|
||||
"Make a custom API call to a specific endpoint": "Passer un appel API personnalisé à un endpoint spécifique",
|
||||
"Mailing List": "Liste de diffusion",
|
||||
"Email Address": "Adresse e-mail",
|
||||
"Variables": "Variables",
|
||||
"Tag IDs": "ID du tag",
|
||||
"Variable Name": "Nom de la variable",
|
||||
"Variable Value": "Valeur de la variable",
|
||||
"Email Addresses": "Adresses e-mail",
|
||||
"Phone Number": "Numéro de téléphone",
|
||||
"Method": "Méthode",
|
||||
"Headers": "En-têtes",
|
||||
"Query Parameters": "Paramètres de requête",
|
||||
"Body": "Corps",
|
||||
"Response is Binary ?": "La réponse est Binaire ?",
|
||||
"No Error on Failure": "Aucune erreur en cas d'échec",
|
||||
"Timeout (in seconds)": "Délai d'expiration (en secondes)",
|
||||
"Select one of your SendPulse mailing lists": "Sélectionnez une de vos listes de diffusion SendPulse",
|
||||
"Subscriber email address": "Adresse e-mail de l'abonné",
|
||||
"Optional subscriber variables (e.g., name, phone)": "Variables optionnelles d'abonné (par exemple, nom, téléphone)",
|
||||
"Optional tag IDs to assign": "ID de tag facultatif à assigner",
|
||||
"Select variable to update": "Sélectionnez la variable à mettre à jour",
|
||||
"New value for the variable": "Nouvelle valeur pour la variable",
|
||||
"Email address to delete from all mailing lists": "Adresse e-mail à supprimer de toutes les listes de diffusion",
|
||||
"Email addresses to unsubscribe (max 100)": "Adresses e-mail pour se désabonner (max 100)",
|
||||
"Email address of the subscriber to update": "Adresse e-mail de l'abonné à mettre à jour",
|
||||
"New phone number (optional)": "Nouveau numéro de téléphone (facultatif)",
|
||||
"Subscriber variables to update (e.g., name, custom fields)": "Variables d'abonné à mettre à jour (par exemple, nom, champs personnalisés)",
|
||||
"Authorization headers are injected automatically from your connection.": "Les en-têtes d'autorisation sont injectés automatiquement à partir de votre connexion.",
|
||||
"Enable for files like PDFs, images, etc..": "Activer pour les fichiers comme les PDFs, les images, etc.",
|
||||
"GET": "GET",
|
||||
"POST": "POST",
|
||||
"PATCH": "PATCH",
|
||||
"PUT": "PUT",
|
||||
"DELETE": "DELETE",
|
||||
"HEAD": "HEAD",
|
||||
"New Subscriber": "Nouvel abonné",
|
||||
"New Unsubscriber": "Nouveau désabonné",
|
||||
"Updated Subscriber": "Abonné mis à jour",
|
||||
"Fires when new subscriber is added": "Déclenche quand un nouvel abonné est ajouté",
|
||||
"Fires when subscriber unsubscribes": "Déclenche lorsque l'abonné se désabonne",
|
||||
"Fires when subscriber details change (polling)": "Déclenche lorsque les détails de l'abonné changent (sondage)"
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
{
|
||||
"Client ID": "クライアント ID",
|
||||
"Client Secret": "クライアントシークレット",
|
||||
"Enter your SendPulse client credentials": "SendPulseクライアントの資格情報を入力してください",
|
||||
"Add Subscriber": "購読者を追加",
|
||||
"Change Variable for Subscriber": "購読者の変数を変更する",
|
||||
"Delete Contact": "連絡先を削除",
|
||||
"Unsubscribe User": "Unsubscribe User",
|
||||
"Update Subscriber": "購読者を更新",
|
||||
"Custom API Call": "カスタムAPI通話",
|
||||
"Add subscriber to mailing list": "購読者をメーリングリストに追加",
|
||||
"Update subscriber variable": "購読者変数を更新",
|
||||
"Permanently delete contact from all mailing lists": "すべてのメーリングリストから連絡先を完全に削除",
|
||||
"Remove subscribers from mailing list": "メーリングリストから購読者を削除",
|
||||
"Update subscriber details and variables": "購読者の詳細と変数を更新",
|
||||
"Make a custom API call to a specific endpoint": "特定のエンドポイントへのカスタム API コールを実行します。",
|
||||
"Mailing List": "メーリングリスト:",
|
||||
"Email Address": "メールアドレス",
|
||||
"Variables": "変数",
|
||||
"Tag IDs": "タグID",
|
||||
"Variable Name": "変数名",
|
||||
"Variable Value": "変数値",
|
||||
"Email Addresses": "メールアドレス",
|
||||
"Phone Number": "電話番号",
|
||||
"Method": "方法",
|
||||
"Headers": "ヘッダー",
|
||||
"Query Parameters": "クエリパラメータ",
|
||||
"Body": "本文",
|
||||
"Response is Binary ?": "応答はバイナリですか?",
|
||||
"No Error on Failure": "失敗時にエラーはありません",
|
||||
"Timeout (in seconds)": "タイムアウト(秒)",
|
||||
"Select one of your SendPulse mailing lists": "SendPulseメーリングリストのいずれかを選択してください",
|
||||
"Subscriber email address": "購読者メールアドレス",
|
||||
"Optional subscriber variables (e.g., name, phone)": "オプションの購読者変数(例、名前、電話番号)",
|
||||
"Optional tag IDs to assign": "割り当てるオプションのタグID",
|
||||
"Select variable to update": "更新する変数を選択",
|
||||
"New value for the variable": "変数の新しい値",
|
||||
"Email address to delete from all mailing lists": "すべてのメーリングリストから削除するメールアドレス",
|
||||
"Email addresses to unsubscribe (max 100)": "購読解除メールアドレス(最大100)",
|
||||
"Email address of the subscriber to update": "更新する購読者のメールアドレス",
|
||||
"New phone number (optional)": "新しい電話番号 (オプション)",
|
||||
"Subscriber variables to update (e.g., name, custom fields)": "更新する変数(例、名前、カスタムフィールド)",
|
||||
"Authorization headers are injected automatically from your connection.": "認証ヘッダは接続から自動的に注入されます。",
|
||||
"Enable for files like PDFs, images, etc..": "PDF、画像などのファイルを有効にします。",
|
||||
"GET": "取得",
|
||||
"POST": "POST",
|
||||
"PATCH": "PATCH",
|
||||
"PUT": "PUT",
|
||||
"DELETE": "削除",
|
||||
"HEAD": "頭",
|
||||
"New Subscriber": "新規購読",
|
||||
"New Unsubscriber": "新しい購読解除",
|
||||
"Updated Subscriber": "購読者の更新",
|
||||
"Fires when new subscriber is added": "新しい購読者が追加されたときに発火します",
|
||||
"Fires when subscriber unsubscribes": "購読者が購読解除した時に発火する",
|
||||
"Fires when subscriber details change (polling)": "購読者の詳細が変更されたときに発火します(ポーリング)"
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
{
|
||||
"Client ID": "Klant ID",
|
||||
"Client Secret": "Client Secret",
|
||||
"Enter your SendPulse client credentials": "Voer uw SendPulse clientreferenties in",
|
||||
"Add Subscriber": "Voeg abonnee toe",
|
||||
"Change Variable for Subscriber": "Variabele voor abonnee wijzigen",
|
||||
"Delete Contact": "Contactpersoon verwijderen",
|
||||
"Unsubscribe User": "Gebruiker afmelden",
|
||||
"Update Subscriber": "Abonnee bijwerken",
|
||||
"Custom API Call": "Custom API Call",
|
||||
"Add subscriber to mailing list": "Voeg abonnee toe aan de mailinglijst",
|
||||
"Update subscriber variable": "Abonnee variabele bijwerken",
|
||||
"Permanently delete contact from all mailing lists": "Contact permanent verwijderen uit alle mailinglijsten",
|
||||
"Remove subscribers from mailing list": "Abonnees van mailinglijst verwijderen",
|
||||
"Update subscriber details and variables": "Abonnee details en variabelen bijwerken",
|
||||
"Make a custom API call to a specific endpoint": "Maak een aangepaste API call naar een specifiek eindpunt",
|
||||
"Mailing List": "Mailing lijst",
|
||||
"Email Address": "Uw e-mailadres",
|
||||
"Variables": "Variabelen",
|
||||
"Tag IDs": "Tag ID's",
|
||||
"Variable Name": "Variabele naam",
|
||||
"Variable Value": "Variabele waarde",
|
||||
"Email Addresses": "E-mail adressen",
|
||||
"Phone Number": "Telefoon nummer",
|
||||
"Method": "Methode",
|
||||
"Headers": "Kopteksten",
|
||||
"Query Parameters": "Query parameters",
|
||||
"Body": "Lichaam",
|
||||
"Response is Binary ?": "Antwoord is binair?",
|
||||
"No Error on Failure": "Geen fout bij fout",
|
||||
"Timeout (in seconds)": "Time-out (in seconden)",
|
||||
"Select one of your SendPulse mailing lists": "Selecteer een van je SendPulse mailing lijsten",
|
||||
"Subscriber email address": "E-mailadres abonnee",
|
||||
"Optional subscriber variables (e.g., name, phone)": "Optionele abonnee variabelen (bijv. naam, telefoon)",
|
||||
"Optional tag IDs to assign": "Optionele tag IDs toe te wijzen",
|
||||
"Select variable to update": "Selecteer een variabele om bij te werken",
|
||||
"New value for the variable": "Nieuwe waarde voor de variabele",
|
||||
"Email address to delete from all mailing lists": "E-mailadres om te verwijderen uit alle mailinglijsten",
|
||||
"Email addresses to unsubscribe (max 100)": "Email adressen om af te melden (max 100)",
|
||||
"Email address of the subscriber to update": "E-mailadres van de te updaten abonnee",
|
||||
"New phone number (optional)": "Nieuw telefoonnummer (optioneel)",
|
||||
"Subscriber variables to update (e.g., name, custom fields)": "Bijwerken abonnee variabelen (bijv. naam, aangepaste velden)",
|
||||
"Authorization headers are injected automatically from your connection.": "Autorisatie headers worden automatisch geïnjecteerd vanuit uw verbinding.",
|
||||
"Enable for files like PDFs, images, etc..": "Inschakelen voor bestanden zoals PDF's, afbeeldingen etc..",
|
||||
"GET": "KRIJG",
|
||||
"POST": "POSTE",
|
||||
"PATCH": "BEKIJK",
|
||||
"PUT": "PUT",
|
||||
"DELETE": "VERWIJDEREN",
|
||||
"HEAD": "HOOFD",
|
||||
"New Subscriber": "Nieuwe abonnee",
|
||||
"New Unsubscriber": "Nieuwe afmelder",
|
||||
"Updated Subscriber": "Abonnee bijgewerkt",
|
||||
"Fires when new subscriber is added": "Vuurt wanneer nieuwe abonnee is toegevoegd",
|
||||
"Fires when subscriber unsubscribes": "Vuurt wanneer abonnee zich uitschrijft",
|
||||
"Fires when subscriber details change (polling)": "Vuurt wanneer details van abonnee veranderen (polling)"
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
{
|
||||
"Client ID": "ID do Cliente",
|
||||
"Client Secret": "Chave secreta",
|
||||
"Enter your SendPulse client credentials": "Digite suas credenciais do cliente SendPulse",
|
||||
"Add Subscriber": "Adicionar Assinante",
|
||||
"Change Variable for Subscriber": "Alterar variável para Assinante",
|
||||
"Delete Contact": "Excluir contato",
|
||||
"Unsubscribe User": "Desinscrever usuário",
|
||||
"Update Subscriber": "Atualizar Assinante",
|
||||
"Custom API Call": "Chamada de API personalizada",
|
||||
"Add subscriber to mailing list": "Adicionar assinante à lista de e-mails",
|
||||
"Update subscriber variable": "Atualizar variável de assinante",
|
||||
"Permanently delete contact from all mailing lists": "Excluir permanentemente contatos de todas as listas de discussão",
|
||||
"Remove subscribers from mailing list": "Remover membros da lista de e-mails",
|
||||
"Update subscriber details and variables": "Atualizar detalhes e variáveis de assinantes",
|
||||
"Make a custom API call to a specific endpoint": "Faça uma chamada de API personalizada para um ponto de extremidade específico",
|
||||
"Mailing List": "Lista de Correio",
|
||||
"Email Address": "Endereço de e-mail",
|
||||
"Variables": "Variáveis",
|
||||
"Tag IDs": "IDs de tags",
|
||||
"Variable Name": "Nome da Variável",
|
||||
"Variable Value": "Valor da Variável",
|
||||
"Email Addresses": "Endereços de e-mail",
|
||||
"Phone Number": "Número de telefone",
|
||||
"Method": "Método",
|
||||
"Headers": "Cabeçalhos",
|
||||
"Query Parameters": "Parâmetros da consulta",
|
||||
"Body": "Conteúdo",
|
||||
"Response is Binary ?": "A resposta é binária ?",
|
||||
"No Error on Failure": "Nenhum erro no Failure",
|
||||
"Timeout (in seconds)": "Tempo limite (em segundos)",
|
||||
"Select one of your SendPulse mailing lists": "Selecione uma das suas listas de discussão do SendPulse",
|
||||
"Subscriber email address": "Endereço de e-mail assinante",
|
||||
"Optional subscriber variables (e.g., name, phone)": "Variáveis opcionais de assinante (por exemplo, nome, telefone)",
|
||||
"Optional tag IDs to assign": "IDs de tags opcionais para atribuir",
|
||||
"Select variable to update": "Selecione a variável para atualizar",
|
||||
"New value for the variable": "Novo valor para a variável",
|
||||
"Email address to delete from all mailing lists": "Endereço de email a ser excluído de todas as listas de email",
|
||||
"Email addresses to unsubscribe (max 100)": "Endereços de e-mail para cancelar inscrição (máx. 100)",
|
||||
"Email address of the subscriber to update": "Endereço de e-mail do assinante para atualizar",
|
||||
"New phone number (optional)": "Novo número de telefone (opcional)",
|
||||
"Subscriber variables to update (e.g., name, custom fields)": "Variáveis de assinante para atualizar (por exemplo, nome, campos personalizados)",
|
||||
"Authorization headers are injected automatically from your connection.": "Os cabeçalhos de autorização são inseridos automaticamente a partir da sua conexão.",
|
||||
"Enable for files like PDFs, images, etc..": "Habilitar para arquivos como PDFs, imagens, etc..",
|
||||
"GET": "OBTER",
|
||||
"POST": "POSTAR",
|
||||
"PATCH": "COMPRAR",
|
||||
"PUT": "COLOCAR",
|
||||
"DELETE": "EXCLUIR",
|
||||
"HEAD": "CABEÇA",
|
||||
"New Subscriber": "Novo Assinante",
|
||||
"New Unsubscriber": "Novo Desassinante",
|
||||
"Updated Subscriber": "Assinante atualizado",
|
||||
"Fires when new subscriber is added": "Efetua quando um novo assinante é adicionado",
|
||||
"Fires when subscriber unsubscribes": "Atira quando o assinante cancelar a assinatura",
|
||||
"Fires when subscriber details change (polling)": "Efetua quando os detalhes do inscrito mudam (enquete)"
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
{
|
||||
"SendPulse": "SendPulse",
|
||||
"Client ID": "ID клиента",
|
||||
"Client Secret": "Секрет клиента",
|
||||
"Enter your SendPulse client credentials": "Введите учетные данные клиента SendPulse",
|
||||
"Add Subscriber": "Добавить подписчика",
|
||||
"Change Variable for Subscriber": "Изменить переменную для подписчика",
|
||||
"Delete Contact": "Удалить контакт",
|
||||
"Unsubscribe User": "Отписаться от пользователя",
|
||||
"Update Subscriber": "Обновить подписчика",
|
||||
"Custom API Call": "Пользовательский вызов API",
|
||||
"Add subscriber to mailing list": "Добавить подписчика в список рассылки",
|
||||
"Update subscriber variable": "Обновить переменную подписчика",
|
||||
"Permanently delete contact from all mailing lists": "Удалить контакт из всех списков рассылки",
|
||||
"Remove subscribers from mailing list": "Удалить подписчиков из списка рассылки",
|
||||
"Update subscriber details and variables": "Обновить детали и переменные подписчика",
|
||||
"Make a custom API call to a specific endpoint": "Сделать пользовательский API вызов к определенной конечной точке",
|
||||
"Mailing List": "Список рассылки",
|
||||
"Email Address": "Email Address",
|
||||
"Variables": "Переменные",
|
||||
"Tag IDs": "ID тегов",
|
||||
"Variable Name": "Имя переменной",
|
||||
"Variable Value": "Переменное значение",
|
||||
"Email Addresses": "Адреса E-mail",
|
||||
"Phone Number": "Номер телефона",
|
||||
"Method": "Метод",
|
||||
"Headers": "Заголовки",
|
||||
"Query Parameters": "Параметры запроса",
|
||||
"Body": "Тело",
|
||||
"No Error on Failure": "Нет ошибок при ошибке",
|
||||
"Timeout (in seconds)": "Таймаут (в секундах)",
|
||||
"Select one of your SendPulse mailing lists": "Выберите один из ваших списков рассылки SendPulse",
|
||||
"Subscriber email address": "Адрес электронной почты подписчика",
|
||||
"Optional subscriber variables (e.g., name, phone)": "Необязательные переменные подписчика (например, имя, телефон)",
|
||||
"Optional tag IDs to assign": "Необязательные идентификаторы тегов для назначения",
|
||||
"Select variable to update": "Выберите переменную для обновления",
|
||||
"New value for the variable": "Новое значение для переменной",
|
||||
"Email address to delete from all mailing lists": "Адрес электронной почты для удаления из всех списков рассылки",
|
||||
"Email addresses to unsubscribe (max 100)": "Отписаться от e-mail адресов (максимум 100)",
|
||||
"Email address of the subscriber to update": "Адрес электронной почты подписчика для обновления",
|
||||
"New phone number (optional)": "Новый номер телефона (необязательно)",
|
||||
"Subscriber variables to update (e.g., name, custom fields)": "Абонентские переменные для обновления (например, имя, пользовательские поля)",
|
||||
"Authorization headers are injected automatically from your connection.": "Заголовки авторизации включаются автоматически из вашего соединения.",
|
||||
"GET": "ПОЛУЧИТЬ",
|
||||
"POST": "ПОСТ",
|
||||
"PATCH": "ПАТЧ",
|
||||
"PUT": "ПОКУПИТЬ",
|
||||
"DELETE": "УДАЛИТЬ",
|
||||
"HEAD": "HEAD",
|
||||
"New Subscriber": "Новый подписчик",
|
||||
"New Unsubscriber": "Новый отказ от подписки",
|
||||
"Updated Subscriber": "Абонент обновлен",
|
||||
"Fires when new subscriber is added": "Оказывается при добавлении нового абонента",
|
||||
"Fires when subscriber unsubscribes": "Огнестрел при отказе от подписки",
|
||||
"Fires when subscriber details change (polling)": "Огнестрелы при смене сведений подписчика (опрос)"
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
{
|
||||
"Client ID": "Client ID",
|
||||
"Client Secret": "Client Secret",
|
||||
"Enter your SendPulse client credentials": "Enter your SendPulse client credentials",
|
||||
"Add Subscriber": "Add Subscriber",
|
||||
"Change Variable for Subscriber": "Change Variable for Subscriber",
|
||||
"Delete Contact": "Delete Contact",
|
||||
"Unsubscribe User": "Unsubscribe User",
|
||||
"Update Subscriber": "Update Subscriber",
|
||||
"Custom API Call": "Custom API Call",
|
||||
"Add subscriber to mailing list": "Add subscriber to mailing list",
|
||||
"Update subscriber variable": "Update subscriber variable",
|
||||
"Permanently delete contact from all mailing lists": "Permanently delete contact from all mailing lists",
|
||||
"Remove subscribers from mailing list": "Remove subscribers from mailing list",
|
||||
"Update subscriber details and variables": "Update subscriber details and variables",
|
||||
"Make a custom API call to a specific endpoint": "Make a custom API call to a specific endpoint",
|
||||
"Mailing List": "Mailing List",
|
||||
"Email Address": "Email Address",
|
||||
"Variables": "Variables",
|
||||
"Tag IDs": "Tag IDs",
|
||||
"Variable Name": "Variable Name",
|
||||
"Variable Value": "Variable Value",
|
||||
"Email Addresses": "Email Addresses",
|
||||
"Phone Number": "Phone Number",
|
||||
"Method": "Method",
|
||||
"Headers": "Headers",
|
||||
"Query Parameters": "Query Parameters",
|
||||
"Body": "Body",
|
||||
"Response is Binary ?": "Response is Binary ?",
|
||||
"No Error on Failure": "No Error on Failure",
|
||||
"Timeout (in seconds)": "Timeout (in seconds)",
|
||||
"Select one of your SendPulse mailing lists": "Select one of your SendPulse mailing lists",
|
||||
"Subscriber email address": "Subscriber email address",
|
||||
"Optional subscriber variables (e.g., name, phone)": "Optional subscriber variables (e.g., name, phone)",
|
||||
"Optional tag IDs to assign": "Optional tag IDs to assign",
|
||||
"Select variable to update": "Select variable to update",
|
||||
"New value for the variable": "New value for the variable",
|
||||
"Email address to delete from all mailing lists": "Email address to delete from all mailing lists",
|
||||
"Email addresses to unsubscribe (max 100)": "Email addresses to unsubscribe (max 100)",
|
||||
"Email address of the subscriber to update": "Email address of the subscriber to update",
|
||||
"New phone number (optional)": "New phone number (optional)",
|
||||
"Subscriber variables to update (e.g., name, custom fields)": "Subscriber variables to update (e.g., name, custom fields)",
|
||||
"Authorization headers are injected automatically from your connection.": "Authorization headers are injected automatically from your connection.",
|
||||
"Enable for files like PDFs, images, etc..": "Enable for files like PDFs, images, etc..",
|
||||
"GET": "GET",
|
||||
"POST": "POST",
|
||||
"PATCH": "PATCH",
|
||||
"PUT": "PUT",
|
||||
"DELETE": "DELETE",
|
||||
"HEAD": "HEAD",
|
||||
"New Subscriber": "New Subscriber",
|
||||
"New Unsubscriber": "New Unsubscriber",
|
||||
"Updated Subscriber": "Updated Subscriber",
|
||||
"Fires when new subscriber is added": "Fires when new subscriber is added",
|
||||
"Fires when subscriber unsubscribes": "Fires when subscriber unsubscribes",
|
||||
"Fires when subscriber details change (polling)": "Fires when subscriber details change (polling)"
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
{
|
||||
"SendPulse": "SendPulse",
|
||||
"Client ID": "Client ID",
|
||||
"Client Secret": "Client Secret",
|
||||
"Enter your SendPulse client credentials": "Enter your SendPulse client credentials",
|
||||
"Add Subscriber": "Add Subscriber",
|
||||
"Change Variable for Subscriber": "Change Variable for Subscriber",
|
||||
"Delete Contact": "Delete Contact",
|
||||
"Unsubscribe User": "Unsubscribe User",
|
||||
"Update Subscriber": "Update Subscriber",
|
||||
"Custom API Call": "Custom API Call",
|
||||
"Add subscriber to mailing list": "Add subscriber to mailing list",
|
||||
"Update subscriber variable": "Update subscriber variable",
|
||||
"Permanently delete contact from all mailing lists": "Permanently delete contact from all mailing lists",
|
||||
"Remove subscribers from mailing list": "Remove subscribers from mailing list",
|
||||
"Update subscriber details and variables": "Update subscriber details and variables",
|
||||
"Make a custom API call to a specific endpoint": "Make a custom API call to a specific endpoint",
|
||||
"Mailing List": "Mailing List",
|
||||
"Email Address": "Email Address",
|
||||
"Variables": "Variables",
|
||||
"Tag IDs": "Tag IDs",
|
||||
"Variable Name": "Variable Name",
|
||||
"Variable Value": "Variable Value",
|
||||
"Email Addresses": "Email Addresses",
|
||||
"Phone Number": "Phone Number",
|
||||
"Method": "Method",
|
||||
"Headers": "Headers",
|
||||
"Query Parameters": "Query Parameters",
|
||||
"Body": "Body",
|
||||
"No Error on Failure": "No Error on Failure",
|
||||
"Timeout (in seconds)": "Timeout (in seconds)",
|
||||
"Select one of your SendPulse mailing lists": "Select one of your SendPulse mailing lists",
|
||||
"Subscriber email address": "Subscriber email address",
|
||||
"Optional subscriber variables (e.g., name, phone)": "Optional subscriber variables (e.g., name, phone)",
|
||||
"Optional tag IDs to assign": "Optional tag IDs to assign",
|
||||
"Select variable to update": "Select variable to update",
|
||||
"New value for the variable": "New value for the variable",
|
||||
"Email address to delete from all mailing lists": "Email address to delete from all mailing lists",
|
||||
"Email addresses to unsubscribe (max 100)": "Email addresses to unsubscribe (max 100)",
|
||||
"Email address of the subscriber to update": "Email address of the subscriber to update",
|
||||
"New phone number (optional)": "New phone number (optional)",
|
||||
"Subscriber variables to update (e.g., name, custom fields)": "Subscriber variables to update (e.g., name, custom fields)",
|
||||
"Authorization headers are injected automatically from your connection.": "Authorization headers are injected automatically from your connection.",
|
||||
"GET": "GET",
|
||||
"POST": "POST",
|
||||
"PATCH": "PATCH",
|
||||
"PUT": "PUT",
|
||||
"DELETE": "DELETE",
|
||||
"HEAD": "HEAD",
|
||||
"New Subscriber": "New Subscriber",
|
||||
"New Unsubscriber": "New Unsubscriber",
|
||||
"Updated Subscriber": "Updated Subscriber",
|
||||
"Fires when new subscriber is added": "Fires when new subscriber is added",
|
||||
"Fires when subscriber unsubscribes": "Fires when subscriber unsubscribes",
|
||||
"Fires when subscriber details change (polling)": "Fires when subscriber details change (polling)"
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
{
|
||||
"Client ID": "客户端ID",
|
||||
"Client Secret": "客户端密钥",
|
||||
"Enter your SendPulse client credentials": "Enter your SendPulse client credentials",
|
||||
"Add Subscriber": "Add Subscriber",
|
||||
"Change Variable for Subscriber": "Change Variable for Subscriber",
|
||||
"Delete Contact": "Delete Contact",
|
||||
"Unsubscribe User": "Unsubscribe User",
|
||||
"Update Subscriber": "Update Subscriber",
|
||||
"Custom API Call": "自定义 API 呼叫",
|
||||
"Add subscriber to mailing list": "Add subscriber to mailing list",
|
||||
"Update subscriber variable": "Update subscriber variable",
|
||||
"Permanently delete contact from all mailing lists": "Permanently delete contact from all mailing lists",
|
||||
"Remove subscribers from mailing list": "Remove subscribers from mailing list",
|
||||
"Update subscriber details and variables": "Update subscriber details and variables",
|
||||
"Make a custom API call to a specific endpoint": "将一个自定义 API 调用到一个特定的终点",
|
||||
"Mailing List": "Mailing List",
|
||||
"Email Address": "Email Address",
|
||||
"Variables": "Variables",
|
||||
"Tag IDs": "Tag IDs",
|
||||
"Variable Name": "Variable Name",
|
||||
"Variable Value": "Variable Value",
|
||||
"Email Addresses": "Email Addresses",
|
||||
"Phone Number": "Phone Number",
|
||||
"Method": "方法",
|
||||
"Headers": "信头",
|
||||
"Query Parameters": "查询参数",
|
||||
"Body": "正文内容",
|
||||
"Response is Binary ?": "Response is Binary ?",
|
||||
"No Error on Failure": "失败时没有错误",
|
||||
"Timeout (in seconds)": "超时(秒)",
|
||||
"Select one of your SendPulse mailing lists": "Select one of your SendPulse mailing lists",
|
||||
"Subscriber email address": "Subscriber email address",
|
||||
"Optional subscriber variables (e.g., name, phone)": "Optional subscriber variables (e.g., name, phone)",
|
||||
"Optional tag IDs to assign": "Optional tag IDs to assign",
|
||||
"Select variable to update": "Select variable to update",
|
||||
"New value for the variable": "New value for the variable",
|
||||
"Email address to delete from all mailing lists": "Email address to delete from all mailing lists",
|
||||
"Email addresses to unsubscribe (max 100)": "Email addresses to unsubscribe (max 100)",
|
||||
"Email address of the subscriber to update": "Email address of the subscriber to update",
|
||||
"New phone number (optional)": "New phone number (optional)",
|
||||
"Subscriber variables to update (e.g., name, custom fields)": "Subscriber variables to update (e.g., name, custom fields)",
|
||||
"Authorization headers are injected automatically from your connection.": "授权头自动从您的连接中注入。",
|
||||
"Enable for files like PDFs, images, etc..": "Enable for files like PDFs, images, etc..",
|
||||
"GET": "获取",
|
||||
"POST": "帖子",
|
||||
"PATCH": "PATCH",
|
||||
"PUT": "弹出",
|
||||
"DELETE": "删除",
|
||||
"HEAD": "黑色",
|
||||
"New Subscriber": "New Subscriber",
|
||||
"New Unsubscriber": "New Unsubscriber",
|
||||
"Updated Subscriber": "Updated Subscriber",
|
||||
"Fires when new subscriber is added": "Fires when new subscriber is added",
|
||||
"Fires when subscriber unsubscribes": "Fires when subscriber unsubscribes",
|
||||
"Fires when subscriber details change (polling)": "Fires when subscriber details change (polling)"
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
import {
|
||||
createCustomApiCallAction,
|
||||
HttpMethod,
|
||||
} from '@activepieces/pieces-common';
|
||||
import { createPiece } from '@activepieces/pieces-framework';
|
||||
import { sendpulseAuth } from './lib/common/auth';
|
||||
import { sendpulseApiCall } from './lib/common/client';
|
||||
import { newSubscriberTrigger } from './lib/triggers/new-subscriber';
|
||||
import { newUnsubscriberTrigger } from './lib/triggers/new-unsubscriber';
|
||||
import { updatedSubscriberTrigger } from './lib/triggers/updated-subscriber';
|
||||
import { addSubscriberAction } from './lib/actions/add-subscriber';
|
||||
import { changeVariableForSubscriberAction } from './lib/actions/change-variable-for-subscriber';
|
||||
import { deleteContactAction } from './lib/actions/delete-contact';
|
||||
import { unsubscribeUserAction } from './lib/actions/unsubscribe-user';
|
||||
import { updateSubscriberAction } from './lib/actions/update-subscriber';
|
||||
|
||||
export const sendpulse = createPiece({
|
||||
displayName: 'SendPulse',
|
||||
auth: sendpulseAuth,
|
||||
minimumSupportedRelease: '0.36.1',
|
||||
logoUrl: 'https://cdn.activepieces.com/pieces/sendpulse.png',
|
||||
authors: ['aryel780', 'onyedikachi-david'],
|
||||
actions: [
|
||||
addSubscriberAction,
|
||||
changeVariableForSubscriberAction,
|
||||
deleteContactAction,
|
||||
unsubscribeUserAction,
|
||||
updateSubscriberAction,
|
||||
createCustomApiCallAction({
|
||||
auth: sendpulseAuth,
|
||||
baseUrl: () => 'https://api.sendpulse.com',
|
||||
authMapping: async (auth) => {
|
||||
const typedAuth = auth.props;
|
||||
const token = await sendpulseApiCall<{ access_token: string }>({
|
||||
method: HttpMethod.POST,
|
||||
auth: typedAuth,
|
||||
resourceUri: '/oauth/access_token',
|
||||
body: {
|
||||
grant_type: 'client_credentials',
|
||||
client_id: typedAuth.clientId,
|
||||
client_secret: typedAuth.clientSecret,
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
Authorization: `Bearer ${token.access_token}`,
|
||||
};
|
||||
},
|
||||
}),
|
||||
],
|
||||
triggers: [
|
||||
newSubscriberTrigger,
|
||||
newUnsubscriberTrigger,
|
||||
updatedSubscriberTrigger
|
||||
],
|
||||
});
|
||||
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
import { HttpMethod } from '@activepieces/pieces-common';
|
||||
import { createAction, Property } from '@activepieces/pieces-framework';
|
||||
import { sendpulseApiCall } from '../common/client';
|
||||
import { sendpulseAuth } from '../common/auth';
|
||||
import { mailingListDropdown } from '../common/props';
|
||||
|
||||
export const addSubscriberAction = createAction({
|
||||
auth: sendpulseAuth,
|
||||
name: 'add-subscriber',
|
||||
displayName: 'Add Subscriber',
|
||||
description: 'Add subscriber to mailing list',
|
||||
props: {
|
||||
mailingListId: mailingListDropdown,
|
||||
email: Property.ShortText({
|
||||
displayName: 'Email Address',
|
||||
description: 'Subscriber email address',
|
||||
required: true,
|
||||
}),
|
||||
variables: Property.Object({
|
||||
displayName: 'Variables',
|
||||
description: 'Optional subscriber variables (e.g., name, phone)',
|
||||
required: false,
|
||||
}),
|
||||
tags: Property.Array({
|
||||
displayName: 'Tag IDs',
|
||||
description: 'Optional tag IDs to assign',
|
||||
required: false,
|
||||
}),
|
||||
},
|
||||
|
||||
async run(context) {
|
||||
const { mailingListId, email, variables, tags } = context.propsValue;
|
||||
|
||||
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||
if (!emailRegex.test(email)) {
|
||||
throw new Error(`Invalid email format: ${email}`);
|
||||
}
|
||||
|
||||
const emailObject: any = { email };
|
||||
if (variables && Object.keys(variables).length > 0) {
|
||||
emailObject.variables = variables;
|
||||
}
|
||||
|
||||
const requestBody: any = {
|
||||
emails: [emailObject],
|
||||
};
|
||||
|
||||
if (tags && tags.length > 0) {
|
||||
const tagNumbers = tags.map((tag) => {
|
||||
const num = Number(tag);
|
||||
if (isNaN(num)) {
|
||||
throw new Error(`Invalid tag ID: ${tag}. Tag IDs must be numbers.`);
|
||||
}
|
||||
return num;
|
||||
});
|
||||
requestBody.tags = tagNumbers;
|
||||
}
|
||||
|
||||
try {
|
||||
const result = await sendpulseApiCall<{ result: boolean }>({
|
||||
method: HttpMethod.POST,
|
||||
auth: context.auth.props,
|
||||
resourceUri: `/addressbooks/${mailingListId}/emails`,
|
||||
body: requestBody,
|
||||
});
|
||||
|
||||
if (result.result === true) {
|
||||
return {
|
||||
success: true,
|
||||
message: 'Subscriber added successfully',
|
||||
email,
|
||||
variables: variables || {},
|
||||
mailingListId,
|
||||
tags: requestBody.tags || [],
|
||||
};
|
||||
}
|
||||
|
||||
throw new Error('SendPulse API returned failure');
|
||||
} catch (error: any) {
|
||||
throw new Error(`Failed to add subscriber: ${error.message || 'Unknown error'}`);
|
||||
}
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,152 @@
|
||||
import { HttpMethod } from '@activepieces/pieces-common';
|
||||
import { createAction, Property } from '@activepieces/pieces-framework';
|
||||
import { sendpulseAuth } from '../common/auth';
|
||||
import { sendpulseApiCall } from '../common/client';
|
||||
import { mailingListDropdown } from '../common/props';
|
||||
|
||||
type SendpulseVariable = {
|
||||
name: string;
|
||||
type: string;
|
||||
};
|
||||
|
||||
const variableDropdown = Property.Dropdown({
|
||||
auth: sendpulseAuth,
|
||||
displayName: 'Variable Name',
|
||||
description: 'Select variable to update',
|
||||
required: true,
|
||||
refreshers: ['mailingListId'],
|
||||
options: async ({ auth, mailingListId }) => {
|
||||
if (!auth || !mailingListId) {
|
||||
return {
|
||||
disabled: true,
|
||||
options: [],
|
||||
placeholder: 'Please select a mailing list first',
|
||||
};
|
||||
}
|
||||
|
||||
try {
|
||||
const variables = await sendpulseApiCall<SendpulseVariable[]>({
|
||||
auth: auth as any,
|
||||
method: HttpMethod.GET,
|
||||
resourceUri: `/addressbooks/${mailingListId}/variables`,
|
||||
});
|
||||
|
||||
if (!variables.length) {
|
||||
return {
|
||||
disabled: true,
|
||||
options: [],
|
||||
placeholder: 'No variables found in this mailing list',
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
disabled: false,
|
||||
options: variables
|
||||
.filter(variable => variable.name !== 'email')
|
||||
.map((variable) => ({
|
||||
label: `${variable.name} (${variable.type})`,
|
||||
value: variable.name,
|
||||
})),
|
||||
};
|
||||
} catch (error: any) {
|
||||
return {
|
||||
disabled: true,
|
||||
options: [],
|
||||
placeholder: `Failed to load variables: ${error.message}`,
|
||||
};
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
export const changeVariableForSubscriberAction = createAction({
|
||||
auth: sendpulseAuth,
|
||||
name: 'change-variable-for-subscriber',
|
||||
displayName: 'Change Variable for Subscriber',
|
||||
description: 'Update subscriber variable',
|
||||
props: {
|
||||
mailingListId: mailingListDropdown,
|
||||
email: Property.ShortText({
|
||||
displayName: 'Email Address',
|
||||
description: 'Subscriber email address',
|
||||
required: true,
|
||||
}),
|
||||
variableName: variableDropdown,
|
||||
variableValue: Property.ShortText({
|
||||
displayName: 'Variable Value',
|
||||
description: 'New value for the variable',
|
||||
required: true,
|
||||
}),
|
||||
},
|
||||
|
||||
async run(context) {
|
||||
const { mailingListId, email, variableName, variableValue } = context.propsValue;
|
||||
|
||||
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||
if (!emailRegex.test(email)) {
|
||||
throw new Error(`Invalid email format: ${email}`);
|
||||
}
|
||||
|
||||
let variableType: string | null = null;
|
||||
try {
|
||||
const variables = await sendpulseApiCall<SendpulseVariable[]>({
|
||||
auth: context.auth.props,
|
||||
method: HttpMethod.GET,
|
||||
resourceUri: `/addressbooks/${mailingListId}/variables`,
|
||||
});
|
||||
|
||||
const variable = variables.find(v => v.name === variableName);
|
||||
if (variable) {
|
||||
variableType = variable.type;
|
||||
}
|
||||
} catch (error) {
|
||||
// Continue without type validation if variable fetch fails
|
||||
}
|
||||
|
||||
if (variableType) {
|
||||
if (variableType === 'number' && isNaN(Number(variableValue))) {
|
||||
throw new Error(`Variable "${variableName}" expects a number, but got: ${variableValue}`);
|
||||
}
|
||||
|
||||
if (variableType === 'date') {
|
||||
const dateRegex = /^\d{4}-\d{2}-\d{2}$/;
|
||||
if (!dateRegex.test(variableValue) && !Date.parse(variableValue)) {
|
||||
throw new Error(`Variable "${variableName}" expects a date format (YYYY-MM-DD), but got: ${variableValue}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const body = {
|
||||
email,
|
||||
variables: [
|
||||
{
|
||||
name: variableName,
|
||||
value: variableValue,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
try {
|
||||
const result = await sendpulseApiCall<{ result: boolean }>({
|
||||
method: HttpMethod.POST,
|
||||
auth: context.auth.props,
|
||||
resourceUri: `/addressbooks/${mailingListId}/emails/variable`,
|
||||
body,
|
||||
});
|
||||
|
||||
if (result.result) {
|
||||
return {
|
||||
success: true,
|
||||
message: `Variable "${variableName}" updated for ${email}`,
|
||||
email,
|
||||
variableName,
|
||||
variableValue,
|
||||
variableType,
|
||||
};
|
||||
} else {
|
||||
throw new Error('SendPulse API returned failure');
|
||||
}
|
||||
} catch (error: any) {
|
||||
throw new Error(`Failed to update variable: ${error.message || 'Unknown error'}`);
|
||||
}
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,47 @@
|
||||
import { HttpMethod } from '@activepieces/pieces-common';
|
||||
import { createAction, Property } from '@activepieces/pieces-framework';
|
||||
import { sendpulseApiCall } from '../common/client';
|
||||
import { sendpulseAuth } from '../common/auth';
|
||||
|
||||
export const deleteContactAction = createAction({
|
||||
auth: sendpulseAuth,
|
||||
name: 'delete-contact',
|
||||
displayName: 'Delete Contact',
|
||||
description: 'Permanently delete contact from all mailing lists',
|
||||
props: {
|
||||
email: Property.ShortText({
|
||||
displayName: 'Email Address',
|
||||
description: 'Email address to delete from all mailing lists',
|
||||
required: true,
|
||||
}),
|
||||
},
|
||||
|
||||
async run(context) {
|
||||
const { email } = context.propsValue;
|
||||
|
||||
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||
if (!emailRegex.test(email)) {
|
||||
throw new Error(`Invalid email format: ${email}`);
|
||||
}
|
||||
|
||||
try {
|
||||
const result = await sendpulseApiCall<{ result: boolean }>({
|
||||
method: HttpMethod.DELETE,
|
||||
auth: context.auth.props,
|
||||
resourceUri: `/emails/${encodeURIComponent(email)}`,
|
||||
});
|
||||
|
||||
if (result.result) {
|
||||
return {
|
||||
success: true,
|
||||
message: `Contact ${email} deleted from all mailing lists`,
|
||||
email,
|
||||
};
|
||||
}
|
||||
|
||||
throw new Error('SendPulse API returned failure');
|
||||
} catch (error: any) {
|
||||
throw new Error(`Failed to delete contact: ${error.message || 'Unknown error'}`);
|
||||
}
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,64 @@
|
||||
import { HttpMethod } from '@activepieces/pieces-common';
|
||||
import { createAction, Property } from '@activepieces/pieces-framework';
|
||||
import { sendpulseApiCall } from '../common/client';
|
||||
import { sendpulseAuth } from '../common/auth';
|
||||
import { mailingListDropdown } from '../common/props';
|
||||
|
||||
export const unsubscribeUserAction = createAction({
|
||||
auth: sendpulseAuth,
|
||||
name: 'unsubscribe-user',
|
||||
displayName: 'Unsubscribe User',
|
||||
description: 'Remove subscribers from mailing list',
|
||||
props: {
|
||||
mailingListId: mailingListDropdown,
|
||||
emails: Property.Array({
|
||||
displayName: 'Email Addresses',
|
||||
description: 'Email addresses to unsubscribe (max 100)',
|
||||
required: true,
|
||||
}),
|
||||
},
|
||||
|
||||
async run(context) {
|
||||
const { mailingListId, emails } = context.propsValue;
|
||||
|
||||
if (emails.length === 0) {
|
||||
throw new Error('At least one email address is required');
|
||||
}
|
||||
|
||||
if (emails.length > 100) {
|
||||
throw new Error('Maximum 100 email addresses allowed per request');
|
||||
}
|
||||
|
||||
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||
const invalidEmails = emails.filter(email => !emailRegex.test(email as string));
|
||||
|
||||
if (invalidEmails.length > 0) {
|
||||
throw new Error(`Invalid email format(s): ${invalidEmails.join(', ')}`);
|
||||
}
|
||||
|
||||
const body = { emails };
|
||||
|
||||
try {
|
||||
const result = await sendpulseApiCall<{ result: boolean }>({
|
||||
method: HttpMethod.DELETE,
|
||||
auth: context.auth.props,
|
||||
resourceUri: `/addressbooks/${mailingListId}/emails`,
|
||||
body,
|
||||
});
|
||||
|
||||
if (result.result) {
|
||||
return {
|
||||
success: true,
|
||||
message: `${emails.length} subscriber(s) unsubscribed successfully`,
|
||||
unsubscribed: emails,
|
||||
mailingListId,
|
||||
count: emails.length,
|
||||
};
|
||||
} else {
|
||||
throw new Error('Unsubscription failed - API returned failure');
|
||||
}
|
||||
} catch (error: any) {
|
||||
throw new Error(`Failed to unsubscribe users: ${error.message || 'Unknown error'}`);
|
||||
}
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,101 @@
|
||||
import { HttpMethod } from '@activepieces/pieces-common';
|
||||
import { createAction, Property } from '@activepieces/pieces-framework';
|
||||
import { sendpulseApiCall } from '../common/client';
|
||||
import { sendpulseAuth } from '../common/auth';
|
||||
import { mailingListDropdown } from '../common/props';
|
||||
|
||||
export const updateSubscriberAction = createAction({
|
||||
auth: sendpulseAuth,
|
||||
name: 'update-subscriber',
|
||||
displayName: 'Update Subscriber',
|
||||
description: 'Update subscriber details and variables',
|
||||
props: {
|
||||
mailingListId: mailingListDropdown,
|
||||
email: Property.ShortText({
|
||||
displayName: 'Email Address',
|
||||
description: 'Email address of the subscriber to update',
|
||||
required: true,
|
||||
}),
|
||||
phone: Property.ShortText({
|
||||
displayName: 'Phone Number',
|
||||
description: 'New phone number (optional)',
|
||||
required: false,
|
||||
}),
|
||||
variables: Property.Object({
|
||||
displayName: 'Variables',
|
||||
description: 'Subscriber variables to update (e.g., name, custom fields)',
|
||||
required: false,
|
||||
}),
|
||||
},
|
||||
|
||||
async run(context) {
|
||||
const { mailingListId, email, phone, variables } = context.propsValue;
|
||||
|
||||
const results: any[] = [];
|
||||
let hasUpdates = false;
|
||||
|
||||
if (phone) {
|
||||
try {
|
||||
const phoneResult = await sendpulseApiCall<{ result: boolean }>({
|
||||
method: HttpMethod.PUT,
|
||||
auth: context.auth.props,
|
||||
resourceUri: `/addressbooks/${mailingListId}/phone`,
|
||||
body: { email, phone },
|
||||
});
|
||||
|
||||
if (phoneResult.result) {
|
||||
results.push({ type: 'phone', success: true, value: phone });
|
||||
hasUpdates = true;
|
||||
} else {
|
||||
results.push({ type: 'phone', success: false, error: 'API returned failure' });
|
||||
}
|
||||
} catch (error: any) {
|
||||
results.push({ type: 'phone', success: false, error: error.message });
|
||||
}
|
||||
}
|
||||
|
||||
if (variables && Object.keys(variables).length > 0) {
|
||||
const variableUpdates = Object.entries(variables).map(([name, value]) => ({
|
||||
name,
|
||||
value: String(value),
|
||||
}));
|
||||
|
||||
try {
|
||||
const variableResult = await sendpulseApiCall<{ result: boolean }>({
|
||||
method: HttpMethod.POST,
|
||||
auth: context.auth.props,
|
||||
resourceUri: `/addressbooks/${mailingListId}/emails/variable`,
|
||||
body: { email, variables: variableUpdates },
|
||||
});
|
||||
|
||||
if (variableResult.result) {
|
||||
results.push({ type: 'variables', success: true, count: variableUpdates.length });
|
||||
hasUpdates = true;
|
||||
} else {
|
||||
results.push({ type: 'variables', success: false, error: 'API returned failure' });
|
||||
}
|
||||
} catch (error: any) {
|
||||
results.push({ type: 'variables', success: false, error: error.message });
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasUpdates && !phone && (!variables || Object.keys(variables).length === 0)) {
|
||||
throw new Error('No updates provided. Please specify phone number or variables to update.');
|
||||
}
|
||||
|
||||
const successfulUpdates = results.filter(r => r.success);
|
||||
const failedUpdates = results.filter(r => !r.success);
|
||||
|
||||
if (successfulUpdates.length === 0) {
|
||||
throw new Error(`All updates failed: ${failedUpdates.map(f => f.error).join(', ')}`);
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
message: `Subscriber ${email} updated successfully`,
|
||||
email,
|
||||
updates: results,
|
||||
hasFailures: failedUpdates.length > 0,
|
||||
};
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,33 @@
|
||||
import { PieceAuth } from '@activepieces/pieces-framework';
|
||||
import { sendpulseApiCall } from './client';
|
||||
import { HttpMethod } from '@activepieces/pieces-common';
|
||||
|
||||
export const sendpulseAuth = PieceAuth.CustomAuth({
|
||||
description: 'Enter your SendPulse client credentials',
|
||||
props: {
|
||||
clientId: PieceAuth.SecretText({
|
||||
displayName: 'Client ID',
|
||||
required: true,
|
||||
}),
|
||||
clientSecret: PieceAuth.SecretText({
|
||||
displayName: 'Client Secret',
|
||||
required: true,
|
||||
}),
|
||||
},
|
||||
validate: async ({ auth }) => {
|
||||
try {
|
||||
await sendpulseApiCall({
|
||||
method: HttpMethod.GET,
|
||||
resourceUri: '/addressbooks',
|
||||
auth,
|
||||
});
|
||||
return { valid: true };
|
||||
} catch {
|
||||
return {
|
||||
valid: false,
|
||||
error: 'Invalid Client ID or Client Secret',
|
||||
};
|
||||
}
|
||||
},
|
||||
required: true,
|
||||
});
|
||||
@@ -0,0 +1,89 @@
|
||||
import {
|
||||
httpClient,
|
||||
HttpMethod,
|
||||
HttpRequest,
|
||||
HttpMessageBody,
|
||||
QueryParams,
|
||||
} from '@activepieces/pieces-common';
|
||||
|
||||
export type SendPulseAuthProps = {
|
||||
clientId: string;
|
||||
clientSecret: string;
|
||||
};
|
||||
|
||||
let cachedToken: string | null = null;
|
||||
let tokenExpiresAt = 0;
|
||||
|
||||
async function getAccessToken(auth: SendPulseAuthProps): Promise<string> {
|
||||
if (cachedToken && Date.now() < tokenExpiresAt) {
|
||||
return cachedToken;
|
||||
}
|
||||
|
||||
const response = await httpClient.sendRequest<{
|
||||
access_token: string;
|
||||
expires_in: number;
|
||||
}>({
|
||||
method: HttpMethod.POST,
|
||||
url: 'https://api.sendpulse.com/oauth/access_token',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: {
|
||||
grant_type: 'client_credentials',
|
||||
client_id: auth.clientId,
|
||||
client_secret: auth.clientSecret,
|
||||
},
|
||||
});
|
||||
|
||||
cachedToken = response.body.access_token;
|
||||
tokenExpiresAt = Date.now() + response.body.expires_in * 1000 - 30 * 1000;
|
||||
return cachedToken!;
|
||||
}
|
||||
|
||||
export type SendPulseApiCallParams = {
|
||||
method: HttpMethod;
|
||||
resourceUri: string;
|
||||
query?: Record<string, string | number | string[] | undefined>;
|
||||
body?: any;
|
||||
auth: SendPulseAuthProps;
|
||||
};
|
||||
|
||||
export async function sendpulseApiCall<T extends HttpMessageBody>({
|
||||
method,
|
||||
resourceUri,
|
||||
query,
|
||||
body,
|
||||
auth,
|
||||
}: SendPulseApiCallParams): Promise<T> {
|
||||
const token = await getAccessToken(auth);
|
||||
|
||||
const queryParams: QueryParams = {};
|
||||
if (query) {
|
||||
for (const [key, value] of Object.entries(query)) {
|
||||
if (value !== null && value !== undefined) {
|
||||
queryParams[key] = String(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const request: HttpRequest = {
|
||||
method,
|
||||
url: `https://api.sendpulse.com${resourceUri}`,
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
queryParams,
|
||||
body,
|
||||
};
|
||||
|
||||
try {
|
||||
const response = await httpClient.sendRequest<T>(request);
|
||||
return response.body;
|
||||
} catch (error: any) {
|
||||
const statusCode = error.response?.status;
|
||||
const errorMessage = error.response?.data?.message || error.message || 'Unknown error';
|
||||
|
||||
throw new Error(`SendPulse API Error (${statusCode || 'Unknown'}): ${errorMessage}`);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
import { Property } from '@activepieces/pieces-framework';
|
||||
import { HttpMethod } from '@activepieces/pieces-common';
|
||||
import { sendpulseApiCall } from './client';
|
||||
import { sendpulseAuth } from './auth';
|
||||
|
||||
type SendpulseMailingList = {
|
||||
id: number;
|
||||
name: string;
|
||||
status_explain: string;
|
||||
};
|
||||
|
||||
export const mailingListDropdown = Property.Dropdown({
|
||||
auth: sendpulseAuth,
|
||||
displayName: 'Mailing List',
|
||||
description: 'Select one of your SendPulse mailing lists',
|
||||
required: true,
|
||||
refreshers: [],
|
||||
options: async ({ auth }) => {
|
||||
if (!auth) {
|
||||
return {
|
||||
disabled: true,
|
||||
options: [],
|
||||
placeholder: 'Please connect your SendPulse account.',
|
||||
};
|
||||
}
|
||||
const typedAuth = auth.props
|
||||
|
||||
try {
|
||||
const lists = await sendpulseApiCall<SendpulseMailingList[]>({
|
||||
auth: auth.props,
|
||||
method: HttpMethod.GET,
|
||||
resourceUri: '/addressbooks?limit=100&offset=0',
|
||||
});
|
||||
|
||||
if (!lists.length) {
|
||||
return {
|
||||
disabled: true,
|
||||
options: [],
|
||||
placeholder: 'No mailing lists found in your account.',
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
disabled: false,
|
||||
options: lists.map((list) => ({
|
||||
label: `${list.name} (${list.status_explain})`,
|
||||
value: list.id,
|
||||
})),
|
||||
};
|
||||
} catch (error: any) {
|
||||
return {
|
||||
disabled: true,
|
||||
options: [],
|
||||
placeholder: `Failed to load mailing lists: ${error.message}`,
|
||||
};
|
||||
}
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,131 @@
|
||||
import {
|
||||
createTrigger,
|
||||
TriggerStrategy,
|
||||
WebhookResponse,
|
||||
} from '@activepieces/pieces-framework';
|
||||
import { sendpulseAuth } from '../common/auth';
|
||||
import { sendpulseApiCall } from '../common/client';
|
||||
import { mailingListDropdown } from '../common/props';
|
||||
import { HttpMethod } from '@activepieces/pieces-common';
|
||||
|
||||
export const newSubscriberTrigger = createTrigger({
|
||||
auth: sendpulseAuth,
|
||||
name: 'new_subscriber',
|
||||
displayName: 'New Subscriber',
|
||||
description: 'Fires when new subscriber is added',
|
||||
type: TriggerStrategy.WEBHOOK,
|
||||
props: {
|
||||
mailingListId: mailingListDropdown,
|
||||
},
|
||||
|
||||
async onEnable(context) {
|
||||
const { mailingListId } = context.propsValue;
|
||||
|
||||
try {
|
||||
const webhookResponse = await sendpulseApiCall<{
|
||||
success: boolean;
|
||||
data: Array<{ id: number; action: string; url: string }>;
|
||||
}>({
|
||||
method: HttpMethod.POST,
|
||||
auth: context.auth.props,
|
||||
resourceUri: '/v2/email-service/webhook',
|
||||
body: {
|
||||
url: context.webhookUrl,
|
||||
actions: ['new_emails'],
|
||||
},
|
||||
});
|
||||
|
||||
if (webhookResponse.success && webhookResponse.data?.length > 0) {
|
||||
const webhook = webhookResponse.data.find(w => w.action === 'new_emails');
|
||||
if (webhook) {
|
||||
await context.store.put('webhook_id', webhook.id);
|
||||
await context.store.put('mailing_list_id', mailingListId);
|
||||
}
|
||||
} else {
|
||||
throw new Error('Failed to create webhook');
|
||||
}
|
||||
} catch (error: any) {
|
||||
throw new Error(`Failed to enable new subscriber trigger: ${error.message}`);
|
||||
}
|
||||
},
|
||||
|
||||
async onDisable(context) {
|
||||
try {
|
||||
const webhookId = await context.store.get('webhook_id');
|
||||
|
||||
if (webhookId) {
|
||||
await sendpulseApiCall({
|
||||
method: HttpMethod.DELETE,
|
||||
auth: context.auth.props,
|
||||
resourceUri: `/v2/email-service/webhook/${webhookId}`,
|
||||
});
|
||||
|
||||
await context.store.delete('webhook_id');
|
||||
await context.store.delete('mailing_list_id');
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('Failed to delete webhook during disable:', error);
|
||||
}
|
||||
},
|
||||
|
||||
async run(context) {
|
||||
const storedListId = await context.store.get('mailing_list_id');
|
||||
|
||||
interface NewSubscriberPayload {
|
||||
timestamp: string;
|
||||
variables: any[];
|
||||
email: string;
|
||||
source: string;
|
||||
book_id: string;
|
||||
event: string;
|
||||
}
|
||||
|
||||
const payload = context.payload.body as NewSubscriberPayload | NewSubscriberPayload[];
|
||||
|
||||
const payloads = Array.isArray(payload) ? payload : [payload];
|
||||
|
||||
const results = [];
|
||||
|
||||
for (const item of payloads) {
|
||||
if (item.event === 'new_emails' && item.book_id === storedListId) {
|
||||
results.push({
|
||||
id: `${item.email}_${item.timestamp}`,
|
||||
email: item.email,
|
||||
mailingListId: item.book_id,
|
||||
source: item.source,
|
||||
variables: item.variables || {},
|
||||
addedAt: new Date(parseInt(item.timestamp) * 1000).toISOString(),
|
||||
timestamp: item.timestamp,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
},
|
||||
|
||||
async test() {
|
||||
return [
|
||||
{
|
||||
id: 'demo@example.com_1496827625',
|
||||
email: 'demo@example.com',
|
||||
mailingListId: '123456',
|
||||
source: 'address book',
|
||||
variables: {},
|
||||
addedAt: new Date().toISOString(),
|
||||
timestamp: '1496827625',
|
||||
},
|
||||
];
|
||||
},
|
||||
|
||||
sampleData: {
|
||||
id: 'subscriber@example.com_1496827625',
|
||||
email: 'subscriber@example.com',
|
||||
mailingListId: '123456',
|
||||
source: 'subscription form',
|
||||
variables: {
|
||||
name: 'John Doe',
|
||||
},
|
||||
addedAt: '2023-06-01T12:00:00.000Z',
|
||||
timestamp: '1496827625',
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,137 @@
|
||||
import {
|
||||
createTrigger,
|
||||
TriggerStrategy,
|
||||
WebhookResponse,
|
||||
} from '@activepieces/pieces-framework';
|
||||
import { sendpulseAuth } from '../common/auth';
|
||||
import { sendpulseApiCall } from '../common/client';
|
||||
import { mailingListDropdown } from '../common/props';
|
||||
import { HttpMethod } from '@activepieces/pieces-common';
|
||||
|
||||
export const newUnsubscriberTrigger = createTrigger({
|
||||
auth: sendpulseAuth,
|
||||
name: 'new_unsubscriber',
|
||||
displayName: 'New Unsubscriber',
|
||||
description: 'Fires when subscriber unsubscribes',
|
||||
type: TriggerStrategy.WEBHOOK,
|
||||
props: {
|
||||
mailingListId: mailingListDropdown,
|
||||
},
|
||||
|
||||
async onEnable(context) {
|
||||
const { mailingListId } = context.propsValue;
|
||||
|
||||
try {
|
||||
const webhookResponse = await sendpulseApiCall<{
|
||||
success: boolean;
|
||||
data: Array<{ id: number; action: string; url: string }>;
|
||||
}>({
|
||||
method: HttpMethod.POST,
|
||||
auth: context.auth.props,
|
||||
resourceUri: '/v2/email-service/webhook',
|
||||
body: {
|
||||
url: context.webhookUrl,
|
||||
actions: ['unsubscribe'],
|
||||
},
|
||||
});
|
||||
|
||||
if (webhookResponse.success && webhookResponse.data?.length > 0) {
|
||||
const webhook = webhookResponse.data.find(w => w.action === 'unsubscribe');
|
||||
if (webhook) {
|
||||
await context.store.put('webhook_id', webhook.id);
|
||||
await context.store.put('mailing_list_id', mailingListId);
|
||||
}
|
||||
} else {
|
||||
throw new Error('Failed to create webhook');
|
||||
}
|
||||
} catch (error: any) {
|
||||
throw new Error(`Failed to enable unsubscriber trigger: ${error.message}`);
|
||||
}
|
||||
},
|
||||
|
||||
async onDisable(context) {
|
||||
try {
|
||||
const webhookId = await context.store.get('webhook_id');
|
||||
|
||||
if (webhookId) {
|
||||
await sendpulseApiCall({
|
||||
method: HttpMethod.DELETE,
|
||||
auth: context.auth.props,
|
||||
resourceUri: `/v2/email-service/webhook/${webhookId}`,
|
||||
});
|
||||
|
||||
await context.store.delete('webhook_id');
|
||||
await context.store.delete('mailing_list_id');
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('Failed to delete webhook during disable:', error);
|
||||
}
|
||||
},
|
||||
|
||||
async run(context) {
|
||||
const storedListId = await context.store.get('mailing_list_id');
|
||||
|
||||
interface UnsubscribePayload {
|
||||
task_id: string;
|
||||
timestamp: string;
|
||||
from_all: string;
|
||||
email: string;
|
||||
reason: string | null;
|
||||
book_id: string;
|
||||
event: string;
|
||||
categories: string;
|
||||
}
|
||||
|
||||
const payload = context.payload.body as UnsubscribePayload | UnsubscribePayload[];
|
||||
|
||||
const payloads = Array.isArray(payload) ? payload : [payload];
|
||||
|
||||
const results = [];
|
||||
|
||||
for (const item of payloads) {
|
||||
if (item.event === 'unsubscribe' && item.book_id === storedListId) {
|
||||
results.push({
|
||||
id: `${item.email}_${item.timestamp}`,
|
||||
email: item.email,
|
||||
mailingListId: item.book_id,
|
||||
taskId: item.task_id,
|
||||
fromAll: item.from_all === '1',
|
||||
reason: item.reason || 'No reason provided',
|
||||
categories: item.categories || '',
|
||||
unsubscribedAt: new Date(parseInt(item.timestamp) * 1000).toISOString(),
|
||||
timestamp: item.timestamp,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
},
|
||||
|
||||
async test() {
|
||||
return [
|
||||
{
|
||||
id: 'test-unsubscribe@example.com_1496827872',
|
||||
email: 'test-unsubscribe@example.com',
|
||||
mailingListId: '123456',
|
||||
taskId: '3668141',
|
||||
fromAll: true,
|
||||
reason: 'User clicked unsubscribe link',
|
||||
categories: '',
|
||||
unsubscribedAt: new Date().toISOString(),
|
||||
timestamp: '1496827872',
|
||||
},
|
||||
];
|
||||
},
|
||||
|
||||
sampleData: {
|
||||
id: 'unsub@example.com_1496827872',
|
||||
email: 'unsub@example.com',
|
||||
mailingListId: '123456',
|
||||
taskId: '3668141',
|
||||
fromAll: false,
|
||||
reason: 'Manual unsubscribe',
|
||||
categories: 'newsletter',
|
||||
unsubscribedAt: '2023-06-01T12:30:00.000Z',
|
||||
timestamp: '1496827872',
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,151 @@
|
||||
import {
|
||||
createTrigger,
|
||||
TriggerStrategy,
|
||||
} from '@activepieces/pieces-framework';
|
||||
import { sendpulseAuth } from '../common/auth';
|
||||
import { sendpulseApiCall } from '../common/client';
|
||||
import { mailingListDropdown } from '../common/props';
|
||||
import { HttpMethod } from '@activepieces/pieces-common';
|
||||
|
||||
function detectChanges(previous: any, current: any): Record<string, { from: any; to: any }> {
|
||||
const changes: Record<string, { from: any; to: any }> = {};
|
||||
|
||||
const allKeys = new Set([...Object.keys(previous), ...Object.keys(current)]);
|
||||
|
||||
for (const key of allKeys) {
|
||||
if (JSON.stringify(previous[key]) !== JSON.stringify(current[key])) {
|
||||
changes[key] = {
|
||||
from: previous[key],
|
||||
to: current[key],
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return changes;
|
||||
}
|
||||
|
||||
export const updatedSubscriberTrigger = createTrigger({
|
||||
auth: sendpulseAuth,
|
||||
name: 'updated_subscriber',
|
||||
displayName: 'Updated Subscriber',
|
||||
description: 'Fires when subscriber details change (polling)',
|
||||
type: TriggerStrategy.POLLING,
|
||||
props: {
|
||||
mailingListId: mailingListDropdown,
|
||||
},
|
||||
|
||||
async onEnable(context) {
|
||||
await context.store.put('mailing_list_id', String(context.propsValue.mailingListId));
|
||||
await context.store.put('last_check', Date.now().toString());
|
||||
},
|
||||
|
||||
async onDisable(context) {
|
||||
await context.store.delete('mailing_list_id');
|
||||
await context.store.delete('last_check');
|
||||
await context.store.delete('subscribers_cache');
|
||||
},
|
||||
|
||||
async run(context) {
|
||||
const mailingListId = await context.store.get('mailing_list_id');
|
||||
|
||||
if (!mailingListId) {
|
||||
return [];
|
||||
}
|
||||
|
||||
try {
|
||||
const currentSubscribers = await sendpulseApiCall<any[]>({
|
||||
method: HttpMethod.GET,
|
||||
auth: context.auth.props,
|
||||
resourceUri: `/addressbooks/${mailingListId}/emails`,
|
||||
});
|
||||
|
||||
const cachedSubscribers = await context.store.get('subscribers_cache');
|
||||
|
||||
if (!cachedSubscribers) {
|
||||
await context.store.put('subscribers_cache', JSON.stringify(currentSubscribers));
|
||||
return [];
|
||||
}
|
||||
|
||||
const previousSubscribers = JSON.parse(cachedSubscribers as string);
|
||||
const changes = [];
|
||||
|
||||
for (const current of currentSubscribers) {
|
||||
const previous = previousSubscribers.find((p: any) => p.email === current.email);
|
||||
|
||||
if (previous) {
|
||||
const hasChanges = JSON.stringify(current) !== JSON.stringify(previous);
|
||||
|
||||
if (hasChanges) {
|
||||
changes.push({
|
||||
id: `${current.email}_${Date.now()}`,
|
||||
email: current.email,
|
||||
mailingListId,
|
||||
previousData: previous,
|
||||
currentData: current,
|
||||
updatedAt: new Date().toISOString(),
|
||||
changes: detectChanges(previous, current),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await context.store.put('subscribers_cache', JSON.stringify(currentSubscribers));
|
||||
await context.store.put('last_check', Date.now().toString());
|
||||
|
||||
return changes;
|
||||
} catch (error: any) {
|
||||
console.error('Error checking for subscriber updates:', error);
|
||||
return [];
|
||||
}
|
||||
},
|
||||
|
||||
async test() {
|
||||
return [
|
||||
{
|
||||
id: 'test-updated@example.com_1234567890',
|
||||
email: 'test-updated@example.com',
|
||||
mailingListId: '123456',
|
||||
previousData: {
|
||||
email: 'test-updated@example.com',
|
||||
variables: { name: 'Old Name' },
|
||||
},
|
||||
currentData: {
|
||||
email: 'test-updated@example.com',
|
||||
variables: { name: 'New Name' },
|
||||
},
|
||||
updatedAt: new Date().toISOString(),
|
||||
changes: {
|
||||
'variables.name': {
|
||||
from: 'Old Name',
|
||||
to: 'New Name',
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
},
|
||||
|
||||
sampleData: {
|
||||
id: 'updated-user@example.com_1234567890',
|
||||
email: 'updated-user@example.com',
|
||||
mailingListId: '123456',
|
||||
previousData: {
|
||||
email: 'updated-user@example.com',
|
||||
variables: { phone: '+1234567890', name: 'John' },
|
||||
},
|
||||
currentData: {
|
||||
email: 'updated-user@example.com',
|
||||
variables: { phone: '+0987654321', name: 'John Updated' },
|
||||
},
|
||||
updatedAt: '2023-06-01T12:30:00.000Z',
|
||||
changes: {
|
||||
'variables.phone': {
|
||||
from: '+1234567890',
|
||||
to: '+0987654321',
|
||||
},
|
||||
'variables.name': {
|
||||
from: 'John',
|
||||
to: 'John Updated',
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "../../../../dist/out-tsc",
|
||||
"declaration": true,
|
||||
"types": ["node"]
|
||||
},
|
||||
"include": ["src/**/*.ts"]
|
||||
}
|
||||
Reference in New Issue
Block a user