@pipedream/twilio 0.3.3 → 0.3.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/utils.mjs ADDED
@@ -0,0 +1,147 @@
1
+ /**
2
+ * Format a number of seconds into a time elapsed string
3
+ *
4
+ * @example
5
+ * // returns "15s"
6
+ * formatTimeElapsed(15);
7
+ *
8
+ * @example
9
+ * // returns "35min"
10
+ * formatTimeElapsed(60 * 35.5);
11
+ *
12
+ * @param {Number} seconds - the number of seconds
13
+ * @returns the formatted time elapsed string
14
+ */
15
+ function formatTimeElapsed(seconds) {
16
+ var interval = seconds / 31536000;
17
+
18
+ if (interval > 1) {
19
+ return Math.floor(interval) + " years";
20
+ }
21
+ interval = seconds / 2592000;
22
+ if (interval > 1) {
23
+ return Math.floor(interval) + " months";
24
+ }
25
+ interval = seconds / 86400;
26
+ if (interval > 1) {
27
+ return Math.floor(interval) + "d";
28
+ }
29
+ interval = seconds / 3600;
30
+ if (interval > 1) {
31
+ return Math.floor(interval) + "h";
32
+ }
33
+ interval = seconds / 60;
34
+ if (interval > 1) {
35
+ return Math.floor(interval) + "min";
36
+ }
37
+ return Math.floor(seconds) + "s";
38
+ }
39
+
40
+ /**
41
+ * Get the time between two dates as a time-elapsed string
42
+ *
43
+ * @param {Date} date1 the earlier date
44
+ * @param {Date} date2 the later date
45
+ * @returns the time elapsed between two dates
46
+ */
47
+ function timeBetween(date1, date2) {
48
+ var seconds = Math.floor((date2 - date1) / 1000);
49
+
50
+ return formatTimeElapsed(seconds);
51
+ }
52
+
53
+ /**
54
+ * Return a copy of `obj` with properties omitted whose value is an empty string
55
+ *
56
+ * @param {Object} obj - the base object
57
+ * @returns the new object
58
+ */
59
+ function omitEmptyStringValues(obj) {
60
+ return Object.fromEntries(
61
+ Object.entries(obj).filter((kVpair) => kVpair[1] !== ""),
62
+ );
63
+ }
64
+
65
+ /**
66
+ * Return `value` if `condition` or an empty string otherwise
67
+ *
68
+ * @param {*} condition - the condition
69
+ * @param {*} value - the value to conditionally return
70
+ * @returns the value, if the condition is true, and empty string otherwise
71
+ */
72
+ function valueOrEmptyString(condition, value) {
73
+ return condition
74
+ ? value
75
+ : "";
76
+ }
77
+
78
+ /**
79
+ * Format a date as a human-readable string
80
+ *
81
+ * @example
82
+ * // returns "2021-10-01"
83
+ * formatDateString("2021-10-01T01:06:45.000Z");
84
+ *
85
+ * @param {Date|String} date - the date to format
86
+ * @returns the formatted date string
87
+ */
88
+ function formatDateString(date) {
89
+ const dateObj = new Date(date);
90
+ return dateObj.toISOString().split("T")[0];
91
+ }
92
+
93
+ /**
94
+ * Format a [Twilio Call object]{@link https://www.twilio.com/docs/voice/api/call-resource} as a
95
+ * string
96
+ *
97
+ * @param {Object} call - The Twilio Call object
98
+ * @returns the string representing a call
99
+ */
100
+ function callToString(call) {
101
+ const fromPart = valueOrEmptyString(call.fromFormatted, call.fromFormatted);
102
+ const toPart = valueOrEmptyString(call.toFormatted, ` to ${call.toFormatted}`);
103
+ const datePart = valueOrEmptyString(call.startTime, ` on ${formatDateString(call.startTime)}`);
104
+ const durationPart = valueOrEmptyString(call.duration, ` for ${formatTimeElapsed(call.duration)}`);
105
+ return fromPart + toPart + datePart + durationPart;
106
+ }
107
+
108
+ /**
109
+ * Format a [Twilio Message object]{@link https://www.twilio.com/docs/sms/api/message-resource} as a
110
+ * string
111
+ *
112
+ * @param {Object} call - The Twilio Message object
113
+ * @returns the string representing a message
114
+ */
115
+ function messageToString(message) {
116
+ const MAX_LENGTH = 30;
117
+ const messageText = message.body.length > MAX_LENGTH
118
+ ? `${message.body.slice(0, MAX_LENGTH)}...`
119
+ : message.body; // truncate long text
120
+ const messageDate = message.dateSent || message.dateCreated;
121
+ const dateString = formatDateString(messageDate);
122
+ return `${message.from} to ${message.to} on ${dateString}: ${messageText}`;
123
+ }
124
+
125
+ /**
126
+ * Format a [Twilio Recording object]{@link https://www.twilio.com/docs/voice/api/recording} as a
127
+ * string
128
+ *
129
+ * @param {Object} call - The Twilio Recording object
130
+ * @returns the string representing a recording
131
+ */
132
+ function recordingToString(recording) {
133
+ const datePart = valueOrEmptyString(recording.startTime, ` ${formatDateString(recording.startTime)}`);
134
+ const durationPart = valueOrEmptyString(recording.duration, ` - ${formatTimeElapsed(recording.duration)}`);
135
+ return datePart + durationPart;
136
+ }
137
+
138
+ export {
139
+ formatTimeElapsed,
140
+ timeBetween,
141
+ omitEmptyStringValues,
142
+ valueOrEmptyString,
143
+ formatDateString,
144
+ callToString,
145
+ messageToString,
146
+ recordingToString,
147
+ };
@@ -1,86 +0,0 @@
1
- const twilio = require("../../twilio.app.js");
2
- const MessagingResponse = require("twilio").twiml.MessagingResponse;
3
- const twilioClient = require("twilio");
4
-
5
- module.exports = {
6
- key: "twilio-new-incoming-sms",
7
- name: "New Incoming SMS",
8
- description:
9
- "Configures a webhook in Twilio, tied to an incoming phone number, and emits an event each time an SMS is sent to that number",
10
- version: "0.0.4",
11
- dedupe: "unique",
12
- props: {
13
- twilio,
14
- incomingPhoneNumber: { propDefinition: [twilio, "incomingPhoneNumber"] },
15
- authToken: { propDefinition: [twilio, "authToken"] },
16
- responseMessage: { propDefinition: [twilio, "responseMessage"] },
17
- http: {
18
- type: "$.interface.http",
19
- customResponse: true,
20
- },
21
- },
22
- hooks: {
23
- async activate() {
24
- console.log(
25
- `Creating webhook for phone number ${this.incomingPhoneNumber}`
26
- );
27
- const createWebhookResp = await this.twilio.setIncomingSMSWebhookURL(
28
- this.incomingPhoneNumber,
29
- this.http.endpoint
30
- );
31
- console.log(createWebhookResp);
32
- },
33
- async deactivate() {
34
- console.log(
35
- `Removing webhook from phone number ${this.incomingPhoneNumber}`
36
- );
37
- const deleteWebhookResp = await this.twilio.setIncomingSMSWebhookURL(
38
- this.incomingPhoneNumber,
39
- "" // remove the webhook URL
40
- );
41
- console.log(deleteWebhookResp);
42
- },
43
- },
44
- async run(event) {
45
- const { body, headers } = event;
46
- const twiml = new MessagingResponse();
47
-
48
- // https://support.twilio.com/hc/en-us/articles/223134127-Receive-SMS-and-MMS-Messages-without-Responding
49
- let responseBody = "<Response></Response>";
50
- if (this.responseMessage) {
51
- twiml.message(this.responseMessage);
52
- responseBody = twiml.toString();
53
- }
54
-
55
- this.http.respond({
56
- status: 200,
57
- headers: { "Content-Type": "text/xml" },
58
- body: responseBody,
59
- });
60
-
61
- const twilioSignature = headers["x-twilio-signature"];
62
- if (!twilioSignature) {
63
- console.log("No x-twilio-signature header in request. Exiting.");
64
- return;
65
- }
66
-
67
- // See https://www.twilio.com/docs/usage/webhooks/webhooks-security
68
- if (
69
- !twilioClient.validateRequest(
70
- this.authToken,
71
- twilioSignature,
72
- `${this.http.endpoint}/`, // This must match the incoming URL exactly, which contains a /
73
- body
74
- )
75
- ) {
76
- throw new Error(
77
- "Computed Twilio signature doesn't match signature received in header"
78
- );
79
- }
80
-
81
- this.$emit(body, {
82
- summary: body.Body, // the content of the text message
83
- id: headers["i-twilio-idempotency-token"], // if Twilio retries a message, but we've already emitted, dedupe
84
- });
85
- },
86
- };
package/twilio.app.js DELETED
@@ -1,52 +0,0 @@
1
- const twilioClient = require("twilio");
2
-
3
- module.exports = {
4
- type: "app",
5
- app: "twilio",
6
- propDefinitions: {
7
- authToken: {
8
- type: "string",
9
- secret: true,
10
- label: "Twilio Auth Token",
11
- description:
12
- "Your Twilio auth token, found [in your Twilio console](https://www.twilio.com/console). Required for validating Twilio events.",
13
- },
14
- incomingPhoneNumber: {
15
- type: "string",
16
- label: "Incoming Phone Number",
17
- description:
18
- "The Twilio phone number where you'll receive messages. This source creates a webhook tied to this incoming phone number, **overwriting any existing webhook URL**.",
19
- async options() {
20
- return await this.listIncomingPhoneNumbers();
21
- },
22
- },
23
- responseMessage: {
24
- type: "string",
25
- optional: true,
26
- label: "SMS Response Message",
27
- description:
28
- "The message you want to send in response to incoming messages. Leave this blank if you don't need to issue a response.",
29
- },
30
- },
31
- methods: {
32
- getClient() {
33
- return twilioClient(this.$auth.Sid, this.$auth.Secret, {
34
- accountSid: this.$auth.AccountSid,
35
- });
36
- },
37
- async setIncomingSMSWebhookURL(phoneNumberSid, url) {
38
- const client = this.getClient();
39
- return await client.incomingPhoneNumbers(phoneNumberSid).update({
40
- smsMethod: "POST",
41
- smsUrl: url,
42
- });
43
- },
44
- async listIncomingPhoneNumbers() {
45
- const client = this.getClient();
46
- const numbers = await client.incomingPhoneNumbers.list();
47
- return numbers.map((number) => {
48
- return { label: number.friendlyName, value: number.sid };
49
- });
50
- },
51
- },
52
- };