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,63 @@
{
"Identifier": "Identifier",
"Key": "Schlüssel",
"\n\n1.Go to the [Crisp Marketplace](https://marketplace.crisp.chat/);\n2.Sign in or create an account (this account is different from your main Crisp account);\n3.Once logged-in, go to Plugins and click on the New Plugin button;\n4.Select the plugin type, in this case Private;\n5.Give your plugin a name, eg. \"Integration\", and hit Create;\n6.On the plugin page, go to Tokens and scroll down to Production;\n7.Click on \"Ask a production token\", and pick the scopes you require;\n - website:conversation:messages website": "\n\n1.Gehe zum [Crisp Marketplace](https://marketplace.crisp.chat/);\n2. Melden Sie sich an oder erstellen Sie ein Konto (dieses Konto unterscheidet sich von Ihrem Hauptkonto bei Crisp);\n3. nce eingeloggt, gehen Sie zu Plugins und klicken Sie auf die Schaltfläche Neues Plugins;\n4. Wählen Sie den Plugin-Typ, in diesem Fall Private;\n5.Geben Sie Ihrem Plugin einen Namen, zB. \"Integration\", und klicken Sie auf Erstellen;\n6.Auf der Plugin-Seite gehen Sie zu Token und scrollen nach unten zu Production;\n7. Klicken Sie auf \"Fragen Sie einen Produktions-Token\" und wählen Sie die Bereiche aus, die Sie benötigen;\n - website:conversation:messages website:conversation:sessions website:people:profile\n8. Klicken Sie auf \"Produktions-Token anfordern\";\n(warten Sie, dass Ihre Einreichung genehmigt wird, dies kann einige Minuten dauern);\n9. nce akzeptiert, komm zurück zu Token und kopiere deine Produktionstoken Tastatur (konfiguriere sie sicher in deinem Integrationscode);\n10. installiere das Plugin auf allen Webseiten, für die du es verwenden möchtest (über den privaten Installations-Link, angegeben im Abschnitt Einstellungen unter Gefahrenzone / Sichtbarkeit);\n",
"Add Note to Conversation": "Notiz zur Unterhaltung hinzufügen",
"Create Conversation": "Unterhaltung erstellen",
"Create/Update Contact": "Kontakt erstellen/aktualisieren",
"Change Conversation State": "Konversationsstatus ändern",
"Find Conversation": "Unterhaltung finden",
"Find User Profile": "Nutzerprofil finden",
"Custom API Call": "Eigener API-Aufruf",
"Adds an internal note to a conversation.": "Fügt eine interne Notiz zu einer Unterhaltung hinzu.",
"Creates a new conversation.": "Erstellt eine neue Unterhaltung.",
"Creates a new contact or updates an existing contact.": "Erstellt einen neuen Kontakt oder aktualisiert einen bestehenden Kontakt.",
"Updates the state of a conversation.": "Aktualisiert den Status einer Unterhaltung.",
"Searches for conversations matching the specified criteria.": "Sucht nach Unterhaltungen, die den angegebenen Kriterien entsprechen.",
"Finds a user profile by email address.": "Findet ein Benutzerprofil per E-Mail-Adresse.",
"Make a custom API call to a specific endpoint": "Einen benutzerdefinierten API-Aufruf an einen bestimmten Endpunkt machen",
"Website ID": "Website-ID",
"Conversation ID (session_id)": "Konversationsnummer (session_id)",
"Note Content": "Notiz Inhalt",
"Customer Email": "Kunden-E-Mail",
"Customer Username": "Kunden-Benutzername",
"Message From": "Nachricht von",
"Message": "Nachricht",
"Email": "E-Mail",
"Name": "Name",
"Phone Number": "Telefonnummer",
"Address": "Adresse",
"Company": "Firma",
"Contact Website": "Website kontaktieren",
"Notepad": "Notizblock",
"State": "Bundesland",
"Search Query": "Suchanfrage",
"Email Address": "E-Mail-Adresse",
"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)",
"You can obtain website ID by navigating to Settings -> Workspace Settings -> Setup & Integrations.": "Sie können die Website-ID unter Einstellungen -> Workspace Einstellungen -> Setup & Integrations abrufen.",
"You can obtain session from URL address bar.It starts with 'session_'.": "Sie können die Session über die URL Adresse bar.Es beginnt mit 'session_'.",
"The email address of the user to find.": "Die E-Mail-Adresse des zu findenden Benutzers.",
"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..",
"User": "Benutzer",
"Operator": "Operator",
"Unresolved": "Unerledigt",
"Resolved": "Gelöst",
"Pending": "Ausstehend",
"GET": "ERHALTEN",
"POST": "POST",
"PATCH": "PATCH",
"PUT": "PUT",
"DELETE": "LÖSCHEN",
"HEAD": "HEAD",
"New Contact Created": "Neuer Kontakt erstellt",
"New Conversation Created": "Neue Unterhaltung erstellt",
"Triggers when a new contact is added.": "Wird ausgelöst, wenn ein neuer Kontakt hinzugefügt wird.",
"Triggers when a new conversation is started.": "Wird ausgelöst, wenn eine neue Unterhaltung gestartet wird."
}

View File

@@ -0,0 +1,63 @@
{
"Identifier": "Identifier",
"Key": "Clave",
"\n\n1.Go to the [Crisp Marketplace](https://marketplace.crisp.chat/);\n2.Sign in or create an account (this account is different from your main Crisp account);\n3.Once logged-in, go to Plugins and click on the New Plugin button;\n4.Select the plugin type, in this case Private;\n5.Give your plugin a name, eg. \"Integration\", and hit Create;\n6.On the plugin page, go to Tokens and scroll down to Production;\n7.Click on \"Ask a production token\", and pick the scopes you require;\n - website:conversation:messages website": "\n\n1.Go to the [Crisp Marketplace](https://marketplace.crisp.chat/);\n2.Sign in or create an account (this account is different from your main Crisp account);\n3.Once logged-in, go to Plugins and click on the New Plugin button;\n4.Select the plugin type, in this case Private;\n5.Give your plugin a name, eg. \"Integration\", and hit Create;\n6.On the plugin page, go to Tokens and scroll down to Production;\n7.Click on \"Ask a production token\", and pick the scopes you require;\n - website:conversation:messages website:conversation:sessions website:people:profiles\n8.Click on \"Request production token\";\n(wait that your submission gets approved, this can take a few minutes);\n9.Once accepted, come back to Tokens, and copy your Production token keypair (configure it securely in your integration code);\n10.Finally, install the plugin on all websites you need to use it for (using the private install link, provided in the Settings section under Danger Zone / Visibility);\n",
"Add Note to Conversation": "Añadir nota a la conversación",
"Create Conversation": "Crear conversación",
"Create/Update Contact": "Crear/Actualizar contacto",
"Change Conversation State": "Cambiar estado de conversación",
"Find Conversation": "Encontrar conversación",
"Find User Profile": "Buscar perfil de usuario",
"Custom API Call": "Llamada API personalizada",
"Adds an internal note to a conversation.": "Añade una nota interna a una conversación.",
"Creates a new conversation.": "Crea una nueva conversación.",
"Creates a new contact or updates an existing contact.": "Crea un nuevo contacto o actualiza un contacto existente.",
"Updates the state of a conversation.": "Actualiza el estado de una conversación.",
"Searches for conversations matching the specified criteria.": "Busca conversaciones que coincidan con los criterios especificados.",
"Finds a user profile by email address.": "Encuentra un perfil de usuario por dirección de correo electrónico.",
"Make a custom API call to a specific endpoint": "Hacer una llamada API personalizada a un extremo específico",
"Website ID": "ID del sitio web",
"Conversation ID (session_id)": "ID de conversación (sesión_id)",
"Note Content": "Contenido de Nota",
"Customer Email": "Email del cliente",
"Customer Username": "Usuario del cliente",
"Message From": "Mensaje de",
"Message": "Mensaje",
"Email": "E-mail",
"Name": "Nombre",
"Phone Number": "Número de teléfono",
"Address": "Dirección",
"Company": "Empresa",
"Contact Website": "Sitio web de contacto",
"Notepad": "Bloc de notas",
"State": "Estado",
"Search Query": "Buscar consulta",
"Email Address": "Dirección de email",
"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)",
"You can obtain website ID by navigating to Settings -> Workspace Settings -> Setup & Integrations.": "Puede obtener el ID del sitio web navegando a Ajustes -> Configuración del espacio de trabajo -> Configuración e Integraciones.",
"You can obtain session from URL address bar.It starts with 'session_'.": "Puedes obtener la sesión de la barra de direcciones URL. Empieza con 'session_'.",
"The email address of the user to find.": "La dirección de correo electrónico del usuario a encontrar.",
"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.",
"User": "Usuario",
"Operator": "Operador",
"Unresolved": "Sin resolver",
"Resolved": "Resuelto",
"Pending": "Pendiente",
"GET": "RECOGER",
"POST": "POST",
"PATCH": "PATCH",
"PUT": "PUT",
"DELETE": "BORRAR",
"HEAD": "LIMPIO",
"New Contact Created": "Nuevo contacto creado",
"New Conversation Created": "Nueva conversación creada",
"Triggers when a new contact is added.": "Se activa cuando se añade un nuevo contacto.",
"Triggers when a new conversation is started.": "Dispara cuando se inicia una nueva conversación."
}

View File

@@ -0,0 +1,63 @@
{
"Identifier": "Identifier",
"Key": "Clés",
"\n\n1.Go to the [Crisp Marketplace](https://marketplace.crisp.chat/);\n2.Sign in or create an account (this account is different from your main Crisp account);\n3.Once logged-in, go to Plugins and click on the New Plugin button;\n4.Select the plugin type, in this case Private;\n5.Give your plugin a name, eg. \"Integration\", and hit Create;\n6.On the plugin page, go to Tokens and scroll down to Production;\n7.Click on \"Ask a production token\", and pick the scopes you require;\n - website:conversation:messages website": "\n\n1.Go to the [Crisp Marketplace](https://marketplace.crisp.chat/);\n2.Sign in or create an account (this account is different from your main Crisp account);\n3.Once logged-in, go to Plugins and click on the New Plugin button;\n4.Select the plugin type, in this case Private;\n5.Give your plugin a name, eg. \"Integration\", and hit Create;\n6.On the plugin page, go to Tokens and scroll down to Production;\n7.Click on \"Ask a production token\", and pick the scopes you require;\n - website:conversation:messages website:conversation:sessions website:people:profiles\n8.Click on \"Request production token\";\n(wait that your submission gets approved, this can take a few minutes);\n9.Once accepted, come back to Tokens, and copy your Production token keypair (configure it securely in your integration code);\n10.Finally, install the plugin on all websites you need to use it for (using the private install link, provided in the Settings section under Danger Zone / Visibility);\n",
"Add Note to Conversation": "Ajouter une note à la conversation",
"Create Conversation": "Créer une conversation",
"Create/Update Contact": "Créer/mettre à jour le contact",
"Change Conversation State": "Changer l'état de la conversation",
"Find Conversation": "Trouver une conversation",
"Find User Profile": "Trouver le profil utilisateur",
"Custom API Call": "Appel API personnalisé",
"Adds an internal note to a conversation.": "Ajoute une note interne à une conversation.",
"Creates a new conversation.": "Crée une nouvelle conversation.",
"Creates a new contact or updates an existing contact.": "Crée un nouveau contact ou met à jour un contact existant.",
"Updates the state of a conversation.": "Met à jour l'état d'une conversation.",
"Searches for conversations matching the specified criteria.": "Recherche des conversations correspondant aux critères spécifiés.",
"Finds a user profile by email address.": "Trouve un profil utilisateur par adresse e-mail.",
"Make a custom API call to a specific endpoint": "Passez un appel API personnalisé à un point de terminaison spécifique",
"Website ID": "ID du site web",
"Conversation ID (session_id)": "ID de la conversation (session_id)",
"Note Content": "Contenu de la note",
"Customer Email": "E-mail du client",
"Customer Username": "Nom d'utilisateur du client",
"Message From": "Message de",
"Message": "Message",
"Email": "Courriel",
"Name": "Nom",
"Phone Number": "Numéro de téléphone",
"Address": "Adresses",
"Company": "Entreprise",
"Contact Website": "Site Web du contact",
"Notepad": "Bloc-notes",
"State": "État",
"Search Query": "Requête de recherche",
"Email Address": "Adresse e-mail",
"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'attente (en secondes)",
"You can obtain website ID by navigating to Settings -> Workspace Settings -> Setup & Integrations.": "Vous pouvez obtenir l'ID du site Web en accédant à Paramètres -> Paramètres de l'espace de travail -> Configuration et intégrations.",
"You can obtain session from URL address bar.It starts with 'session_'.": "Vous pouvez obtenir une session à partir de la barre d'adresse d'URL. Il commence par 'session_'.",
"The email address of the user to find.": "L'adresse email de l'utilisateur à trouver.",
"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.",
"User": "Utilisateur",
"Operator": "Opérateur",
"Unresolved": "Non résolu",
"Resolved": "Résolu",
"Pending": "En attente",
"GET": "OBTENIR",
"POST": "POSTER",
"PATCH": "PATCH",
"PUT": "EFFACER",
"DELETE": "SUPPRIMER",
"HEAD": "TÊTE",
"New Contact Created": "Nouveau contact créé",
"New Conversation Created": "Nouvelle conversation créée",
"Triggers when a new contact is added.": "Déclenche lorsqu'un nouveau contact est ajouté.",
"Triggers when a new conversation is started.": "Déclenche quand une nouvelle conversation est démarrée."
}

View File

