diff --git a/components/thoughtly/actions/create-contact/create-contact.mjs b/components/thoughtly/actions/create-contact/create-contact.mjs new file mode 100644 index 0000000000000..94c48ccc79b62 --- /dev/null +++ b/components/thoughtly/actions/create-contact/create-contact.mjs @@ -0,0 +1,62 @@ +import thoughtly from "../../thoughtly.app.mjs"; + +export default { + key: "thoughtly-create-contact", + name: "Create Contact", + description: "Generates a new contact within your Thoughtly team. [See the documentation](https://api.thought.ly/docs/#/contact/post_contact_create)", + version: "0.0.1", + type: "action", + props: { + thoughtly, + phoneNumber: { + type: "string", + label: "Phone Number", + description: "The phone number of the new contact.", + }, + name: { + type: "string", + label: "Name", + description: "The name of the new contact.", + optional: true, + }, + email: { + type: "string", + label: "Email", + description: "The email of the new contact.", + optional: true, + }, + countryCode: { + type: "string", + label: "Country Code", + description: "The country code of the new contact's phone number.", + optional: true, + }, + tags: { + type: "string[]", + label: "Tags", + description: "Tags associated with the new contact.", + optional: true, + }, + attributes: { + type: "object", + label: "Attributes", + description: "Additional attributes for the new contact.", + optional: true, + }, + }, + async run({ $ }) { + const response = await this.thoughtly.createContact({ + $, + data: { + phone_number: this.phoneNumber, + name: this.name, + email: this.email, + country_code: this.countryCode, + tags: this.tags, + attributes: this.attributes, + }, + }); + $.export("$summary", `Successfully created contact with ID: ${response.data.id}`); + return response; + }, +}; diff --git a/components/thoughtly/actions/trigger-call/trigger-call.mjs b/components/thoughtly/actions/trigger-call/trigger-call.mjs new file mode 100644 index 0000000000000..65c718ccd7637 --- /dev/null +++ b/components/thoughtly/actions/trigger-call/trigger-call.mjs @@ -0,0 +1,43 @@ +import { parseObject } from "../../common/utils.mjs"; +import thoughtly from "../../thoughtly.app.mjs"; + +export default { + key: "thoughtly-trigger-call", + name: "Trigger a Call", + description: "Triggers a call to a designated contact. [See the documentation](https://api.thought.ly/docs/#/contact/post_contact_call)", + version: "0.0.1", + type: "action", + props: { + thoughtly, + contactId: { + propDefinition: [ + thoughtly, + "contactId", + ], + }, + interviewId: { + propDefinition: [ + thoughtly, + "interviewId", + ], + }, + metadata: { + type: "object", + label: "Metadata", + description: "An object of metadata.", + optional: true, + }, + }, + async run({ $ }) { + const response = await this.thoughtly.callContact({ + $, + data: { + contact_id: this.contactId, + interview_id: this.interviewId, + metadata: parseObject(this.metadata), + }, + }); + $.export("$summary", `Successfully triggered a call to contact ID ${this.contactId}`); + return response; + }, +}; diff --git a/components/thoughtly/common/utils.mjs b/components/thoughtly/common/utils.mjs new file mode 100644 index 0000000000000..dcc9cc61f6f41 --- /dev/null +++ b/components/thoughtly/common/utils.mjs @@ -0,0 +1,24 @@ +export const parseObject = (obj) => { + if (!obj) return undefined; + + if (Array.isArray(obj)) { + return obj.map((item) => { + if (typeof item === "string") { + try { + return JSON.parse(item); + } catch (e) { + return item; + } + } + return item; + }); + } + if (typeof obj === "string") { + try { + return JSON.parse(obj); + } catch (e) { + return obj; + } + } + return obj; +}; diff --git a/components/thoughtly/package.json b/components/thoughtly/package.json index 2ea3785f8db6c..9a2a969102308 100644 --- a/components/thoughtly/package.json +++ b/components/thoughtly/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/thoughtly", - "version": "0.0.1", + "version": "0.1.0", "description": "Pipedream Thoughtly Components", "main": "thoughtly.app.mjs", "keywords": [ @@ -11,5 +11,9 @@ "author": "Pipedream (https://pipedream.com/)", "publishConfig": { "access": "public" + }, + "dependencies": { + "@pipedream/platform": "^1.6.5" } -} \ No newline at end of file +} + diff --git a/components/thoughtly/sources/new-response-instant/new-response-instant.mjs b/components/thoughtly/sources/new-response-instant/new-response-instant.mjs new file mode 100644 index 0000000000000..d384baf29957b --- /dev/null +++ b/components/thoughtly/sources/new-response-instant/new-response-instant.mjs @@ -0,0 +1,50 @@ +import thoughtly from "../../thoughtly.app.mjs"; +import sampleEmit from "./test-event.mjs"; + +export default { + key: "thoughtly-new-response-instant", + name: "New Response (Instant)", + description: "Emit new event when a thoughtly gets a new response.", + version: "0.0.1", + type: "source", + dedupe: "unique", + props: { + thoughtly, + http: "$.interface.http", + db: "$.service.db", + interviewId: { + propDefinition: [ + thoughtly, + "interviewId", + ], + }, + }, + hooks: { + async activate() { + await this.thoughtly.createHook({ + data: { + type: "NEW_RESPONSE", + url: this.http.endpoint, + data: this.interviewId, + }, + }); + }, + async deactivate() { + await this.thoughtly.deleteHook({ + data: { + type: "NEW_RESPONSE", + url: this.http.endpoint, + data: this.interviewId, + }, + }); + }, + }, + async run({ body }) { + this.$emit(body, { + id: body.id, + summary: `New response received with Id: ${body.id}`, + ts: Date.parse(body.created), + }); + }, + sampleEmit, +}; diff --git a/components/thoughtly/sources/new-response-instant/test-event.mjs b/components/thoughtly/sources/new-response-instant/test-event.mjs new file mode 100644 index 0000000000000..ee83232ee5bee --- /dev/null +++ b/components/thoughtly/sources/new-response-instant/test-event.mjs @@ -0,0 +1,44 @@ +export default { + "id": "12345678-1234-1234-1234-123456789012", + "created": "2024-05-14T14:27:36.575Z", + "updated": "2024-05-14T14:27:36.704Z", + "version": 2, + "interview": { + "id": "12345678" + }, + "contact": { + "id": "12345678-1234-1234-1234-123456789012", + "created": "2024-05-14T13:26:36.017Z", + "updated": "2024-05-14T13:26:36.017Z", + "version": 1, + "team_id": "12345678-1234-1234-1234-123456789012", + "status": "ACTIVE", + "name": "Contact name", + "caller_type": null, + "phone_number": "+123456789", + "email": "contact@email.com", + "attributes": {}, + "tags": [] + }, + "team": {}, + "type": "PHONE_CALL", + "status": "NOT_STARTED", + "start_time": "2024-05-14T14:27:33.016Z", + "end_time": null, + "duration_ms": "0", + "conversation_history": [ + { + "date": "2024-05-14T14:27:36.574Z", + "text": "string", + "author": "ai", + "audio_url": "https://cdn.thoughtly.net/production-1234567890.wav", + "cumulative_duration_ms": 0 + } + ], + "ai_name": "Tessa", + "phone_number": "+123456789", + "recording_url": null, + "transcript": "Agent: agent text", + "summary_data": null, + "metadata": null +} \ No newline at end of file diff --git a/components/thoughtly/thoughtly.app.mjs b/components/thoughtly/thoughtly.app.mjs index 0eb5cd0189108..77831d8cde90a 100644 --- a/components/thoughtly/thoughtly.app.mjs +++ b/components/thoughtly/thoughtly.app.mjs @@ -1,11 +1,105 @@ +import { axios } from "@pipedream/platform"; + export default { type: "app", app: "thoughtly", - propDefinitions: {}, + propDefinitions: { + contactId: { + type: "string", + label: "Contact ID", + description: "The ID of the contact.", + async options({ page }) { + const { data: { contacts } } = await this.listContacts({ + params: { + page, + }, + }); + + return contacts.map(({ + id: value, name, phone_number, + }) => ({ + label: `${name || phone_number}`, + value, + })); + }, + }, + interviewId: { + type: "string", + label: "Interview ID", + description: "The ID of the interview.", + async options({ page }) { + const { data: { interviews } } = await this.listInterviews({ + params: { + page, + }, + }); + + return interviews.map(({ + id: value, title: label, + }) => ({ + label, + value, + })); + }, + }, + }, methods: { - // this.$auth contains connected account data - authKeys() { - console.log(Object.keys(this.$auth)); + _baseUrl() { + return "https://api.thought.ly"; + }, + _headers() { + return { + "x-api-token": `${this.$auth.api_token}`, + }; + }, + _makeRequest({ + $ = this, path, ...opts + }) { + return axios($, { + url: this._baseUrl() + path, + headers: this._headers(), + ...opts, + }); + }, + createContact(opts = {}) { + return this._makeRequest({ + method: "POST", + path: "/contact/create", + ...opts, + }); + }, + callContact(opts = {}) { + return this._makeRequest({ + method: "POST", + path: "/contact/call", + ...opts, + }); + }, + listContacts(opts = {}) { + return this._makeRequest({ + path: "/contact", + ...opts, + }); + }, + listInterviews(opts = {}) { + return this._makeRequest({ + path: "/interview", + ...opts, + }); + }, + createHook(opts = {}) { + return this._makeRequest({ + method: "POST", + path: "/webhooks/subscribe", + ...opts, + }); + }, + deleteHook(opts = {}) { + return this._makeRequest({ + method: "DELETE", + path: "/webhooks/unsubscribe", + ...opts, + }); }, }, -}; \ No newline at end of file +}; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e33968d60512f..aaf0a4b4795d0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8668,7 +8668,10 @@ importers: '@pipedream/platform': 1.6.0 components/thoughtly: - specifiers: {} + specifiers: + '@pipedream/platform': ^1.6.5 + dependencies: + '@pipedream/platform': 1.6.5 components/threads: specifiers: