From 3429bf6ba4c2ac6033619188ed5f9346f9b1f2ca Mon Sep 17 00:00:00 2001 From: Luan Cazarine Date: Tue, 22 Oct 2024 12:00:13 -0300 Subject: [PATCH 1/4] smstools init --- .../add-contact-opt-out.mjs | 27 ++ .../actions/add-contact/add-contact.mjs | 118 ++++++++ .../smstools/actions/send-sms/send-sms.mjs | 71 +++++ components/smstools/package.json | 2 +- components/smstools/smstools.app.mjs | 268 +++++++++++++++++- .../new-inbound-message.mjs | 72 +++++ 6 files changed, 552 insertions(+), 6 deletions(-) create mode 100644 components/smstools/actions/add-contact-opt-out/add-contact-opt-out.mjs create mode 100644 components/smstools/actions/add-contact/add-contact.mjs create mode 100644 components/smstools/actions/send-sms/send-sms.mjs create mode 100644 components/smstools/sources/new-inbound-message/new-inbound-message.mjs diff --git a/components/smstools/actions/add-contact-opt-out/add-contact-opt-out.mjs b/components/smstools/actions/add-contact-opt-out/add-contact-opt-out.mjs new file mode 100644 index 0000000000000..a65f9335b56a6 --- /dev/null +++ b/components/smstools/actions/add-contact-opt-out/add-contact-opt-out.mjs @@ -0,0 +1,27 @@ +import smstools from "../../smstools.app.mjs"; +import { axios } from "@pipedream/platform"; + +export default { + key: "smstools-add-contact-opt-out", + name: "Add Contact to Opt-Out List", + description: "Adds a selected contact to the opt-out list, stopping further communications. [See the documentation](https://www.smstools.com/en/sms-gateway-api/add_optout)", + version: "0.0.{{ts}}", + type: "action", + props: { + smstools, + contact: { + propDefinition: [ + smstools, + "contact", + ], + }, + }, + async run({ $ }) { + const response = await this.smstools.addOptOut({ + contactid: this.contact, + }); + + $.export("$summary", `Successfully added contact with ID ${this.contact} to the opt-out list.`); + return response; + }, +}; diff --git a/components/smstools/actions/add-contact/add-contact.mjs b/components/smstools/actions/add-contact/add-contact.mjs new file mode 100644 index 0000000000000..736d896342a9e --- /dev/null +++ b/components/smstools/actions/add-contact/add-contact.mjs @@ -0,0 +1,118 @@ +import smstools from "../../smstools.app.mjs"; +import { axios } from "@pipedream/platform"; + +export default { + key: "smstools-add-contact", + name: "Add Contact to Group", + description: "Adds a new contact to an existing contact list. [See the documentation](https://www.smstools.com/en/sms-gateway-api/add_contact)", + version: "0.0.{{ts}}", + type: "action", + props: { + smstools, + phone: { + propDefinition: [ + smstools, + "phone", + ], + }, + groupId: { + propDefinition: [ + smstools, + "groupId", + ], + }, + firstName: { + type: "string", + label: "First Name", + description: "First name of the contact.", + optional: true, + }, + lastName: { + type: "string", + label: "Last Name", + description: "Last name of the contact.", + optional: true, + }, + birthday: { + type: "string", + label: "Birthday", + description: "Birthday of the contact.", + optional: true, + }, + extra1: { + type: "string", + label: "Extra 1", + description: "Extra field 1 for the contact.", + optional: true, + }, + extra2: { + type: "string", + label: "Extra 2", + description: "Extra field 2 for the contact.", + optional: true, + }, + extra3: { + type: "string", + label: "Extra 3", + description: "Extra field 3 for the contact.", + optional: true, + }, + extra4: { + type: "string", + label: "Extra 4", + description: "Extra field 4 for the contact.", + optional: true, + }, + extra5: { + type: "string", + label: "Extra 5", + description: "Extra field 5 for the contact.", + optional: true, + }, + extra6: { + type: "string", + label: "Extra 6", + description: "Extra field 6 for the contact.", + optional: true, + }, + extra7: { + type: "string", + label: "Extra 7", + description: "Extra field 7 for the contact.", + optional: true, + }, + extra8: { + type: "string", + label: "Extra 8", + description: "Extra field 8 for the contact.", + optional: true, + }, + unsubscribed: { + type: "boolean", + label: "Unsubscribed", + description: "Indicates if the contact is unsubscribed.", + optional: true, + }, + }, + async run({ $ }) { + const response = await this.smstools.addContactToGroup({ + phone: this.phone, + groupId: this.groupId, + firstname: this.firstName, + lastname: this.lastName, + birthday: this.birthday, + extra1: this.extra1, + extra2: this.extra2, + extra3: this.extra3, + extra4: this.extra4, + extra5: this.extra5, + extra6: this.extra6, + extra7: this.extra7, + extra8: this.extra8, + unsubscribed: this.unsubscribed, + }); + + $.export("$summary", `Successfully added contact with phone number ${this.phone}`); + return response; + }, +}; diff --git a/components/smstools/actions/send-sms/send-sms.mjs b/components/smstools/actions/send-sms/send-sms.mjs new file mode 100644 index 0000000000000..b544f49392181 --- /dev/null +++ b/components/smstools/actions/send-sms/send-sms.mjs @@ -0,0 +1,71 @@ +import smstools from "../../smstools.app.mjs"; +import { axios } from "@pipedream/platform"; + +export default { + key: "smstools-send-sms", + name: "Send SMS or WhatsApp Message", + description: "Sends a SMS or WhatsApp message to a specified contact. [See the documentation](https://www.smstools.com/en/sms-gateway-api/send_message)", + version: "0.0.1", + type: "action", + props: { + smstools, + message: { + type: "string", + label: "Message", + description: "The message to be sent.", + }, + to: { + propDefinition: [ + smstools, + "to", + ], + }, + sender: { + propDefinition: [ + smstools, + "sender", + ], + }, + date: { + propDefinition: [ + smstools, + "date", + ], + optional: true, + }, + reference: { + propDefinition: [ + smstools, + "reference", + ], + optional: true, + }, + test: { + propDefinition: [ + smstools, + "test", + ], + optional: true, + }, + subId: { + propDefinition: [ + smstools, + "subId", + ], + optional: true, + }, + }, + async run({ $ }) { + const response = await this.smstools.sendMessage({ + message: this.message, + to: this.to, + sender: this.sender, + date: this.date, + reference: this.reference, + test: this.test, + subId: this.subId, + }); + $.export("$summary", `Message sent successfully with ID: ${response.messageid}`); + return response; + }, +}; diff --git a/components/smstools/package.json b/components/smstools/package.json index 787c8d992c03b..898766e422877 100644 --- a/components/smstools/package.json +++ b/components/smstools/package.json @@ -12,4 +12,4 @@ "publishConfig": { "access": "public" } -} \ No newline at end of file +} diff --git a/components/smstools/smstools.app.mjs b/components/smstools/smstools.app.mjs index 9a06528cfd4ce..e0b745bbc8d1b 100644 --- a/components/smstools/smstools.app.mjs +++ b/components/smstools/smstools.app.mjs @@ -1,11 +1,269 @@ +import { axios } from "@pipedream/platform"; + export default { type: "app", app: "smstools", - propDefinitions: {}, + propDefinitions: { + inboundMessage: { + type: "string", + label: "Inbound Message", + description: "Emits new event when a new inbound message is received.", + async options() { + const messages = await this.getInboxMessages(); + return messages.map((msg) => ({ + label: msg.message, + value: msg.ID, + })); + }, + }, + phone: { + type: "string", + label: "Phone Number", + description: "The phone number of the contact.", + }, + groupId: { + type: "string", + label: "Group ID", + description: "The group ID where the contact should be added.", + async options() { + const groups = await this.getGroups(); + return groups.map((group) => ({ + label: group.name, + value: group.id, + })); + }, + }, + contact: { + type: "string", + label: "Contact", + description: "Select a contact to add to the opt-out list.", + async options() { + const contacts = await this.getContacts(); + return contacts.map((contact) => ({ + label: contact.name, + value: contact.id, + })); + }, + }, + message: { + type: "string", + label: "Message", + description: "The message to be sent.", + }, + to: { + type: "string", + label: "Recipient", + description: "The contact to send the message to.", + async options() { + const contacts = await this.getContacts(); + return contacts.map((contact) => ({ + label: contact.name, + value: contact.phone, + })); + }, + }, + sender: { + type: "string", + label: "Sender", + description: "The sender ID for the message.", + async options() { + const senders = await this.getSenderIds(); + return senders.map((sender) => ({ + label: sender.name, + value: sender.id, + })); + }, + }, + subId: { + type: "string", + label: "Sub ID", + description: "Subaccount ID from which the message is sent.", + async options() { + const subaccounts = await this.getSubAccounts(); + return subaccounts.map((subaccount) => ({ + label: subaccount.name, + value: subaccount.id, + })); + }, + optional: true, + }, + firstName: { + type: "string", + label: "First Name", + description: "First name of the contact.", + optional: true, + }, + lastName: { + type: "string", + label: "Last Name", + description: "Last name of the contact.", + optional: true, + }, + birthday: { + type: "string", + label: "Birthday", + description: "Birthday of the contact.", + optional: true, + }, + extra1: { + type: "string", + label: "Extra 1", + description: "Extra field 1 for the contact.", + optional: true, + }, + extra2: { + type: "string", + label: "Extra 2", + description: "Extra field 2 for the contact.", + optional: true, + }, + extra3: { + type: "string", + label: "Extra 3", + description: "Extra field 3 for the contact.", + optional: true, + }, + extra4: { + type: "string", + label: "Extra 4", + description: "Extra field 4 for the contact.", + optional: true, + }, + extra5: { + type: "string", + label: "Extra 5", + description: "Extra field 5 for the contact.", + optional: true, + }, + extra6: { + type: "string", + label: "Extra 6", + description: "Extra field 6 for the contact.", + optional: true, + }, + extra7: { + type: "string", + label: "Extra 7", + description: "Extra field 7 for the contact.", + optional: true, + }, + extra8: { + type: "string", + label: "Extra 8", + description: "Extra field 8 for the contact.", + optional: true, + }, + unsubscribed: { + type: "boolean", + label: "Unsubscribed", + description: "Indicates if the contact is unsubscribed.", + optional: true, + }, + date: { + type: "string", + label: "Scheduled Date", + description: "The date to send the message.", + optional: true, + }, + reference: { + type: "string", + label: "Reference", + description: "Reference for the message.", + optional: true, + }, + test: { + type: "boolean", + label: "Test", + description: "Test mode for the message.", + optional: true, + }, + }, methods: { - // this.$auth contains connected account data - authKeys() { - console.log(Object.keys(this.$auth)); + _baseUrl() { + return "https://api.smsgatewayapi.com/v1"; + }, + async _makeRequest(opts = {}) { + const { + $ = this, method = "GET", path = "/", headers, ...otherOpts + } = opts; + return axios($, { + ...otherOpts, + method, + url: this._baseUrl() + path, + headers: { + ...headers, + "X-Client-Id": this.$auth.client_id, + "X-Client-Secret": this.$auth.client_secret, + "Content-Type": "application/json", + }, + }); + }, + async getInboxMessages(opts = {}) { + return this._makeRequest({ + path: "/message/inbox", + ...opts, + }); + }, + async getContacts(opts = {}) { + return this._makeRequest({ + path: "/contacts", + ...opts, + }); + }, + async getGroups(opts = {}) { + return this._makeRequest({ + path: "/groups", + ...opts, + }); + }, + async getSenderIds(opts = {}) { + return this._makeRequest({ + path: "/senderids", + ...opts, + }); + }, + async getSubAccounts(opts = {}) { + return this._makeRequest({ + path: "/subaccounts", + ...opts, + }); + }, + async addContactToGroup({ + phone, groupId, ...otherData + }) { + return this._makeRequest({ + method: "POST", + path: "/contact", + data: { + phone, + groupid: groupId, + ...otherData, + }, + }); + }, + async addOptOut(data = {}) { + return this._makeRequest({ + method: "POST", + path: "/optout", + data, + }); + }, + async sendMessage({ + message, to, sender, date, reference, test, subId, + }) { + return this._makeRequest({ + method: "POST", + path: "/message/send", + data: { + message, + to, + sender, + date, + reference, + test, + subid: subId, + }, + }); }, }, -}; \ No newline at end of file +}; diff --git a/components/smstools/sources/new-inbound-message/new-inbound-message.mjs b/components/smstools/sources/new-inbound-message/new-inbound-message.mjs new file mode 100644 index 0000000000000..eeed19334293a --- /dev/null +++ b/components/smstools/sources/new-inbound-message/new-inbound-message.mjs @@ -0,0 +1,72 @@ +import smstools from "../../smstools.app.mjs"; +import { axios } from "@pipedream/platform"; + +export default { + key: "smstools-new-inbound-message", + name: "New Inbound Message", + description: "Emits new event when a new inbound message is received. [See the documentation](https://www.smstools.com/en/sms-gateway-api/get_inbox_all)", + version: "0.0.{{ts}}", + type: "source", + dedupe: "unique", + props: { + smstools, + db: "$.service.db", + timer: { + type: "$.interface.timer", + default: { + intervalSeconds: 900, + }, + }, + }, + methods: { + _getLastMessageId() { + return this.db.get("lastMessageId"); + }, + _setLastMessageId(id) { + this.db.set("lastMessageId", id); + }, + }, + hooks: { + async deploy() { + const messages = await this.smstools.getInboxMessages({ + params: { + limit: 50, + }, + }); + + messages.slice(0, 50).forEach((msg) => { + this.$emit(msg, { + id: msg.ID, + summary: `New inbound message from ${msg.sender}`, + ts: new Date(msg.date).getTime(), + }); + }); + + const lastMessage = messages[0]; + if (lastMessage) { + this._setLastMessageId(lastMessage.ID); + } + }, + }, + async run() { + const lastMessageId = this._getLastMessageId(); + const messages = await this.smstools.getInboxMessages({ + params: { + after_id: lastMessageId, + }, + }); + + messages.forEach((msg) => { + this.$emit(msg, { + id: msg.ID, + summary: `New inbound message from ${msg.sender}`, + ts: new Date(msg.date).getTime(), + }); + }); + + const lastMessage = messages[0]; + if (lastMessage) { + this._setLastMessageId(lastMessage.ID); + } + }, +}; From 26d7e3602617ee5742e93847bb88a05b9aef1b84 Mon Sep 17 00:00:00 2001 From: Luan Cazarine Date: Thu, 24 Oct 2024 10:34:37 -0300 Subject: [PATCH 2/4] [Components] smstools #14370 Sources - New Inbound Message Actions - Add Contact - Add Contact Opt Out - Send SMS --- .../add-contact-opt-out.mjs | 25 +- .../actions/add-contact/add-contact.mjs | 48 ++-- .../smstools/actions/send-sms/send-sms.mjs | 43 +-- components/smstools/package.json | 5 +- components/smstools/smstools.app.mjs | 258 ++++++------------ .../new-inbound-message.mjs | 80 +++--- .../new-inbound-message/test-event.mjs | 8 + 7 files changed, 191 insertions(+), 276 deletions(-) create mode 100644 components/smstools/sources/new-inbound-message/test-event.mjs diff --git a/components/smstools/actions/add-contact-opt-out/add-contact-opt-out.mjs b/components/smstools/actions/add-contact-opt-out/add-contact-opt-out.mjs index a65f9335b56a6..a696fba6d52cd 100644 --- a/components/smstools/actions/add-contact-opt-out/add-contact-opt-out.mjs +++ b/components/smstools/actions/add-contact-opt-out/add-contact-opt-out.mjs @@ -1,27 +1,34 @@ +import { ConfigurationError } from "@pipedream/platform"; import smstools from "../../smstools.app.mjs"; -import { axios } from "@pipedream/platform"; export default { key: "smstools-add-contact-opt-out", name: "Add Contact to Opt-Out List", description: "Adds a selected contact to the opt-out list, stopping further communications. [See the documentation](https://www.smstools.com/en/sms-gateway-api/add_optout)", - version: "0.0.{{ts}}", + version: "0.0.1", type: "action", props: { smstools, - contact: { + contactNumber: { propDefinition: [ smstools, - "contact", + "contactNumber", ], }, }, async run({ $ }) { - const response = await this.smstools.addOptOut({ - contactid: this.contact, - }); + try { + const response = await this.smstools.addOptOut({ + $, + data: { + number: this.contactNumber, + }, + }); - $.export("$summary", `Successfully added contact with ID ${this.contact} to the opt-out list.`); - return response; + $.export("$summary", `Successfully added contact number ${this.contactNumber} to the opt-out list.`); + return response; + } catch (e) { + throw new ConfigurationError("The number is already opted-out or does not exist in the database."); + } }, }; diff --git a/components/smstools/actions/add-contact/add-contact.mjs b/components/smstools/actions/add-contact/add-contact.mjs index 736d896342a9e..082c219cf366a 100644 --- a/components/smstools/actions/add-contact/add-contact.mjs +++ b/components/smstools/actions/add-contact/add-contact.mjs @@ -1,21 +1,20 @@ +import { ConfigurationError } from "@pipedream/platform"; import smstools from "../../smstools.app.mjs"; -import { axios } from "@pipedream/platform"; export default { key: "smstools-add-contact", name: "Add Contact to Group", description: "Adds a new contact to an existing contact list. [See the documentation](https://www.smstools.com/en/sms-gateway-api/add_contact)", - version: "0.0.{{ts}}", + version: "0.0.1", type: "action", props: { smstools, phone: { - propDefinition: [ - smstools, - "phone", - ], + type: "string", + label: "Phone Number", + description: "The phone number of the contact.", }, - groupId: { + groupid: { propDefinition: [ smstools, "groupId", @@ -36,7 +35,7 @@ export default { birthday: { type: "string", label: "Birthday", - description: "Birthday of the contact.", + description: "Birthday of the contact. **Format: YYYY-MM-DD**.", optional: true, }, extra1: { @@ -95,24 +94,21 @@ export default { }, }, async run({ $ }) { - const response = await this.smstools.addContactToGroup({ - phone: this.phone, - groupId: this.groupId, - firstname: this.firstName, - lastname: this.lastName, - birthday: this.birthday, - extra1: this.extra1, - extra2: this.extra2, - extra3: this.extra3, - extra4: this.extra4, - extra5: this.extra5, - extra6: this.extra6, - extra7: this.extra7, - extra8: this.extra8, - unsubscribed: this.unsubscribed, - }); + try { + const { + smstools, + ...data + } = this; + + const response = await smstools.addContact({ + $, + data, + }); - $.export("$summary", `Successfully added contact with phone number ${this.phone}`); - return response; + $.export("$summary", `Successfully added contact with ID: ${response.ID}`); + return response; + } catch (e) { + throw new ConfigurationError(e.response.data.errorMsg); + } }, }; diff --git a/components/smstools/actions/send-sms/send-sms.mjs b/components/smstools/actions/send-sms/send-sms.mjs index b544f49392181..aff1345e0b164 100644 --- a/components/smstools/actions/send-sms/send-sms.mjs +++ b/components/smstools/actions/send-sms/send-sms.mjs @@ -1,5 +1,4 @@ import smstools from "../../smstools.app.mjs"; -import { axios } from "@pipedream/platform"; export default { key: "smstools-send-sms", @@ -17,8 +16,10 @@ export default { to: { propDefinition: [ smstools, - "to", + "contactNumber", ], + type: "string[]", + description: "The contact(s) to send the message to.", }, sender: { propDefinition: [ @@ -27,24 +28,21 @@ export default { ], }, date: { - propDefinition: [ - smstools, - "date", - ], + type: "string", + label: "Scheduled Date", + description: "The date to send the message. **Format: yyyy-MM-dd HH:mm**. If not provided, the message will be sent as soon as possible.", optional: true, }, reference: { - propDefinition: [ - smstools, - "reference", - ], + type: "string", + label: "Reference", + description: "Reference for the message.", optional: true, }, test: { - propDefinition: [ - smstools, - "test", - ], + type: "boolean", + label: "Test", + description: "Test mode for the message.", optional: true, }, subId: { @@ -57,13 +55,16 @@ export default { }, async run({ $ }) { const response = await this.smstools.sendMessage({ - message: this.message, - to: this.to, - sender: this.sender, - date: this.date, - reference: this.reference, - test: this.test, - subId: this.subId, + $, + data: { + message: this.message, + to: this.to, + sender: this.sender, + date: this.date, + reference: this.reference, + test: this.test, + subId: this.subId, + }, }); $.export("$summary", `Message sent successfully with ID: ${response.messageid}`); return response; diff --git a/components/smstools/package.json b/components/smstools/package.json index 898766e422877..a69571462df76 100644 --- a/components/smstools/package.json +++ b/components/smstools/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/smstools", - "version": "0.0.1", + "version": "0.1.0", "description": "Pipedream SMSTools Components", "main": "smstools.app.mjs", "keywords": [ @@ -11,5 +11,8 @@ "author": "Pipedream (https://pipedream.com/)", "publishConfig": { "access": "public" + }, + "dependencies": { + "@pipedream/platform": "^3.0.3" } } diff --git a/components/smstools/smstools.app.mjs b/components/smstools/smstools.app.mjs index e0b745bbc8d1b..85141870001d7 100644 --- a/components/smstools/smstools.app.mjs +++ b/components/smstools/smstools.app.mjs @@ -16,50 +16,35 @@ export default { })); }, }, - phone: { - type: "string", - label: "Phone Number", - description: "The phone number of the contact.", - }, groupId: { type: "string", label: "Group ID", description: "The group ID where the contact should be added.", - async options() { - const groups = await this.getGroups(); - return groups.map((group) => ({ - label: group.name, - value: group.id, + async options({ page }) { + const groups = await this.getGroups({ + params: { + page: page + 1, + }, + }); + return groups.map(({ + ID: value, name: label, + }) => ({ + label, + value, })); }, }, - contact: { - type: "string", - label: "Contact", - description: "Select a contact to add to the opt-out list.", - async options() { - const contacts = await this.getContacts(); - return contacts.map((contact) => ({ - label: contact.name, - value: contact.id, - })); - }, - }, - message: { - type: "string", - label: "Message", - description: "The message to be sent.", - }, - to: { - type: "string", - label: "Recipient", - description: "The contact to send the message to.", - async options() { - const contacts = await this.getContacts(); - return contacts.map((contact) => ({ - label: contact.name, - value: contact.phone, - })); + contactNumber: { + type: "string", + label: "Contact Number", + description: "Select a contact number to add to the opt-out list.", + async options({ page }) { + const { contacts } = await this.getContactNumbers({ + params: { + page: page + 1, + }, + }); + return contacts.map(({ phone }) => phone); }, }, sender: { @@ -68,9 +53,11 @@ export default { description: "The sender ID for the message.", async options() { const senders = await this.getSenderIds(); - return senders.map((sender) => ({ - label: sender.name, - value: sender.id, + return senders.map(({ + ID: value, name: label, + }) => ({ + label, + value, })); }, }, @@ -80,190 +67,111 @@ export default { description: "Subaccount ID from which the message is sent.", async options() { const subaccounts = await this.getSubAccounts(); - return subaccounts.map((subaccount) => ({ - label: subaccount.name, - value: subaccount.id, + return subaccounts.map(({ + ID: value, username: label, + }) => ({ + label, + value, })); }, optional: true, }, - firstName: { - type: "string", - label: "First Name", - description: "First name of the contact.", - optional: true, - }, - lastName: { - type: "string", - label: "Last Name", - description: "Last name of the contact.", - optional: true, - }, - birthday: { - type: "string", - label: "Birthday", - description: "Birthday of the contact.", - optional: true, - }, - extra1: { - type: "string", - label: "Extra 1", - description: "Extra field 1 for the contact.", - optional: true, - }, - extra2: { - type: "string", - label: "Extra 2", - description: "Extra field 2 for the contact.", - optional: true, - }, - extra3: { - type: "string", - label: "Extra 3", - description: "Extra field 3 for the contact.", - optional: true, - }, - extra4: { - type: "string", - label: "Extra 4", - description: "Extra field 4 for the contact.", - optional: true, - }, - extra5: { - type: "string", - label: "Extra 5", - description: "Extra field 5 for the contact.", - optional: true, - }, - extra6: { - type: "string", - label: "Extra 6", - description: "Extra field 6 for the contact.", - optional: true, - }, - extra7: { - type: "string", - label: "Extra 7", - description: "Extra field 7 for the contact.", - optional: true, - }, - extra8: { - type: "string", - label: "Extra 8", - description: "Extra field 8 for the contact.", - optional: true, - }, - unsubscribed: { - type: "boolean", - label: "Unsubscribed", - description: "Indicates if the contact is unsubscribed.", - optional: true, - }, - date: { - type: "string", - label: "Scheduled Date", - description: "The date to send the message.", - optional: true, - }, - reference: { - type: "string", - label: "Reference", - description: "Reference for the message.", - optional: true, - }, - test: { - type: "boolean", - label: "Test", - description: "Test mode for the message.", - optional: true, - }, }, methods: { _baseUrl() { return "https://api.smsgatewayapi.com/v1"; }, - async _makeRequest(opts = {}) { - const { - $ = this, method = "GET", path = "/", headers, ...otherOpts - } = opts; + _params(params = {}) { + return { + client_id: `${this.$auth.client_id}`, + client_secret: `${this.$auth.client_secret}`, + ...params, + }; + }, + _makeRequest({ + $ = this, path, params, ...opts + }) { return axios($, { - ...otherOpts, - method, url: this._baseUrl() + path, - headers: { - ...headers, - "X-Client-Id": this.$auth.client_id, - "X-Client-Secret": this.$auth.client_secret, - "Content-Type": "application/json", - }, + params: this._params(params), + ...opts, }); }, - async getInboxMessages(opts = {}) { + getInboxMessages(opts = {}) { return this._makeRequest({ path: "/message/inbox", ...opts, }); }, - async getContacts(opts = {}) { + getContactNumbers(opts = {}) { return this._makeRequest({ - path: "/contacts", + path: "/contact", ...opts, }); }, - async getGroups(opts = {}) { + getGroups(opts = {}) { return this._makeRequest({ path: "/groups", ...opts, }); }, - async getSenderIds(opts = {}) { + getSenderIds(opts = {}) { return this._makeRequest({ path: "/senderids", ...opts, }); }, - async getSubAccounts(opts = {}) { + getSubAccounts(opts = {}) { return this._makeRequest({ - path: "/subaccounts", + path: "/subaccount", ...opts, }); }, - async addContactToGroup({ - phone, groupId, ...otherData - }) { + addContact(opts = {}) { return this._makeRequest({ method: "POST", path: "/contact", - data: { - phone, - groupid: groupId, - ...otherData, - }, + ...opts, }); }, - async addOptOut(data = {}) { + addOptOut(opts = {}) { return this._makeRequest({ method: "POST", - path: "/optout", - data, + path: "/optouts", + ...opts, }); }, - async sendMessage({ - message, to, sender, date, reference, test, subId, - }) { + sendMessage(opts = {}) { return this._makeRequest({ method: "POST", path: "/message/send", - data: { - message, - to, - sender, - date, - reference, - test, - subid: subId, - }, + ...opts, }); }, + async *paginate({ + fn, params = {}, maxResults = null, ...opts + }) { + let hasMore = false; + let count = 0; + let page = 0; + + do { + params.page = ++page; + const { messages } = await fn({ + params, + ...opts, + }); + for (const d of messages) { + yield d; + + if (maxResults && ++count === maxResults) { + return count; + } + } + + hasMore = messages.length; + + } while (hasMore); + }, }, }; diff --git a/components/smstools/sources/new-inbound-message/new-inbound-message.mjs b/components/smstools/sources/new-inbound-message/new-inbound-message.mjs index eeed19334293a..600a8616bdde3 100644 --- a/components/smstools/sources/new-inbound-message/new-inbound-message.mjs +++ b/components/smstools/sources/new-inbound-message/new-inbound-message.mjs @@ -1,11 +1,12 @@ +import { DEFAULT_POLLING_SOURCE_TIMER_INTERVAL } from "@pipedream/platform"; import smstools from "../../smstools.app.mjs"; -import { axios } from "@pipedream/platform"; +import sampleEmit from "./test-event.mjs"; export default { key: "smstools-new-inbound-message", name: "New Inbound Message", - description: "Emits new event when a new inbound message is received. [See the documentation](https://www.smstools.com/en/sms-gateway-api/get_inbox_all)", - version: "0.0.{{ts}}", + description: "Emit new event when a new inbound message is received.", + version: "0.0.1", type: "source", dedupe: "unique", props: { @@ -14,59 +15,50 @@ export default { timer: { type: "$.interface.timer", default: { - intervalSeconds: 900, + intervalSeconds: DEFAULT_POLLING_SOURCE_TIMER_INTERVAL, }, }, }, methods: { - _getLastMessageId() { - return this.db.get("lastMessageId"); + _getLastId() { + return this.db.get("lastId") || 0; }, - _setLastMessageId(id) { - this.db.set("lastMessageId", id); + _setLastId(lastId) { + this.db.set("lastId", lastId); }, - }, - hooks: { - async deploy() { - const messages = await this.smstools.getInboxMessages({ - params: { - limit: 50, - }, + async emitEvent(maxResults = false) { + const lastId = this._getLastId(); + const response = this.smstools.paginate({ + fn: this.smstools.getInboxMessages, + maxResults, }); - messages.slice(0, 50).forEach((msg) => { - this.$emit(msg, { - id: msg.ID, - summary: `New inbound message from ${msg.sender}`, - ts: new Date(msg.date).getTime(), - }); - }); + let responseArray = []; + for await (const item of response) { + if (item.ID <= lastId) break; + responseArray.push(item); + } + + if (responseArray.length) { + this._setLastId(responseArray[0].ID); + } - const lastMessage = messages[0]; - if (lastMessage) { - this._setLastMessageId(lastMessage.ID); + for (const item of responseArray.reverse()) { + this.$emit(item, { + id: item.ID, + summary: `New inbound message from ${item.sender}`, + ts: Date.parse(item.date), + }); } }, }, + hooks: { + async deploy() { + await this.emitEvent(25); + }, + }, async run() { - const lastMessageId = this._getLastMessageId(); - const messages = await this.smstools.getInboxMessages({ - params: { - after_id: lastMessageId, - }, - }); - - messages.forEach((msg) => { - this.$emit(msg, { - id: msg.ID, - summary: `New inbound message from ${msg.sender}`, - ts: new Date(msg.date).getTime(), - }); - }); - - const lastMessage = messages[0]; - if (lastMessage) { - this._setLastMessageId(lastMessage.ID); - } + await this.emitEvent(); }, + sampleEmit, }; diff --git a/components/smstools/sources/new-inbound-message/test-event.mjs b/components/smstools/sources/new-inbound-message/test-event.mjs new file mode 100644 index 0000000000000..2fad07180fa26 --- /dev/null +++ b/components/smstools/sources/new-inbound-message/test-event.mjs @@ -0,0 +1,8 @@ +export default { + "ID": "{ID}", + "message": "Hello sms", + "sender": "{nr}", + "type": "sms", + "date": "2022-01-01 12:00:00", + "receiver": "{inbox_nr}" +} \ No newline at end of file From 9d56de43b672d20c886fc8930fcb90443f25f5ac Mon Sep 17 00:00:00 2001 From: Luan Cazarine Date: Thu, 24 Oct 2024 10:38:50 -0300 Subject: [PATCH 3/4] pnpm update --- pnpm-lock.yaml | 129 +++++++++++++++++++++++++------------------------ 1 file changed, 66 insertions(+), 63 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4c445c9e62404..23d9259654b95 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9363,7 +9363,10 @@ importers: '@pipedream/platform': 3.0.3 components/smstools: - specifiers: {} + specifiers: + '@pipedream/platform': ^3.0.3 + dependencies: + '@pipedream/platform': 3.0.3 components/smtp2go: specifiers: @@ -13116,55 +13119,6 @@ packages: - aws-crt dev: false - /@aws-sdk/client-sso-oidc/3.600.0_tdq3komn4zwyd65w7klbptsu34: - resolution: {integrity: sha512-7+I8RWURGfzvChyNQSyj5/tKrqRbzRl7H+BnTOf/4Vsw1nFOi5ROhlhD4X/Y0QCTacxnaoNcIrqnY7uGGvVRzw==} - engines: {node: '>=16.0.0'} - dependencies: - '@aws-crypto/sha256-browser': 5.2.0 - '@aws-crypto/sha256-js': 5.2.0 - '@aws-sdk/client-sts': 3.600.0 - '@aws-sdk/core': 3.598.0 - '@aws-sdk/credential-provider-node': 3.600.0_f7n47caigsrjd2lr2szmwfuee4 - '@aws-sdk/middleware-host-header': 3.598.0 - '@aws-sdk/middleware-logger': 3.598.0 - '@aws-sdk/middleware-recursion-detection': 3.598.0 - '@aws-sdk/middleware-user-agent': 3.598.0 - '@aws-sdk/region-config-resolver': 3.598.0 - '@aws-sdk/types': 3.598.0 - '@aws-sdk/util-endpoints': 3.598.0 - '@aws-sdk/util-user-agent-browser': 3.598.0 - '@aws-sdk/util-user-agent-node': 3.598.0 - '@smithy/config-resolver': 3.0.3 - '@smithy/core': 2.2.3 - '@smithy/fetch-http-handler': 3.2.1 - '@smithy/hash-node': 3.0.2 - '@smithy/invalid-dependency': 3.0.2 - '@smithy/middleware-content-length': 3.0.2 - '@smithy/middleware-endpoint': 3.0.4 - '@smithy/middleware-retry': 3.0.6 - '@smithy/middleware-serde': 3.0.3 - '@smithy/middleware-stack': 3.0.3 - '@smithy/node-config-provider': 3.1.3 - '@smithy/node-http-handler': 3.1.2 - '@smithy/protocol-http': 4.0.3 - '@smithy/smithy-client': 3.1.6 - '@smithy/types': 3.3.0 - '@smithy/url-parser': 3.0.3 - '@smithy/util-base64': 3.0.0 - '@smithy/util-body-length-browser': 3.0.0 - '@smithy/util-body-length-node': 3.0.0 - '@smithy/util-defaults-mode-browser': 3.0.6 - '@smithy/util-defaults-mode-node': 3.0.6 - '@smithy/util-endpoints': 2.0.3 - '@smithy/util-middleware': 3.0.3 - '@smithy/util-retry': 3.0.2 - '@smithy/util-utf8': 3.0.0 - tslib: 2.6.3 - transitivePeerDependencies: - - '@aws-sdk/client-sts' - - aws-crt - dev: false - /@aws-sdk/client-sso/3.423.0: resolution: {integrity: sha512-znIufHkwhCIePgaYciIs3x/+BpzR57CZzbCKHR9+oOvGyufEPPpUT5bFLvbwTgfiVkTjuk6sG/ES3U5Bc+xtrA==} engines: {node: '>=14.0.0'} @@ -13400,7 +13354,7 @@ packages: dependencies: '@aws-crypto/sha256-browser': 5.2.0 '@aws-crypto/sha256-js': 5.2.0 - '@aws-sdk/client-sso-oidc': 3.600.0_tdq3komn4zwyd65w7klbptsu34 + '@aws-sdk/client-sso-oidc': 3.600.0 '@aws-sdk/core': 3.598.0 '@aws-sdk/credential-provider-node': 3.600.0_f7n47caigsrjd2lr2szmwfuee4 '@aws-sdk/middleware-host-header': 3.598.0 @@ -13442,6 +13396,55 @@ packages: - aws-crt dev: false + /@aws-sdk/client-sts/3.600.0_dseaa2p5u2yk67qiepewcq3hkq: + resolution: {integrity: sha512-KQG97B7LvTtTiGmjlrG1LRAY8wUvCQzrmZVV5bjrJ/1oXAU7DITYwVbSJeX9NWg6hDuSk0VE3MFwIXS2SvfLIA==} + engines: {node: '>=16.0.0'} + dependencies: + '@aws-crypto/sha256-browser': 5.2.0 + '@aws-crypto/sha256-js': 5.2.0 + '@aws-sdk/client-sso-oidc': 3.600.0 + '@aws-sdk/core': 3.598.0 + '@aws-sdk/credential-provider-node': 3.600.0_f7n47caigsrjd2lr2szmwfuee4 + '@aws-sdk/middleware-host-header': 3.598.0 + '@aws-sdk/middleware-logger': 3.598.0 + '@aws-sdk/middleware-recursion-detection': 3.598.0 + '@aws-sdk/middleware-user-agent': 3.598.0 + '@aws-sdk/region-config-resolver': 3.598.0 + '@aws-sdk/types': 3.598.0 + '@aws-sdk/util-endpoints': 3.598.0 + '@aws-sdk/util-user-agent-browser': 3.598.0 + '@aws-sdk/util-user-agent-node': 3.598.0 + '@smithy/config-resolver': 3.0.3 + '@smithy/core': 2.2.3 + '@smithy/fetch-http-handler': 3.2.1 + '@smithy/hash-node': 3.0.2 + '@smithy/invalid-dependency': 3.0.2 + '@smithy/middleware-content-length': 3.0.2 + '@smithy/middleware-endpoint': 3.0.4 + '@smithy/middleware-retry': 3.0.6 + '@smithy/middleware-serde': 3.0.3 + '@smithy/middleware-stack': 3.0.3 + '@smithy/node-config-provider': 3.1.3 + '@smithy/node-http-handler': 3.1.2 + '@smithy/protocol-http': 4.0.3 + '@smithy/smithy-client': 3.1.6 + '@smithy/types': 3.3.0 + '@smithy/url-parser': 3.0.3 + '@smithy/util-base64': 3.0.0 + '@smithy/util-body-length-browser': 3.0.0 + '@smithy/util-body-length-node': 3.0.0 + '@smithy/util-defaults-mode-browser': 3.0.6 + '@smithy/util-defaults-mode-node': 3.0.6 + '@smithy/util-endpoints': 2.0.3 + '@smithy/util-middleware': 3.0.3 + '@smithy/util-retry': 3.0.2 + '@smithy/util-utf8': 3.0.0 + tslib: 2.6.3 + transitivePeerDependencies: + - '@aws-sdk/client-sso-oidc' + - aws-crt + dev: false + /@aws-sdk/core/3.556.0: resolution: {integrity: sha512-vJaSaHw2kPQlo11j/Rzuz0gk1tEaKdz+2ser0f0qZ5vwFlANjt08m/frU17ctnVKC1s58bxpctO/1P894fHLrA==} engines: {node: '>=14.0.0'} @@ -16170,12 +16173,12 @@ packages: kuler: 2.0.0 dev: false - /@definitelytyped/header-parser/0.2.12: - resolution: {integrity: sha512-UYtSXiLMhzRFKh7xHMkgiWsscgHxIndmjetaptZMMS0EOvfhUTuEM68GpjiCtz5shXw22Vacs1vDTAkKGDhNmg==} + /@definitelytyped/header-parser/0.2.13: + resolution: {integrity: sha512-m7YEtGhwAjmQyJQFQ7q8+hTGTiC/WrdRATvw8fyTwgW+RiWUt8MAeehuFj4txnCYXDcLO0ozuW5gNrLoYR4Ubg==} engines: {node: '>=18.18.0'} dependencies: '@definitelytyped/typescript-versions': 0.1.4 - '@definitelytyped/utils': 0.1.7 + '@definitelytyped/utils': 0.1.8 semver: 7.6.3 dev: true @@ -16184,8 +16187,8 @@ packages: engines: {node: '>=18.18.0'} dev: true - /@definitelytyped/utils/0.1.7: - resolution: {integrity: sha512-t58AeNg6+mvyMnBHyPC6JQqWMW0Iwyb+vlpBz4V0d0iDY9H8gGCnLFg9vtN1nC+JXfTXBlf9efu9unMUeaPCiA==} + /@definitelytyped/utils/0.1.8: + resolution: {integrity: sha512-4JINx4Rttha29f50PBsJo48xZXx/He5yaIWJRwVarhYAN947+S84YciHl+AIhQNRPAFkg8+5qFngEGtKxQDWXA==} engines: {node: '>=18.18.0'} dependencies: '@qiwi/npm-registry-client': 8.9.1 @@ -17734,7 +17737,7 @@ packages: '@aws-sdk/client-sns': 3.423.0 '@aws-sdk/client-sqs': 3.423.0 '@aws-sdk/client-ssm': 3.423.0 - '@aws-sdk/client-sts': 3.600.0 + '@aws-sdk/client-sts': 3.600.0_dseaa2p5u2yk67qiepewcq3hkq '@aws-sdk/s3-request-presigner': 3.609.0 '@pipedream/helper_functions': 0.3.12 '@pipedream/platform': 1.6.6 @@ -24547,7 +24550,7 @@ packages: peerDependencies: typescript: '*' dependencies: - '@definitelytyped/header-parser': 0.2.12 + '@definitelytyped/header-parser': 0.2.13 command-exists: 1.2.9 rimraf: 3.0.2 semver: 6.3.1 @@ -24562,7 +24565,7 @@ packages: peerDependencies: typescript: '*' dependencies: - '@definitelytyped/header-parser': 0.2.12 + '@definitelytyped/header-parser': 0.2.13 command-exists: 1.2.9 rimraf: 3.0.2 semver: 6.3.1 @@ -24578,9 +24581,9 @@ packages: peerDependencies: typescript: '>= 3.0.0-dev || >= 3.1.0-dev || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.7.0-dev || >= 3.8.0-dev || >= 3.9.0-dev || >= 4.0.0-dev' dependencies: - '@definitelytyped/header-parser': 0.2.12 + '@definitelytyped/header-parser': 0.2.13 '@definitelytyped/typescript-versions': 0.1.4 - '@definitelytyped/utils': 0.1.7 + '@definitelytyped/utils': 0.1.8 dts-critic: 3.3.11_typescript@5.2.2 fs-extra: 6.0.1 json-stable-stringify: 1.0.2 @@ -24598,9 +24601,9 @@ packages: peerDependencies: typescript: '>= 3.0.0-dev || >= 3.1.0-dev || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.7.0-dev || >= 3.8.0-dev || >= 3.9.0-dev || >= 4.0.0-dev' dependencies: - '@definitelytyped/header-parser': 0.2.12 + '@definitelytyped/header-parser': 0.2.13 '@definitelytyped/typescript-versions': 0.1.4 - '@definitelytyped/utils': 0.1.7 + '@definitelytyped/utils': 0.1.8 dts-critic: 3.3.11_typescript@5.5.4 fs-extra: 6.0.1 json-stable-stringify: 1.0.2 From 3c1866e3e93453cb66c829e0798e05b9bb262f93 Mon Sep 17 00:00:00 2001 From: michelle0927 Date: Thu, 24 Oct 2024 13:46:47 -0400 Subject: [PATCH 4/4] Update components/smstools/smstools.app.mjs --- components/smstools/smstools.app.mjs | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/components/smstools/smstools.app.mjs b/components/smstools/smstools.app.mjs index 85141870001d7..5f2d0e4f35784 100644 --- a/components/smstools/smstools.app.mjs +++ b/components/smstools/smstools.app.mjs @@ -4,18 +4,6 @@ export default { type: "app", app: "smstools", propDefinitions: { - inboundMessage: { - type: "string", - label: "Inbound Message", - description: "Emits new event when a new inbound message is received.", - async options() { - const messages = await this.getInboxMessages(); - return messages.map((msg) => ({ - label: msg.message, - value: msg.ID, - })); - }, - }, groupId: { type: "string", label: "Group ID",