@@ -0,0 +1,63 @@
{
"Identifier": "Identifier",
"Key": "キー",
"\n\n1.Go to the [Crisp Marketplace](https://marketplace.crisp.chat/);\n2.Sign in or create an account (this account is different from your main Crisp account);\n3.Once logged-in, go to Plugins and click on the New Plugin button;\n4.Select the plugin type, in this case Private;\n5.Give your plugin a name, eg. \"Integration\", and hit Create;\n6.On the plugin page, go to Tokens and scroll down to Production;\n7.Click on \"Ask a production token\", and pick the scopes you require;\n - website:conversation:messages website": "\n\n1.Go to the [Crisp Marketplace](https://marketplace.crisp.chat/);\n2.Sign in or create an account (this account is different from your main Crisp account);\n3.Once logged-in, go to Plugins and click on the New Plugin button;\n4.Select the plugin type, in this case Private;\n5.Give your plugin a name, eg. \"Integration\", and hit Create;\n6.On the plugin page, go to Tokens and scroll down to Production;\n7.Click on \"Ask a production token\", and pick the scopes you require;\n - website:conversation:messages website:conversation:sessions website:people:profiles\n8.Click on \"Request production token\";\n(wait that your submission gets approved, this can take a few minutes);\n9.Once accepted, come back to Tokens, and copy your Production token keypair (configure it securely in your integration code);\n10.Finally, install the plugin on all websites you need to use it for (using the private install link, provided in the Settings section under Danger Zone / Visibility);\n",
"Add Note to Conversation": "会話にメモを追加",
"Create Conversation": "会話を作成",
"Create/Update Contact": "連絡先の作成/更新",
"Change Conversation State": "会話の状態を変更",
"Find Conversation": "会話を検索",
"Find User Profile": "ユーザープロファイルを検索",
"Custom API Call": "カスタムAPI通話",
"Adds an internal note to a conversation.": "会話に内部メモを追加します。",
"Creates a new conversation.": "新しい会話を作成します。",
"Creates a new contact or updates an existing contact.": "新しい連絡先を作成するか、既存の連絡先を更新します。",
"Updates the state of a conversation.": "会話の状態を更新します。",
"Searches for conversations matching the specified criteria.": "指定された条件に一致する会話を検索します。",
"Finds a user profile by email address.": "メールアドレスでユーザープロファイルを検索します。",
"Make a custom API call to a specific endpoint": "特定のエンドポイントへのカスタム API コールを実行します。",
"Website ID": "ウェブサイト ID",
"Conversation ID (session_id)": "会話 ID (session_id)",
"Note Content": "ノートコンテンツ",
"Customer Email": "顧客のメールアドレス",
"Customer Username": "顧客のユーザー名",
"Message From": "メッセージ送信元",
"Message": "メッセージ",
"Email": "Eメールアドレス",
"Name": "Name",
"Phone Number": "電話番号",
"Address": "住所",
"Company": "会社名",
"Contact Website": "ウェブサイトに連絡",
"Notepad": "ノート",
"State": "都道府県:",
"Search Query": "検索クエリ",
"Email Address": "メールアドレス",
"Method": "方法",
"Headers": "ヘッダー",
"Query Parameters": "クエリパラメータ",
"Body": "本文",
"Response is Binary ?": "応答はバイナリですか?",
"No Error on Failure": "失敗時にエラーはありません",
"Timeout (in seconds)": "タイムアウト(秒)",
"You can obtain website ID by navigating to Settings -> Workspace Settings -> Setup & Integrations.": "ウェブサイトIDは、「設定」→「ワークスペース設定」→「セットアップ&インテグレーション」に移動して取得できます。",
"You can obtain session from URL address bar.It starts with 'session_'.": "URLアドレスバーからセッションを取得できます。session_で始まります。",
"The email address of the user to find.": "検索するユーザーのメールアドレス",
"Authorization headers are injected automatically from your connection.": "認証ヘッダは接続から自動的に注入されます。",
"Enable for files like PDFs, images, etc..": "PDF、画像などのファイルを有効にします。",
"User": "ユーザー",
"Operator": "演算子",
"Unresolved": "未解決です",
"Resolved": "解決済み",
"Pending": "処理待ち",
"GET": "取得",
"POST": "POST",
"PATCH": "PATCH",
"PUT": "PUT",
"DELETE": "削除",
"HEAD": "頭",
"New Contact Created": "新しい連絡先が作成されました",
"New Conversation Created": "新しい会話が作成されました",
"Triggers when a new contact is added.": "新しい連絡先が追加されたときにトリガーします。",
"Triggers when a new conversation is started.": "新しい会話が開始されたときにトリガーします。"
}

View File

@@ -0,0 +1,63 @@
{
"Identifier": "Identifier",
"Key": "Sleutel",
"\n\n1.Go to the [Crisp Marketplace](https://marketplace.crisp.chat/);\n2.Sign in or create an account (this account is different from your main Crisp account);\n3.Once logged-in, go to Plugins and click on the New Plugin button;\n4.Select the plugin type, in this case Private;\n5.Give your plugin a name, eg. \"Integration\", and hit Create;\n6.On the plugin page, go to Tokens and scroll down to Production;\n7.Click on \"Ask a production token\", and pick the scopes you require;\n - website:conversation:messages website": "\n\n1. Ga naar de [Crisp Marktplaats](https://marketplace.crisp.chat/);\n2. Meld je aan of maak een account aan (dit account is anders dan je hoofdaccount van Crisp account);\n3. nce ingelogd, ga naar Plugins en klik op de nieuwe Plugin knop;\n4. selecteer het plugin type, in dit geval Privé;\n5.Geef je plugin een naam, bijv. \"Integratie\", en druk op Aanmaken;\n6.Op de plugin pagina, ga naar Tokens en scroll naar beneden naar Productie;\n7. Klik op \"Vraag een productie token\", en kies de toepassingsgebieden die u wilt;\n - website:conversation:message website:conversation:sessions website:people:profiles\n8. Klik op \"Vraag productie token\";\n(wacht tot je inzending wordt goedgekeurd, dit kan enkele minuten duren);\n9. nce geaccepteerd, kom terug naar Tokens en kopieer je Productie token sleutelpaar (configureer het veilig in je integratiecode);\n10. installeer de plugin op alle websites waar je deze voor moet gebruiken (gebruik makend van de private installatie link, verstrekt in de Instellingen sectie onder Gevaar Zone / Zichtbaarheid);\n",
"Add Note to Conversation": "Notitie toevoegen aan gesprek",
"Create Conversation": "Gesprek aanmaken",
"Create/Update Contact": "Contactpersoon maken/bijwerken",
"Change Conversation State": "Gesprek status wijzigen",
"Find Conversation": "Gesprek zoeken",
"Find User Profile": "Vind gebruikersprofiel",
"Custom API Call": "Custom API Call",
"Adds an internal note to a conversation.": "Voegt een interne notitie toe aan een gesprek.",
"Creates a new conversation.": "Maakt een nieuw gesprek aan.",
"Creates a new contact or updates an existing contact.": "Maakt een nieuw contact of werkt een bestaand contact bij.",
"Updates the state of a conversation.": "Werk de status van een gesprek bij.",
"Searches for conversations matching the specified criteria.": "Zoekt naar gesprekken die aan de opgegeven criteria voldoen.",
"Finds a user profile by email address.": "Vindt een gebruikersprofiel op e-mailadres",
"Make a custom API call to a specific endpoint": "Maak een aangepaste API call naar een specifiek eindpunt",
"Website ID": "Website ID",
"Conversation ID (session_id)": "Gesprek ID (session_id)",
"Note Content": "Notitie inhoud",
"Customer Email": "Klant e-mail",
"Customer Username": "Klant gebruikersnaam",
"Message From": "Bericht van",
"Message": "bericht",
"Email": "E-mail",
"Name": "Naam",
"Phone Number": "Telefoon nummer",
"Address": "Adres:",
"Company": "Bedrijfsnaam",
"Contact Website": "Contact website",
"Notepad": "Kladblok",
"State": "Provincie",
"Search Query": "Zoek query",
"Email Address": "Uw e-mailadres",
"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)",
"You can obtain website ID by navigating to Settings -> Workspace Settings -> Setup & Integrations.": "Je kunt een website-ID verkrijgen door te navigeren naar Instellingen -> Workspace Instellingen-> Setup & Integraties.",
"You can obtain session from URL address bar.It starts with 'session_'.": "U kunt sessie verkrijgen via de balk met URL-adressen. Het begint met 'session_'.",
"The email address of the user to find.": "Het e-mailadres van de gebruiker om te vinden.",
"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..",
"User": "Gebruiker",
"Operator": "Operator",
"Unresolved": "Onopgelost",
"Resolved": "Opgelost",
"Pending": "In behandeling",
"GET": "KRIJG",
"POST": "POSTE",
"PATCH": "BEKIJK",
"PUT": "PUT",
"DELETE": "VERWIJDEREN",
"HEAD": "HOOFD",
"New Contact Created": "Nieuw contact aangemaakt",
"New Conversation Created": "Nieuwe conversatie aangemaakt",
"Triggers when a new contact is added.": "Triggert wanneer een nieuwe contactpersoon wordt toegevoegd.",
"Triggers when a new conversation is started.": "Triggert wanneer een nieuw gesprek begint."
}

View File

@@ -0,0 +1,63 @@
{
"Identifier": "Identifier",
"Key": "Chave",
"\n\n1.Go to the [Crisp Marketplace](https://marketplace.crisp.chat/);\n2.Sign in or create an account (this account is different from your main Crisp account);\n3.Once logged-in, go to Plugins and click on the New Plugin button;\n4.Select the plugin type, in this case Private;\n5.Give your plugin a name, eg. \"Integration\", and hit Create;\n6.On the plugin page, go to Tokens and scroll down to Production;\n7.Click on \"Ask a production token\", and pick the scopes you require;\n - website:conversation:messages website": "\n\n1.Go to the [Crisp Marketplace](https://marketplace.crisp.chat/);\n2.Sign in or create an account (this account is different from your main Crisp account);\n3.Once logged-in, go to Plugins and click on the New Plugin button;\n4.Select the plugin type, in this case Private;\n5.Give your plugin a name, eg. \"Integration\", and hit Create;\n6.On the plugin page, go to Tokens and scroll down to Production;\n7.Click on \"Ask a production token\", and pick the scopes you require;\n - website:conversation:messages website:conversation:sessions website:people:profiles\n8.Click on \"Request production token\";\n(wait that your submission gets approved, this can take a few minutes);\n9.Once accepted, come back to Tokens, and copy your Production token keypair (configure it securely in your integration code);\n10.Finally, install the plugin on all websites you need to use it for (using the private install link, provided in the Settings section under Danger Zone / Visibility);\n",
"Add Note to Conversation": "Adicionar Nota à Conversa",
"Create Conversation": "Criar conversa",
"Create/Update Contact": "Criar/atualizar contato",
"Change Conversation State": "Alterar Estado da Conversa",
"Find Conversation": "Localizar Conversa",
"Find User Profile": "Encontrar perfil de usuário",
"Custom API Call": "Chamada de API personalizada",
"Adds an internal note to a conversation.": "Adiciona uma nota interna a uma conversa.",
"Creates a new conversation.": "Cria uma nova conversa.",
"Creates a new contact or updates an existing contact.": "Cria um novo contato ou atualiza um contato existente.",
"Updates the state of a conversation.": "Atualiza o estado de uma conversa.",
"Searches for conversations matching the specified criteria.": "Procura conversas correspondentes aos critérios especificados.",
"Finds a user profile by email address.": "Localiza um perfil de usuário por endereço de e-mail.",
"Make a custom API call to a specific endpoint": "Faça uma chamada de API personalizada para um ponto de extremidade específico",
"Website ID": "ID do site",
"Conversation ID (session_id)": "ID da conversa (session_id)",
"Note Content": "Conteúdo da Nota",
"Customer Email": "E-mail do Cliente",
"Customer Username": "Usuário do Cliente",
"Message From": "Mensagem de",
"Message": "mensagem",
"Email": "e-mail",
"Name": "Nome",
"Phone Number": "Número de telefone",
"Address": "Endereço",
"Company": "Empresas",
"Contact Website": "Site de contato",
"Notepad": "Notas",
"State": "Estado:",
"Search Query": "Consulta de Pesquisa",
"Email Address": "Endereço de e-mail",
"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)",
"You can obtain website ID by navigating to Settings -> Workspace Settings -> Setup & Integrations.": "Você pode obter o ID do site navegando em Ajustes -> Configurações do Espaço de Trabalho -> Configuração e Integrações.",
"You can obtain session from URL address bar.It starts with 'session_'.": "Você pode obter a sessão na barra de endereços de URL. Ele começa com 'session_'.",
"The email address of the user to find.": "O endereço de e-mail do usuário a ser encontrado.",
"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..",
"User": "Usuário",
"Operator": "Operador",
"Unresolved": "Não resolvido",
"Resolved": "Resolvido",
"Pending": "Pendente",
"GET": "OBTER",
"POST": "POSTAR",
"PATCH": "COMPRAR",
"PUT": "COLOCAR",
"DELETE": "EXCLUIR",
"HEAD": "CABEÇA",
"New Contact Created": "Novo contato criado",
"New Conversation Created": "Nova conversa criada",
"Triggers when a new contact is added.": "Aciona quando um novo contato é adicionado.",
"Triggers when a new conversation is started.": "Dispara quando uma nova conversa é iniciada."
}

View File

@@ -0,0 +1,62 @@
{
"Crisp": "Хрустящий",
"Identifier": "Identifier",
"Key": "Спецификация",
"\n\n1.Go to the [Crisp Marketplace](https://marketplace.crisp.chat/);\n2.Sign in or create an account (this account is different from your main Crisp account);\n3.Once logged-in, go to Plugins and click on the New Plugin button;\n4.Select the plugin type, in this case Private;\n5.Give your plugin a name, eg. \"Integration\", and hit Create;\n6.On the plugin page, go to Tokens and scroll down to Production;\n7.Click on \"Ask a production token\", and pick the scopes you require;\n - website:conversation:messages website": "\n\n1.Go to the [Crisp Marketplace](https://marketplace.crisp.chat/);\n2.Sign in or create an account (this account is different from your main Crisp account);\n3.Once logged-in, go to Plugins and click on the New Plugin button;\n4.Select the plugin type, in this case Private;\n5.Give your plugin a name, eg. \"Integration\", and hit Create;\n6.On the plugin page, go to Tokens and scroll down to Production;\n7.Click on \"Ask a production token\", and pick the scopes you require;\n - website:conversation:messages website:conversation:sessions website:people:profiles\n8.Click on \"Request production token\";\n(wait that your submission gets approved, this can take a few minutes);\n9.Once accepted, come back to Tokens, and copy your Production token keypair (configure it securely in your integration code);\n10.Finally, install the plugin on all websites you need to use it for (using the private install link, provided in the Settings section under Danger Zone / Visibility);\n",
"Add Note to Conversation": "Добавить заметку в разговор",
"Create Conversation": "Создать диалог",
"Create/Update Contact": "Создать/Обновить контакт",
"Change Conversation State": "Изменить состояние разговора",
"Find Conversation": "Найти разговор",
"Find User Profile": "Найти профиль пользователя",
"Custom API Call": "Пользовательский вызов API",
"Adds an internal note to a conversation.": "Добавляет внутреннюю заметку к разговору.",
"Creates a new conversation.": "Создает новый диалог.",
"Creates a new contact or updates an existing contact.": "Создает новый контакт или обновляет существующий контакт.",
"Updates the state of a conversation.": "Обновляет состояние разговора.",
"Searches for conversations matching the specified criteria.": "Поиск диалогов, соответствующих заданным критериям.",
"Finds a user profile by email address.": "Находит профиль пользователя по адресу электронной почты.",
"Make a custom API call to a specific endpoint": "Сделать пользовательский API вызов к определенной конечной точке",
"Website ID": "ID веб-сайта",
"Conversation ID (session_id)": "ID разговора (session_id)",
"Note Content": "Содержание заметки",
"Customer Email": "Email клиента",
"Customer Username": "Имя пользователя",
"Message From": "Сообщение от",
"Message": "Сообщение",
"Email": "Почта",
"Name": "Наименование",
"Phone Number": "Номер телефона",
"Address": "Адрес",
"Company": "Компания",
"Contact Website": "Связаться с сайтом",
"Notepad": "Блокнот",
"State": "Область",
"Search Query": "Поисковый запрос",
"Email Address": "Email Address",
"Method": "Метод",
"Headers": "Заголовки",
"Query Parameters": "Параметры запроса",
"Body": "Тело",
"No Error on Failure": "Нет ошибок при ошибке",
"Timeout (in seconds)": "Таймаут (в секундах)",
"You can obtain website ID by navigating to Settings -> Workspace Settings -> Setup & Integrations.": "Вы можете получить идентификатор веб-сайта, перейдя в Настройки -> Настройки рабочего пространства -> Настройки и Интеграции.",
"You can obtain session from URL address bar.It starts with 'session_'.": "Вы можете получить сессию с адресной строки URL. Она начинается с 'session_'.",
"The email address of the user to find.": "Адрес электронной почты пользователя, который будет найден.",
"Authorization headers are injected automatically from your connection.": "Заголовки авторизации включаются автоматически из вашего соединения.",
"User": "Пользователь",
"Operator": "Оператор",
"Unresolved": "Нерешенные",
"Resolved": "Решена",
"Pending": "В ожидании",
"GET": "ПОЛУЧИТЬ",
"POST": "ПОСТ",
"PATCH": "ПАТЧ",
"PUT": "ПОКУПИТЬ",
"DELETE": "УДАЛИТЬ",
"HEAD": "HEAD",
"New Contact Created": "Создан новый контакт",
"New Conversation Created": "Создан новый диалог",
"Triggers when a new contact is added.": "Триггеры при добавлении нового контакта.",
"Triggers when a new conversation is started.": "Триггеры, когда начинается новая беседа."
}

