From a729f2f9938b64588a461aa412e71fc24ca8d373 Mon Sep 17 00:00:00 2001 From: Michelle Bergeron Date: Thu, 22 May 2025 15:57:38 -0400 Subject: [PATCH 1/2] new components --- .../landbot/actions/send-image/send-image.mjs | 41 +++++++ .../send-text-message/send-text-message.mjs | 34 ++++++ components/landbot/landbot.app.mjs | 107 ++++++++++++++++++ components/landbot/package.json | 17 +++ .../new-message-in-channel.mjs | 69 +++++++++++ .../new-message-in-channel/test-event.mjs | 41 +++++++ 6 files changed, 309 insertions(+) create mode 100644 components/landbot/actions/send-image/send-image.mjs create mode 100644 components/landbot/actions/send-text-message/send-text-message.mjs create mode 100644 components/landbot/landbot.app.mjs create mode 100644 components/landbot/package.json create mode 100644 components/landbot/sources/new-message-in-channel/new-message-in-channel.mjs create mode 100644 components/landbot/sources/new-message-in-channel/test-event.mjs diff --git a/components/landbot/actions/send-image/send-image.mjs b/components/landbot/actions/send-image/send-image.mjs new file mode 100644 index 0000000000000..b80b7ff76fea0 --- /dev/null +++ b/components/landbot/actions/send-image/send-image.mjs @@ -0,0 +1,41 @@ +import landbot from "../../landbot.app.mjs"; + +export default { + key: "landbot-send-image", + name: "Send Image", + description: "Send an image to a customer via Landbot. [See the docs](https://api.landbot.io/#api-Customers-PostHttpsApiLandbotIoV1CustomersCustomer_idSend_image)", + version: "0.0.1", + type: "action", + props: { + landbot, + customerId: { + propDefinition: [ + landbot, + "customerId", + ], + }, + imageUrl: { + type: "string", + label: "Image URL", + description: "The URL of the image to send", + }, + caption: { + type: "string", + label: "Caption", + description: "Optional caption for the image", + optional: true, + }, + }, + async run({ $ }) { + const response = await this.landbot.sendImageMessage({ + $, + customerId: this.customerId, + data: { + url: this.imageUrl, + caption: this.caption, + }, + }); + $.export("$summary", `Successfully sent image to Customer ID: ${this.customerId}`); + return response; + }, +}; diff --git a/components/landbot/actions/send-text-message/send-text-message.mjs b/components/landbot/actions/send-text-message/send-text-message.mjs new file mode 100644 index 0000000000000..0b3094ce983f7 --- /dev/null +++ b/components/landbot/actions/send-text-message/send-text-message.mjs @@ -0,0 +1,34 @@ +import landbot from "../../landbot.app.mjs"; + +export default { + key: "landbot-send-text-message", + name: "Send Text Message", + description: "Send a text message to a customer. [See the documentation](https://api.landbot.io/#api-Customers-PostHttpsApiLandbotIoV1CustomersCustomer_idSend_text)", + version: "0.0.1", + type: "action", + props: { + landbot, + customerId: { + propDefinition: [ + landbot, + "customerId", + ], + }, + message: { + type: "string", + label: "Message", + description: "The message to send to the customer", + }, + }, + async run({ $ }) { + const response = await this.landbot.sendTextMessage({ + $, + customerId: this.customerId, + data: { + message: this.message, + }, + }); + $.export("$summary", `Successfully sent message to Customer ID: ${this.customerId}`); + return response; + }, +}; diff --git a/components/landbot/landbot.app.mjs b/components/landbot/landbot.app.mjs new file mode 100644 index 0000000000000..82cf825afe466 --- /dev/null +++ b/components/landbot/landbot.app.mjs @@ -0,0 +1,107 @@ +import { axios } from "@pipedream/platform"; +const DEFAULT_LIMIT = 20; + +export default { + type: "app", + app: "landbot", + propDefinitions: { + customerId: { + type: "string", + label: "Customer ID", + description: "The ID of the customer to message", + async options({ page }) { + const { customers } = await this.listCustomers({ + params: { + limit: DEFAULT_LIMIT, + offset: page * DEFAULT_LIMIT, + }, + }); + return customers.map((customer) => ({ + label: customer.name, + value: customer.id, + })); + }, + }, + channelId: { + type: "string", + label: "Channel ID", + description: "The ID of the channel to create a webhook for", + async options({ page }) { + const { channels } = await this.listChannels({ + params: { + limit: DEFAULT_LIMIT, + offset: page * DEFAULT_LIMIT, + }, + }); + return channels.map((channel) => ({ + label: channel.name, + value: channel.id, + })); + }, + }, + }, + methods: { + _baseUrl() { + return "https://api.landbot.io/v1"; + }, + _makeRequest({ + $ = this, path, ...opts + }) { + return axios($, { + url: `${this._baseUrl()}${path}`, + headers: { + Authorization: `Token ${this.$auth.api_token}`, + }, + ...opts, + }); + }, + createWebhook({ + channelId, ...opts + }) { + return this._makeRequest({ + path: `/channels/${channelId}/message_hooks/`, + method: "POST", + ...opts, + }); + }, + deleteWebhook({ + channelId, webhookId, ...opts + }) { + return this._makeRequest({ + path: `/channels/${channelId}/message_hooks/${webhookId}/`, + method: "DELETE", + ...opts, + }); + }, + listCustomers(opts = {}) { + return this._makeRequest({ + path: "/customers/", + ...opts, + }); + }, + listChannels(opts = {}) { + return this._makeRequest({ + path: "/channels/", + ...opts, + }); + }, + sendTextMessage({ + customerId, ...opts + }) { + return this._makeRequest({ + path: `/customers/${customerId}/send_text/`, + method: "POST", + ...opts, + }); + }, + sendImageMessage({ + customerId, ...opts + }) { + return this._makeRequest({ + path: `/customers/${customerId}/send_image/`, + method: "POST", + ...opts, + }); + }, + }, +}; diff --git a/components/landbot/package.json b/components/landbot/package.json new file mode 100644 index 0000000000000..f645d1eba234c --- /dev/null +++ b/components/landbot/package.json @@ -0,0 +1,17 @@ +{ + "name": "@pipedream/landbot", + "version": "0.0.1", + "description": "Pipedream Landbot Components", + "main": "landbot.app.mjs", + "keywords": [ + "pipedream", + "landbot" + ], + "author": "Pipedream (https://pipedream.com/)", + "publishConfig": { + "access": "public" + }, + "dependencies": { + "@pipedream/platform": "^3.0.3" + } +} diff --git a/components/landbot/sources/new-message-in-channel/new-message-in-channel.mjs b/components/landbot/sources/new-message-in-channel/new-message-in-channel.mjs new file mode 100644 index 0000000000000..8d36cefe49be5 --- /dev/null +++ b/components/landbot/sources/new-message-in-channel/new-message-in-channel.mjs @@ -0,0 +1,69 @@ +import landbot from "../../landbot.app.mjs"; +import sampleEmit from "./test-event.mjs"; + +export default { + key: "landbot-new-message-in-channel", + name: "New Message in Channel (Instant)", + description: "Emit new events when a new message is sent in a channel. [See the documentation](https://api.landbot.io/#api-MessageHooks-PostHttpsApiLandbotIoV1ChannelsChannel_idMessage_hooks)", + version: "0.0.1", + type: "source", + dedupe: "unique", + props: { + landbot, + db: "$.service.db", + http: "$.interface.http", + channelId: { + propDefinition: [ + landbot, + "channelId", + ], + }, + }, + hooks: { + async activate() { + const { hook } = await this.landbot.createWebhook({ + channelId: this.channelId, + data: { + url: this.http.endpoint, + }, + }); + this._setHookId(hook.id); + }, + async deactivate() { + const webhookId = this._getHookId(); + if (webhookId) { + await this.landbot.deleteWebhook({ + channelId: this.channelId, + webhookId, + }); + } + }, + }, + methods: { + _getHookId() { + return this.db.get("hookId"); + }, + _setHookId(hookId) { + this.db.set("hookId", hookId); + }, + generateMeta(message) { + return { + id: message.timestamp, + summary: `New ${message.type} message in channel`, + ts: message.timestamp, + }; + }, + }, + async run(event) { + const { body } = event; + if (!body || !body.messages) { + return; + } + for (const message of body.messages) { + const meta = this.generateMeta(message); + this.$emit(message, meta); + } + }, + sampleEmit, +}; + diff --git a/components/landbot/sources/new-message-in-channel/test-event.mjs b/components/landbot/sources/new-message-in-channel/test-event.mjs new file mode 100644 index 0000000000000..c3d4937631e1c --- /dev/null +++ b/components/landbot/sources/new-message-in-channel/test-event.mjs @@ -0,0 +1,41 @@ +export default { + "_raw": { + "uuid": "f00627c8-394f-493b-b8a5-e9cd44b5c319", + "extra": {}, + "chat": 473716610, + "ui_key": null, + "type": "text", + "channel": 2955840, + "timestamp": 1747943104.006807, + "author_type": "agent", + "author_uuid": "ce8013ec-ddd2-4711-849a-a5b91cf69ada", + "read": false, + "seq": null, + "samurai": 794028, + "message": "hello world", + "rich_text": null + }, + "type": "text", + "data": { + "body": "hello world" + }, + "timestamp": 1747943104.006807, + "sender": { + "id": 794028, + "name": "", + "type": "agent" + }, + "customer": { + "agent_id": 794028, + "name": "", + "country": "United States", + "url": "https://landbot.site/v3/H-2955840-YBOL4P79UNIGME5S/index.html", + "id": 473548616, + "archived": false + }, + "channel": { + "id": 2955840, + "name": "New bot", + "type": "landbot" + } + } \ No newline at end of file From 2383b2f77950cff836aca3910cfac4be46f77f51 Mon Sep 17 00:00:00 2001 From: Michelle Bergeron Date: Thu, 22 May 2025 15:58:22 -0400 Subject: [PATCH 2/2] pnpm-lock.yaml --- pnpm-lock.yaml | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1dfcf62479279..e2c2ac817db1e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -7126,6 +7126,12 @@ importers: components/lamini: {} + components/landbot: + dependencies: + '@pipedream/platform': + specifier: ^3.0.3 + version: 3.0.3 + components/langbase: dependencies: '@pipedream/platform': @@ -15468,14 +15474,6 @@ importers: specifier: ^6.0.0 version: 6.2.0 - modelcontextprotocol/node_modules2/@modelcontextprotocol/sdk/dist/cjs: {} - - modelcontextprotocol/node_modules2/@modelcontextprotocol/sdk/dist/esm: {} - - modelcontextprotocol/node_modules2/zod-to-json-schema/dist/cjs: {} - - modelcontextprotocol/node_modules2/zod-to-json-schema/dist/esm: {} - packages/ai: dependencies: '@pipedream/sdk':