View File

@@ -0,0 +1,63 @@
{
"Identifier": "Identifier",
"Key": "Key",
"\n\n1.Go to the [Crisp Marketplace](https://marketplace.crisp.chat/);\n2.Sign in or create an account (this account is different from your main Crisp account);\n3.Once logged-in, go to Plugins and click on the New Plugin button;\n4.Select the plugin type, in this case Private;\n5.Give your plugin a name, eg. \"Integration\", and hit Create;\n6.On the plugin page, go to Tokens and scroll down to Production;\n7.Click on \"Ask a production token\", and pick the scopes you require;\n - website:conversation:messages website": "\n\n1.Go to the [Crisp Marketplace](https://marketplace.crisp.chat/);\n2.Sign in or create an account (this account is different from your main Crisp account);\n3.Once logged-in, go to Plugins and click on the New Plugin button;\n4.Select the plugin type, in this case Private;\n5.Give your plugin a name, eg. \"Integration\", and hit Create;\n6.On the plugin page, go to Tokens and scroll down to Production;\n7.Click on \"Ask a production token\", and pick the scopes you require;\n - website:conversation:messages website:conversation:sessions website:people:profiles\n8.Click on \"Request production token\";\n(wait that your submission gets approved, this can take a few minutes);\n9.Once accepted, come back to Tokens, and copy your Production token keypair (configure it securely in your integration code);\n10.Finally, install the plugin on all websites you need to use it for (using the private install link, provided in the Settings section under Danger Zone / Visibility);\n",
"Add Note to Conversation": "Add Note to Conversation",
"Create Conversation": "Create Conversation",
"Create/Update Contact": "Create/Update Contact",
"Change Conversation State": "Change Conversation State",
"Find Conversation": "Find Conversation",
"Find User Profile": "Find User Profile",
"Custom API Call": "Custom API Call",
"Adds an internal note to a conversation.": "Adds an internal note to a conversation.",
"Creates a new conversation.": "Creates a new conversation.",
"Creates a new contact or updates an existing contact.": "Creates a new contact or updates an existing contact.",
"Updates the state of a conversation.": "Updates the state of a conversation.",
"Searches for conversations matching the specified criteria.": "Searches for conversations matching the specified criteria.",
"Finds a user profile by email address.": "Finds a user profile by email address.",
"Make a custom API call to a specific endpoint": "Make a custom API call to a specific endpoint",
"Website ID": "Website ID",
"Conversation ID (session_id)": "Conversation ID (session_id)",
"Note Content": "Note Content",
"Customer Email": "Customer Email",
"Customer Username": "Customer Username",
"Message From": "Message From",
"Message": "Message",
"Email": "Email",
"Name": "Name",
"Phone Number": "Phone Number",
"Address": "Address",
"Company": "Company",
"Contact Website": "Contact Website",
"Notepad": "Notepad",
"State": "State",
"Search Query": "Search Query",
"Email Address": "Email Address",
"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)",
"You can obtain website ID by navigating to Settings -> Workspace Settings -> Setup & Integrations.": "You can obtain website ID by navigating to Settings -> Workspace Settings -> Setup & Integrations.",
"You can obtain session from URL address bar.It starts with 'session_'.": "You can obtain session from URL address bar.It starts with 'session_'.",
"The email address of the user to find.": "The email address of the user to find.",
"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..",
"User": "User",
"Operator": "Operator",
"Unresolved": "Unresolved",
"Resolved": "Resolved",
"Pending": "Pending",
"GET": "GET",
"POST": "POST",
"PATCH": "PATCH",
"PUT": "PUT",
"DELETE": "DELETE",
"HEAD": "HEAD",
"New Contact Created": "New Contact Created",
"New Conversation Created": "New Conversation Created",
"Triggers when a new contact is added.": "Triggers when a new contact is added.",
"Triggers when a new conversation is started.": "Triggers when a new conversation is started."
}

View File

@@ -0,0 +1,62 @@
{
"Crisp": "Crisp",
"Identifier": "Identifier",
"Key": "Key",
"\n\n1.Go to the [Crisp Marketplace](https://marketplace.crisp.chat/);\n2.Sign in or create an account (this account is different from your main Crisp account);\n3.Once logged-in, go to Plugins and click on the New Plugin button;\n4.Select the plugin type, in this case Private;\n5.Give your plugin a name, eg. \"Integration\", and hit Create;\n6.On the plugin page, go to Tokens and scroll down to Production;\n7.Click on \"Ask a production token\", and pick the scopes you require;\n - website:conversation:messages website": "\n\n1.Go to the [Crisp Marketplace](https://marketplace.crisp.chat/);\n2.Sign in or create an account (this account is different from your main Crisp account);\n3.Once logged-in, go to Plugins and click on the New Plugin button;\n4.Select the plugin type, in this case Private;\n5.Give your plugin a name, eg. \"Integration\", and hit Create;\n6.On the plugin page, go to Tokens and scroll down to Production;\n7.Click on \"Ask a production token\", and pick the scopes you require;\n - website:conversation:messages website:conversation:sessions website:people:profiles\n8.Click on \"Request production token\";\n(wait that your submission gets approved, this can take a few minutes);\n9.Once accepted, come back to Tokens, and copy your Production token keypair (configure it securely in your integration code);\n10.Finally, install the plugin on all websites you need to use it for (using the private install link, provided in the Settings section under Danger Zone / Visibility);\n",
"Add Note to Conversation": "Add Note to Conversation",
"Create Conversation": "Create Conversation",
"Create/Update Contact": "Create/Update Contact",
"Change Conversation State": "Change Conversation State",
"Find Conversation": "Find Conversation",
"Find User Profile": "Find User Profile",
"Custom API Call": "Custom API Call",
"Adds an internal note to a conversation.": "Adds an internal note to a conversation.",
"Creates a new conversation.": "Creates a new conversation.",
"Creates a new contact or updates an existing contact.": "Creates a new contact or updates an existing contact.",
"Updates the state of a conversation.": "Updates the state of a conversation.",
"Searches for conversations matching the specified criteria.": "Searches for conversations matching the specified criteria.",
"Finds a user profile by email address.": "Finds a user profile by email address.",
"Make a custom API call to a specific endpoint": "Make a custom API call to a specific endpoint",
"Website ID": "Website ID",
"Conversation ID (session_id)": "Conversation ID (session_id)",
"Note Content": "Note Content",
"Customer Email": "Customer Email",
"Customer Username": "Customer Username",
"Message From": "Message From",
"Message": "Message",
"Email": "Email",
"Name": "Name",
"Phone Number": "Phone Number",
"Address": "Address",
"Company": "Company",
"Contact Website": "Contact Website",
"Notepad": "Notepad",
"State": "State",
"Search Query": "Search Query",
"Email Address": "Email Address",
"Method": "Method",
"Headers": "Headers",
"Query Parameters": "Query Parameters",
"Body": "Body",
"No Error on Failure": "No Error on Failure",
"Timeout (in seconds)": "Timeout (in seconds)",
"You can obtain website ID by navigating to Settings -> Workspace Settings -> Setup & Integrations.": "You can obtain website ID by navigating to Settings -> Workspace Settings -> Setup & Integrations.",
"You can obtain session from URL address bar.It starts with 'session_'.": "You can obtain session from URL address bar.It starts with 'session_'.",
"The email address of the user to find.": "The email address of the user to find.",
"Authorization headers are injected automatically from your connection.": "Authorization headers are injected automatically from your connection.",
"User": "User",
"Operator": "Operator",
"Unresolved": "Unresolved",
"Resolved": "Resolved",
"Pending": "Đang chờ",
"GET": "GET",
"POST": "POST",
"PATCH": "PATCH",
"PUT": "PUT",
"DELETE": "DELETE",
"HEAD": "HEAD",
"New Contact Created": "New Contact Created",
"New Conversation Created": "New Conversation Created",
"Triggers when a new contact is added.": "Triggers when a new contact is added.",
"Triggers when a new conversation is started.": "Triggers when a new conversation is started."
}

View File

@@ -0,0 +1,63 @@
{
"Identifier": "Identifier",
"Key": "关键字",
"\n\n1.Go to the [Crisp Marketplace](https://marketplace.crisp.chat/);\n2.Sign in or create an account (this account is different from your main Crisp account);\n3.Once logged-in, go to Plugins and click on the New Plugin button;\n4.Select the plugin type, in this case Private;\n5.Give your plugin a name, eg. \"Integration\", and hit Create;\n6.On the plugin page, go to Tokens and scroll down to Production;\n7.Click on \"Ask a production token\", and pick the scopes you require;\n - website:conversation:messages website": "\n\n1.Go to the [Crisp Marketplace](https://marketplace.crisp.chat/);\n2.Sign in or create an account (this account is different from your main Crisp account);\n3.Once logged-in, go to Plugins and click on the New Plugin button;\n4.Select the plugin type, in this case Private;\n5.Give your plugin a name, eg. \"Integration\", and hit Create;\n6.On the plugin page, go to Tokens and scroll down to Production;\n7.Click on \"Ask a production token\", and pick the scopes you require;\n - website:conversation:messages website:conversation:sessions website:people:profiles\n8.Click on \"Request production token\";\n(wait that your submission gets approved, this can take a few minutes);\n9.Once accepted, come back to Tokens, and copy your Production token keypair (configure it securely in your integration code);\n10.Finally, install the plugin on all websites you need to use it for (using the private install link, provided in the Settings section under Danger Zone / Visibility);\n",
"Add Note to Conversation": "Add Note to Conversation",
"Create Conversation": "Create Conversation",
"Create/Update Contact": "Create/Update Contact",
"Change Conversation State": "Change Conversation State",
"Find Conversation": "Find Conversation",
"Find User Profile": "Find User Profile",
"Custom API Call": "自定义 API 呼叫",
"Adds an internal note to a conversation.": "Adds an internal note to a conversation.",
"Creates a new conversation.": "Creates a new conversation.",
"Creates a new contact or updates an existing contact.": "Creates a new contact or updates an existing contact.",
"Updates the state of a conversation.": "Updates the state of a conversation.",
"Searches for conversations matching the specified criteria.": "Searches for conversations matching the specified criteria.",
"Finds a user profile by email address.": "Finds a user profile by email address.",
"Make a custom API call to a specific endpoint": "将一个自定义 API 调用到一个特定的终点",
"Website ID": "Website ID",
"Conversation ID (session_id)": "Conversation ID (session_id)",
"Note Content": "Note Content",
"Customer Email": "Customer Email",
"Customer Username": "Customer Username",
"Message From": "Message From",
"Message": "Message",
"Email": "电子邮件地址",
"Name": "名称",
"Phone Number": "Phone Number",
"Address": "Address",
"Company": "Company",
"Contact Website": "Contact Website",
"Notepad": "Notepad",
"State": "State",
"Search Query": "Search Query",
"Email Address": "Email Address",
"Method": "方法",
"Headers": "信头",
"Query Parameters": "查询参数",
"Body": "正文内容",
"Response is Binary ?": "Response is Binary ?",
"No Error on Failure": "失败时没有错误",
"Timeout (in seconds)": "超时(秒)",
"You can obtain website ID by navigating to Settings -> Workspace Settings -> Setup & Integrations.": "You can obtain website ID by navigating to Settings -> Workspace Settings -> Setup & Integrations.",
"You can obtain session from URL address bar.It starts with 'session_'.": "You can obtain session from URL address bar.It starts with 'session_'.",
"The email address of the user to find.": "The email address of the user to find.",
"Authorization headers are injected automatically from your connection.": "授权头自动从您的连接中注入。",
"Enable for files like PDFs, images, etc..": "Enable for files like PDFs, images, etc..",
"User": "用户",
"Operator": "运算符",
"Unresolved": "未解决",
"Resolved": "已解决",
"Pending": "待處理",
"GET": "获取",
"POST": "帖子",
"PATCH": "PATCH",
"PUT": "弹出",
"DELETE": "删除",
"HEAD": "黑色",
"New Contact Created": "New Contact Created",
"New Conversation Created": "New Conversation Created",
"Triggers when a new contact is added.": "Triggers when a new contact is added.",
"Triggers when a new conversation is started.": "Triggers when a new conversation is started."
}

View File

@@ -0,0 +1,44 @@
import { createPiece, PiecePropValueSchema } from '@activepieces/pieces-framework';
import { crispAuth } from './lib/common/auth';
import { createConversationAction } from './lib/actions/create-conversation';
import { createCustomApiCallAction } from '@activepieces/pieces-common';
import { BASE_URL } from './lib/common/client';
import { addNoteToConversationAction } from './lib/actions/add-note-to-conversation';
import { createOrUpdateContactAction } from './lib/actions/create-or-update-contact';
import { findUserProfileAction } from './lib/actions/find-user-profile';
import { updateConversationStateAction } from './lib/actions/update-conversation-state';
import { findConversationAction } from './lib/actions/find-conversation';
import { newContactTrigger } from './lib/triggers/new-contact';
import { newConversationTrigger } from './lib/triggers/new-conversation';
import { PieceCategory } from '@activepieces/shared';
export const crisp = createPiece({
displayName: 'Crisp',
auth: crispAuth,
minimumSupportedRelease: '0.36.1',
logoUrl: 'https://cdn.activepieces.com/pieces/crisp.png',
authors: ['kishanprmr','Ani-4x'],
categories:[PieceCategory.CUSTOMER_SUPPORT],
actions: [
addNoteToConversationAction,
createConversationAction,
createOrUpdateContactAction,
updateConversationStateAction,
findConversationAction,
findUserProfileAction,
createCustomApiCallAction({
auth: crispAuth,
baseUrl: () => BASE_URL,
authMapping: async (auth) => {
return {
Authorization: `Basic ${Buffer.from(
`${auth.props.identifier}:${auth.props.token}`,
).toString('base64')}`,
'X-Crisp-Tier': 'plugin',
'Content-Type': 'application/json',
};
},
}),
],
triggers: [newContactTrigger,newConversationTrigger],
});

View File

@@ -0,0 +1,37 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { HttpMethod } from '@activepieces/pieces-common';
import { crispAuth } from '../common/auth';
import { sessionIdProp, websiteIdProp } from '../common/props';
import { crispApiCall } from '../common/client';
export const addNoteToConversationAction = createAction({
auth: crispAuth,
name: 'add_note',
displayName: 'Add Note to Conversation',
description: 'Adds an internal note to a conversation.',
props: {
websiteId: websiteIdProp,
sessionId: sessionIdProp,
content: Property.LongText({
displayName: 'Note Content',
required: true,
}),
},
async run(context) {
const { websiteId, sessionId, content } = context.propsValue;
const response = await crispApiCall({
auth: context.auth,
method: HttpMethod.POST,
resourceUri: `/website/${websiteId}/conversation/${sessionId}/message`,
body: {
type: 'note',
from: 'operator',
origin: 'chat',
content,
},
});
return response;
},
});

View File

@@ -0,0 +1,115 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { HttpError, HttpMethod } from '@activepieces/pieces-common';
import { crispAuth } from '../common/auth';
import { websiteIdProp } from '../common/props';
import { crispApiCall } from '../common/client';
import { HttpStatusCode } from 'axios';
export const createConversationAction = createAction({
auth: crispAuth,
name: 'create_conversation',
displayName: 'Create Conversation',
description: 'Creates a new conversation.',
props: {
websiteId: websiteIdProp,
email: Property.ShortText({
displayName: 'Customer Email',
required: true,
}),
username: Property.ShortText({
displayName: 'Customer Username',
required: true,
}),
messageFrom: Property.StaticDropdown({
displayName: 'Message From',
required: true,
options: {
disabled: false,
options: [
{ label: 'User', value: 'user' },
{ label: 'Operator', value: 'operator' },
],
},
}),
message: Property.LongText({
displayName: 'Message',
required: true,
}),
},
async run(context) {
const { websiteId, message, messageFrom, email, username } = context.propsValue;
// create user if doesn't exist
try {
await crispApiCall<{ data: Record<string, any> }>({
auth: context.auth,
method: HttpMethod.PUT,
resourceUri: `/website/${websiteId}/people/profile/${email}`,
body: {
email,
person: {
nickname: username,
},
},
});
} catch (e) {
const err = e as HttpError;
if (err.response.status === HttpStatusCode.NotFound) {
await crispApiCall({
auth: context.auth,
method: HttpMethod.POST,
resourceUri: `/website/${websiteId}/people/profile`,
body: {
email,
person: {
nickname: username,
},
},
});
}
}
// create empty conversation
const newConversationResponse = await crispApiCall<{ data: { session_id: string } }>({
auth: context.auth,
method: HttpMethod.POST,
resourceUri: `/website/${websiteId}/conversation`,
body: {},
});
// add text message in conversation
await crispApiCall({
auth: context.auth,
method: HttpMethod.POST,
resourceUri: `/website/${websiteId}/conversation/${newConversationResponse.data.session_id}/message`,
body: {
type: 'text',
from: messageFrom,
origin: 'chat',
content: message,
},
});
// update customer profile meta for conversation
await crispApiCall({
auth: context.auth,
method: HttpMethod.PATCH,
resourceUri: `/website/${websiteId}/conversation/${newConversationResponse.data.session_id}/meta`,
body: {
email,
nickname:username
},
});
const conversationResponse = await crispApiCall({
auth: context.auth,
method: HttpMethod.GET,
resourceUri: `/website/${websiteId}/conversation/${newConversationResponse.data.session_id}`,
});
return conversationResponse;
},
});

View File

@@ -0,0 +1,89 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { HttpError, HttpMethod } from '@activepieces/pieces-common';
import { crispAuth } from '../common/auth';
import { websiteIdProp } from '../common/props';
import { crispApiCall } from '../common/client';
import { HttpStatusCode } from 'axios';
export const createOrUpdateContactAction = createAction({
auth: crispAuth,
name: 'create_update_contact',
displayName: 'Create/Update Contact',
description: 'Creates a new contact or updates an existing contact.',
props: {
websiteId: websiteIdProp,
email: Property.ShortText({
displayName: 'Email',
required: true,
}),
name: Property.ShortText({
displayName: 'Name',
required: true,
}),
phone: Property.ShortText({
displayName: 'Phone Number',
required: false,
}),
address: Property.LongText({
displayName: 'Address',
required: false,
}),
company: Property.ShortText({
displayName: 'Company',
required: false,
}),
website: Property.ShortText({
displayName: 'Contact Website',
required: false,
}),
notepad: Property.LongText({
displayName: 'Notepad',
required: false,
}),
},
async run(context) {
const { websiteId, website, email, name, phone, address, company, notepad } =
context.propsValue;
const contactPayload: Record<string, any> = {
email,
person: {
nickname: name,
},
notepad,
};
if (phone) contactPayload['person']['phone'] = phone;
if (address) contactPayload['person']['address'] = address;
if (website) contactPayload['person']['website'] = website;
if (company) contactPayload['company'] = { name: company };
try {
await crispApiCall({
auth: context.auth,
method: HttpMethod.PUT,
resourceUri: `/website/${websiteId}/people/profile/${email}`,
body: contactPayload,
});
} catch (e) {
const err = e as HttpError;
if (err.response.status === HttpStatusCode.NotFound) {
await crispApiCall({
auth: context.auth,
method: HttpMethod.POST,
resourceUri: `/website/${websiteId}/people/profile`,
body: contactPayload,
});
}
}
const response = await crispApiCall({
auth: context.auth,
method: HttpMethod.GET,
resourceUri: `/website/${websiteId}/people/profile/${email}`,
});
return response;
},
});

View File

@@ -0,0 +1,40 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { HttpMethod } from '@activepieces/pieces-common';
import { crispAuth } from '../common/auth';
import { websiteIdProp } from '../common/props';
import { crispApiCall } from '../common/client';
export const findConversationAction = createAction({
auth: crispAuth,
name: 'find_conversation',
displayName: 'Find Conversation',
description: 'Searches for conversations matching the specified criteria.',
props: {
websiteId: websiteIdProp,
searchQuery: Property.ShortText({
displayName: 'Search Query',
required: true,
}),
},
async run(context) {
const { websiteId, searchQuery } = context.propsValue;
if (!websiteId || !searchQuery) {
throw new Error('Website ID and search query are required');
}
const response = await crispApiCall<{ data: Record<string, any>[] }>({
auth: context.auth,
method: HttpMethod.GET,
resourceUri: `/website/${websiteId}/conversations/1`,
query: {
search_query: searchQuery,
search_type: 'text',
},
});
return {
found: response.data.length > 0,
data: response.data,
};
},
});

View File

@@ -0,0 +1,48 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { HttpError, HttpMethod } from '@activepieces/pieces-common';
import { crispAuth } from '../common/auth';
import { websiteIdProp } from '../common/props';
import { crispApiCall } from '../common/client';
import { HttpStatusCode } from 'axios';
export const findUserProfileAction = createAction({
auth: crispAuth,
name: 'find_user_profile',
displayName: 'Find User Profile',
description: 'Finds a user profile by email address.',
props: {
websiteId: websiteIdProp,
email: Property.ShortText({
displayName: 'Email Address',
description: 'The email address of the user to find.',
required: true,
}),
},
async run(context) {
const { websiteId, email } = context.propsValue;
try {
const response = await crispApiCall<{ data: Record<string, any> }>({
auth: context.auth,
method: HttpMethod.GET,
resourceUri: `/website/${websiteId}/people/profile/${email}`,
});
return {
found: true,
data: response.data,
};
} catch (e) {
const err = e as HttpError;
if (err.response.status === HttpStatusCode.NotFound) {
return {
found: false,
data: {},
};
}
throw err;
}
},
});

View File

@@ -0,0 +1,41 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { HttpMethod } from '@activepieces/pieces-common';
import { crispAuth } from '../common/auth';
import { sessionIdProp, websiteIdProp } from '../common/props';
import { crispApiCall } from '../common/client';
export const updateConversationStateAction = createAction({
auth: crispAuth,
name: 'change_state',
displayName: 'Change Conversation State',
description: 'Updates the state of a conversation.',
props: {
websiteId: websiteIdProp,
sessionId: sessionIdProp,
state: Property.StaticDropdown({
displayName: 'State',
required: true,
options: {
options: [
{ label: 'Unresolved', value: 'unresolved' },
{ label: 'Resolved', value: 'resolved' },
{ label: 'Pending', value: 'pending' },
],
},
}),
},
async run(context) {
const { websiteId, sessionId, state } = context.propsValue;
const response = await crispApiCall({
auth: context.auth,
method: HttpMethod.PATCH,
resourceUri: `/website/${websiteId}/conversation/${sessionId}/state`,
body: {
state,
},
});
return response;
},
});

View File

@@ -0,0 +1,32 @@
import { PieceAuth } from '@activepieces/pieces-framework';
const authMarkdown = `
1.Go to the [Crisp Marketplace](https://marketplace.crisp.chat/);
2.Sign in or create an account (this account is different from your main Crisp account);
3.Once logged-in, go to Plugins and click on the New Plugin button;
4.Select the plugin type, in this case Private;
5.Give your plugin a name, eg. "Integration", and hit Create;
6.On the plugin page, go to Tokens and scroll down to Production;
7.Click on "Ask a production token", and pick the scopes you require;
- website:conversation:messages website:conversation:sessions website:people:profiles
8.Click on "Request production token";
(wait that your submission gets approved, this can take a few minutes);
9.Once accepted, come back to Tokens, and copy your Production token keypair (configure it securely in your integration code);
10.Finally, install the plugin on all websites you need to use it for (using the private install link, provided in the Settings section under Danger Zone / Visibility);
`;
export const crispAuth = PieceAuth.CustomAuth({
description: authMarkdown,
required: true,
props: {
identifier: PieceAuth.SecretText({
displayName: 'Identifier',
required: true,
}),
token: PieceAuth.SecretText({
displayName: 'Key',
required: true,
}),
},
});

View File

@@ -0,0 +1,58 @@
import {
AuthenticationType,
httpClient,
HttpHeaders,
HttpMessageBody,
HttpMethod,
HttpRequest,
QueryParams,
} from '@activepieces/pieces-common';
import { AppConnectionValueForAuthProperty, PiecePropValueSchema } from '@activepieces/pieces-framework';
import { crispAuth } from './auth';
export const BASE_URL = 'https://api.crisp.chat/v1'
export type CrispApiCallParams = {
auth: AppConnectionValueForAuthProperty<typeof crispAuth>;
method: HttpMethod;
resourceUri: string;
query?: Record<string, string | number | string[] | undefined>;
body?: any;
};
export async function crispApiCall<T extends HttpMessageBody>({
auth,
method,
resourceUri,
query,
body,
}: CrispApiCallParams): Promise<T> {
const qs: QueryParams = {};
if (query) {
for (const [key, value] of Object.entries(query)) {
if (value !== null && value !== undefined) {
qs[key] = String(value);
}
}
}
const request: HttpRequest = {
method,
url: BASE_URL + resourceUri,
authentication:{
type:AuthenticationType.BASIC,
username:auth.props.identifier,
password:auth.props.token
},
headers:{
'X-Crisp-Tier':'plugin'
},
queryParams: qs,
body,
};
const response = await httpClient.sendRequest<T>(request);
return response.body;
}

View File

@@ -0,0 +1,14 @@
import { Property } from '@activepieces/pieces-framework';
export const websiteIdProp = Property.ShortText({
displayName: 'Website ID',
description:
'You can obtain website ID by navigating to Settings -> Workspace Settings -> Setup & Integrations.',
required: true,
});
export const sessionIdProp = Property.ShortText({
displayName: 'Conversation ID (session_id)',
description:`You can obtain session from URL address bar.It starts with 'session_'.`,
required: true,
});

View File

@@ -0,0 +1,89 @@
import {
createTrigger,
TriggerStrategy,
Property,
PiecePropValueSchema,
AppConnectionValueForAuthProperty,
} from '@activepieces/pieces-framework';
import { crispAuth } from '../common/auth';
import { websiteIdProp } from '../common/props';
import {
DedupeStrategy,
HttpMethod,
Polling,
pollingHelper,
QueryParams,
} from '@activepieces/pieces-common';
import dayjs from 'dayjs';
import { crispApiCall } from '../common/client';
const polling: Polling<AppConnectionValueForAuthProperty<typeof crispAuth>, { websiteId: string }> = {
strategy: DedupeStrategy.TIMEBASED,
async items({ auth, lastFetchEpochMS, propsValue }) {
const websiteId = propsValue.websiteId;
let page = 1;
let hasMoreItems = false;
const contacts = [];
do {
const qs: QueryParams = {
per_page: '50',
};
if (lastFetchEpochMS) {
qs['filter_date_start'] = dayjs(lastFetchEpochMS).toString();
}
const response = await crispApiCall<{ data: { created_at: number }[] }>({
auth,
method: HttpMethod.GET,
resourceUri: `/website/${websiteId}/people/profiles/${page}`,
query: qs,
});
const items = response.data || [];
contacts.push(...items);
page++;
hasMoreItems = items.length > 0;
if (lastFetchEpochMS === 0) break;
} while (hasMoreItems);
return contacts.map((contact) => ({
epochMilliSeconds: contact.created_at,
data: contact,
}));
},
};
export const newContactTrigger = createTrigger({
auth: crispAuth,
name: 'new_contact',
displayName: 'New Contact Created',
description: 'Triggers when a new contact is added.',
props: {
websiteId: websiteIdProp,
},
type: TriggerStrategy.POLLING,
sampleData: {},
async onEnable(context) {
await pollingHelper.onEnable(polling, {
auth: context.auth,
store: context.store,
propsValue: context.propsValue,
});
},
async onDisable(context) {
await pollingHelper.onDisable(polling, {
auth: context.auth,
store: context.store,
propsValue: context.propsValue,
});
},
async test(context) {
return await pollingHelper.test(polling, context);
},
async run(context) {
return await pollingHelper.poll(polling, context);
},
});

View File

@@ -0,0 +1,87 @@
import {
createTrigger,
TriggerStrategy,
AppConnectionValueForAuthProperty,
} from '@activepieces/pieces-framework';
import { crispAuth } from '../common/auth';
import { websiteIdProp } from '../common/props';
import {
DedupeStrategy,
HttpMethod,
Polling,
pollingHelper,
QueryParams,
} from '@activepieces/pieces-common';
import dayjs from 'dayjs';
import { crispApiCall } from '../common/client';
const polling: Polling<AppConnectionValueForAuthProperty<typeof crispAuth>, { websiteId: string }> = {
strategy: DedupeStrategy.TIMEBASED,
async items({ auth, lastFetchEpochMS, propsValue }) {
const websiteId = propsValue.websiteId;
let page = 1;
let hasMoreItems = false;
const conversations = [];
do {
const qs: QueryParams = {
per_page: '50',
};
if (lastFetchEpochMS) {
qs['filter_date_start'] = dayjs(lastFetchEpochMS).toString();
}
const response = await crispApiCall<{ data: { created_at: number }[] }>({
auth,
method: HttpMethod.GET,
resourceUri: `/website/${websiteId}/conversations/${page}`,
query: qs,
});
const items = response.data || [];
conversations.push(...items);
page++;
hasMoreItems = items.length > 0;
if (lastFetchEpochMS === 0) break;
} while (hasMoreItems);
return conversations.map((conv) => ({
epochMilliSeconds: conv.created_at,
data: conv,
}));
},
};
export const newConversationTrigger = createTrigger({
auth: crispAuth,
name: 'new_conversation',
displayName: 'New Conversation Created',
description: 'Triggers when a new conversation is started.',
props: {
websiteId: websiteIdProp,
},
type: TriggerStrategy.POLLING,
sampleData: {},
async onEnable(context) {
await pollingHelper.onEnable(polling, {
auth: context.auth,
store: context.store,
propsValue: context.propsValue,
});
},
async onDisable(context) {
await pollingHelper.onDisable(polling, {
auth: context.auth,
store: context.store,
propsValue: context.propsValue,
});
},
async test(context) {
return await pollingHelper.test(polling, context);
},
async run(context) {
return await pollingHelper.poll(polling, context);
},
});