@pipedream/twilio 0.3.3 → 0.3.5
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/README.md +14 -0
- package/actions/delete-call/delete-call.mjs +23 -0
- package/actions/delete-message/delete-message.mjs +23 -0
- package/actions/download-recording-media/download-recording-media.mjs +50 -0
- package/actions/get-call/get-call.mjs +24 -0
- package/actions/get-message/get-message.mjs +24 -0
- package/actions/list-calls/list-calls.mjs +60 -0
- package/actions/list-message-media/list-message-media.mjs +34 -0
- package/actions/list-messages/list-messages.mjs +60 -0
- package/actions/list-recording-transcriptions/list-recording-transcriptions.mjs +37 -0
- package/actions/make-phone-call/make-phone-call.mjs +52 -0
- package/actions/send-mms/send-mms.mjs +59 -0
- package/actions/send-sms/send-sms.mjs +52 -0
- package/common/constants.mjs +13 -0
- package/common/utils.mjs +144 -0
- package/package.json +20 -19
- package/sources/common-polling.mjs +44 -0
- package/sources/common-webhook.mjs +99 -0
- package/sources/new-call/new-call.mjs +33 -0
- package/sources/new-incoming-sms/new-incoming-sms.mjs +47 -0
- package/sources/new-phone-number/new-phone-number.mjs +29 -0
- package/sources/new-recording/new-recording.mjs +28 -0
- package/sources/new-transcription/new-transcription.mjs +28 -0
- package/twilio.app.mjs +338 -0
- package/sources/new-incoming-sms/new-incoming-sms.js +0 -86
- package/twilio.app.js +0 -52
package/README.md
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Overview
|
|
2
|
+
|
|
3
|
+
With the Twilio API, you can build telephone applications that make and receive
|
|
4
|
+
phone calls, as well astext messaging applications that send and receive text
|
|
5
|
+
messages.
|
|
6
|
+
|
|
7
|
+
Some examples of applications you could build include:
|
|
8
|
+
|
|
9
|
+
- A phone call application that allows you to make and receive phone calls over
|
|
10
|
+
the internet
|
|
11
|
+
- A text messaging application that allows you to send and receive text
|
|
12
|
+
messages over the internet
|
|
13
|
+
- A voicemail application that allows you to leave and receive voicemails over
|
|
14
|
+
the internet
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import twilio from "../../twilio.app.mjs";
|
|
2
|
+
|
|
3
|
+
export default {
|
|
4
|
+
key: "twilio-delete-call",
|
|
5
|
+
name: "Delete Call",
|
|
6
|
+
description: "Remove a call record from your account. [See the docs](https://www.twilio.com/docs/voice/api/call-resource#delete-a-call-resource) for more information",
|
|
7
|
+
version: "0.1.0",
|
|
8
|
+
type: "action",
|
|
9
|
+
props: {
|
|
10
|
+
twilio,
|
|
11
|
+
sid: {
|
|
12
|
+
propDefinition: [
|
|
13
|
+
twilio,
|
|
14
|
+
"sid",
|
|
15
|
+
],
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
async run({ $ }) {
|
|
19
|
+
const resp = await this.twilio.deleteCall(this.sid);
|
|
20
|
+
$.export("$summary", `Successfully deleted the call, "${this.sid}"`);
|
|
21
|
+
return resp;
|
|
22
|
+
},
|
|
23
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import twilio from "../../twilio.app.mjs";
|
|
2
|
+
|
|
3
|
+
export default {
|
|
4
|
+
key: "twilio-delete-message",
|
|
5
|
+
name: "Delete Message",
|
|
6
|
+
description: "Delete a message record from your account. [See the docs](https://www.twilio.com/docs/sms/api/message-resource#delete-a-message-resource) for more information",
|
|
7
|
+
version: "0.1.0",
|
|
8
|
+
type: "action",
|
|
9
|
+
props: {
|
|
10
|
+
twilio,
|
|
11
|
+
messageId: {
|
|
12
|
+
propDefinition: [
|
|
13
|
+
twilio,
|
|
14
|
+
"messageId",
|
|
15
|
+
],
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
async run({ $ }) {
|
|
19
|
+
const resp = await this.twilio.deleteMessage(this.messageId);
|
|
20
|
+
$.export("$summary", `Successfully deleted the message, "${this.messageId}"`);
|
|
21
|
+
return resp;
|
|
22
|
+
},
|
|
23
|
+
};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import twilio from "../../twilio.app.mjs";
|
|
2
|
+
import got from "got";
|
|
3
|
+
import stream from "stream";
|
|
4
|
+
import { promisify } from "util";
|
|
5
|
+
import fs from "fs";
|
|
6
|
+
|
|
7
|
+
export default {
|
|
8
|
+
key: "twilio-download-recording-media",
|
|
9
|
+
name: "Download Recording Media",
|
|
10
|
+
description: "Download a recording media file. [See the docs](https://www.twilio.com/docs/voice/api/recording#fetch-a-recording-media-file) for more information",
|
|
11
|
+
version: "0.1.0",
|
|
12
|
+
type: "action",
|
|
13
|
+
props: {
|
|
14
|
+
twilio,
|
|
15
|
+
recordingID: {
|
|
16
|
+
propDefinition: [
|
|
17
|
+
twilio,
|
|
18
|
+
"recordingID",
|
|
19
|
+
],
|
|
20
|
+
},
|
|
21
|
+
format: {
|
|
22
|
+
propDefinition: [
|
|
23
|
+
twilio,
|
|
24
|
+
"format",
|
|
25
|
+
],
|
|
26
|
+
},
|
|
27
|
+
filePath: {
|
|
28
|
+
type: "string",
|
|
29
|
+
label: "File Path",
|
|
30
|
+
description: "The destination path in [`/tmp`](https://pipedream.com/docs/workflows/steps/code/nodejs/working-with-files/#the-tmp-directory) for the downloaded the file (e.g., `/tmp/myFile.mp3`)",
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
async run({ $ }) {
|
|
34
|
+
// Get Recording resource to get `uri`
|
|
35
|
+
const recording = await this.twilio.getRecording(this.recordingID);
|
|
36
|
+
const client = this.twilio.getClient();
|
|
37
|
+
// `uri` ends in ".json" - remove ".json" from uri
|
|
38
|
+
const uri = client.api.absoluteUrl(recording.uri).replace(".json", "");
|
|
39
|
+
// Add chosen download format extension (e.g. ".mp3"), as specified in the Twilio API docs:
|
|
40
|
+
// https://www.twilio.com/docs/voice/api/recording#fetch-a-recording-media-file
|
|
41
|
+
const downloadUrl = uri + this.format;
|
|
42
|
+
const pipeline = promisify(stream.pipeline);
|
|
43
|
+
const resp = await pipeline(
|
|
44
|
+
got.stream(downloadUrl),
|
|
45
|
+
fs.createWriteStream(this.filePath),
|
|
46
|
+
);
|
|
47
|
+
$.export("$summary", `Successfully downloaded the recording media file to "${this.filePath}"`);
|
|
48
|
+
return resp;
|
|
49
|
+
},
|
|
50
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import twilio from "../../twilio.app.mjs";
|
|
2
|
+
import { callToString } from "../../common/utils.mjs";
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
key: "twilio-get-call",
|
|
6
|
+
name: "Get Call",
|
|
7
|
+
description: "Return call resource of an individual call. [See the docs](https://www.twilio.com/docs/voice/api/call-resource#fetch-a-call-resource) for more information",
|
|
8
|
+
version: "0.1.0",
|
|
9
|
+
type: "action",
|
|
10
|
+
props: {
|
|
11
|
+
twilio,
|
|
12
|
+
sid: {
|
|
13
|
+
propDefinition: [
|
|
14
|
+
twilio,
|
|
15
|
+
"sid",
|
|
16
|
+
],
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
async run({ $ }) {
|
|
20
|
+
const resp = await this.twilio.getCall(this.sid);
|
|
21
|
+
$.export("$summary", `Successfully fetched the call, "${callToString(resp)}"`);
|
|
22
|
+
return resp;
|
|
23
|
+
},
|
|
24
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import twilio from "../../twilio.app.mjs";
|
|
2
|
+
import { messageToString } from "../../common/utils.mjs";
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
key: "twilio-get-message",
|
|
6
|
+
name: "Get Message",
|
|
7
|
+
description: "Return details of a message. [See the docs](https://www.twilio.com/docs/sms/api/message-resource#fetch-a-message-resource) for more information",
|
|
8
|
+
version: "0.1.0",
|
|
9
|
+
type: "action",
|
|
10
|
+
props: {
|
|
11
|
+
twilio,
|
|
12
|
+
messageId: {
|
|
13
|
+
propDefinition: [
|
|
14
|
+
twilio,
|
|
15
|
+
"messageId",
|
|
16
|
+
],
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
async run({ $ }) {
|
|
20
|
+
const resp = await this.twilio.getMessage(this.messageId);
|
|
21
|
+
$.export("$summary", `Successfully fetched the message, "${messageToString(resp)}"`);
|
|
22
|
+
return resp;
|
|
23
|
+
},
|
|
24
|
+
};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import twilio from "../../twilio.app.mjs";
|
|
2
|
+
import { omitEmptyStringValues } from "../../common/utils.mjs";
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
key: "twilio-list-calls",
|
|
6
|
+
name: "List Calls",
|
|
7
|
+
description: "Return a list of calls associated with your account. [See the docs](https://www.twilio.com/docs/voice/api/call-resource#read-multiple-call-resources) for more information",
|
|
8
|
+
version: "0.1.0",
|
|
9
|
+
type: "action",
|
|
10
|
+
props: {
|
|
11
|
+
twilio,
|
|
12
|
+
from: {
|
|
13
|
+
propDefinition: [
|
|
14
|
+
twilio,
|
|
15
|
+
"from",
|
|
16
|
+
],
|
|
17
|
+
description: "Only include calls from this phone number, SIP address, Client identifier or SIM SID. Format the phone number in E.164 format with a `+` and country code (e.g., `+16175551212`).",
|
|
18
|
+
optional: true,
|
|
19
|
+
},
|
|
20
|
+
to: {
|
|
21
|
+
propDefinition: [
|
|
22
|
+
twilio,
|
|
23
|
+
"to",
|
|
24
|
+
],
|
|
25
|
+
description: "Only show calls made to this phone number, SIP address, Client identifier or SIM SID. Format the phone number in E.164 format with a `+` and country code (e.g., `+16175551212`).",
|
|
26
|
+
optional: true,
|
|
27
|
+
},
|
|
28
|
+
parentCallSid: {
|
|
29
|
+
propDefinition: [
|
|
30
|
+
twilio,
|
|
31
|
+
"parentCallSid",
|
|
32
|
+
],
|
|
33
|
+
},
|
|
34
|
+
status: {
|
|
35
|
+
propDefinition: [
|
|
36
|
+
twilio,
|
|
37
|
+
"status",
|
|
38
|
+
],
|
|
39
|
+
},
|
|
40
|
+
limit: {
|
|
41
|
+
propDefinition: [
|
|
42
|
+
twilio,
|
|
43
|
+
"limit",
|
|
44
|
+
],
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
async run({ $ }) {
|
|
48
|
+
const resp = await this.twilio.listCalls(omitEmptyStringValues({
|
|
49
|
+
to: this.to,
|
|
50
|
+
from: this.from,
|
|
51
|
+
parentCallSid: this.parentCallSid,
|
|
52
|
+
status: this.status,
|
|
53
|
+
limit: this.limit,
|
|
54
|
+
}));
|
|
55
|
+
/* eslint-disable multiline-ternary */
|
|
56
|
+
$.export("$summary", `Successfully fetched ${resp.length} call${resp.length === 1 ? "" : "s"}${
|
|
57
|
+
this.from ? ` from ${this.from}` : ""}${this.to ? ` to ${this.to}` : ""}`);
|
|
58
|
+
return resp;
|
|
59
|
+
},
|
|
60
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import twilio from "../../twilio.app.mjs";
|
|
2
|
+
import { omitEmptyStringValues } from "../../common/utils.mjs";
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
key: "twilio-list-message-media",
|
|
6
|
+
name: "List Message Media",
|
|
7
|
+
description: "Return a list of media associated with your message. [See the docs](https://www.twilio.com/docs/sms/api/media-resource#read-multiple-media-resources) for more information",
|
|
8
|
+
version: "0.1.0",
|
|
9
|
+
type: "action",
|
|
10
|
+
props: {
|
|
11
|
+
twilio,
|
|
12
|
+
messageId: {
|
|
13
|
+
propDefinition: [
|
|
14
|
+
twilio,
|
|
15
|
+
"messageId",
|
|
16
|
+
],
|
|
17
|
+
},
|
|
18
|
+
limit: {
|
|
19
|
+
propDefinition: [
|
|
20
|
+
twilio,
|
|
21
|
+
"limit",
|
|
22
|
+
],
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
async run({ $ }) {
|
|
26
|
+
const resp = await this.twilio.listMessageMedia(this.messageId, omitEmptyStringValues({
|
|
27
|
+
limit: this.limit,
|
|
28
|
+
}));
|
|
29
|
+
$.export("$summary", `Successfully fetched ${resp.length} media object${resp.length === 1
|
|
30
|
+
? ""
|
|
31
|
+
: "s"} associated with the message, "${this.messageId}"`);
|
|
32
|
+
return resp;
|
|
33
|
+
},
|
|
34
|
+
};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { phone } from "phone";
|
|
2
|
+
import twilio from "../../twilio.app.mjs";
|
|
3
|
+
import { omitEmptyStringValues } from "../../common/utils.mjs";
|
|
4
|
+
|
|
5
|
+
export default {
|
|
6
|
+
key: "twilio-list-messages",
|
|
7
|
+
name: "List Messages",
|
|
8
|
+
description: "Return a list of messages associated with your account. [See the docs](https://www.twilio.com/docs/sms/api/message-resource#read-multiple-message-resources) for more information",
|
|
9
|
+
version: "0.1.0",
|
|
10
|
+
type: "action",
|
|
11
|
+
props: {
|
|
12
|
+
twilio,
|
|
13
|
+
from: {
|
|
14
|
+
propDefinition: [
|
|
15
|
+
twilio,
|
|
16
|
+
"from",
|
|
17
|
+
],
|
|
18
|
+
description: "Read messages sent from only this phone number or alphanumeric sender ID. Format the phone number in E.164 format with a `+` and country code (e.g., `+16175551212`).",
|
|
19
|
+
optional: true,
|
|
20
|
+
},
|
|
21
|
+
to: {
|
|
22
|
+
propDefinition: [
|
|
23
|
+
twilio,
|
|
24
|
+
"to",
|
|
25
|
+
],
|
|
26
|
+
description: "Read messages sent to only this phone number. Format the phone number in E.164 format with a `+` and country code (e.g., `+16175551212`).",
|
|
27
|
+
optional: true,
|
|
28
|
+
},
|
|
29
|
+
limit: {
|
|
30
|
+
propDefinition: [
|
|
31
|
+
twilio,
|
|
32
|
+
"limit",
|
|
33
|
+
],
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
async run({ $ }) {
|
|
37
|
+
// Parse the given number into its E.164 equivalent
|
|
38
|
+
// The E.164 phone number will be included in the first element
|
|
39
|
+
// of the array, but the array will be empty if parsing fails.
|
|
40
|
+
// See https://www.npmjs.com/package/phone
|
|
41
|
+
let to = this.to;
|
|
42
|
+
if (this.to) {
|
|
43
|
+
const toParsed = phone(this.to);
|
|
44
|
+
if (!toParsed || !toParsed.phoneNumber) {
|
|
45
|
+
throw new Error(`Phone number ${this.to} couldn't be parsed as a valid number.`);
|
|
46
|
+
}
|
|
47
|
+
to = toParsed.phoneNumber;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const resp = await this.twilio.listMessages(omitEmptyStringValues({
|
|
51
|
+
to,
|
|
52
|
+
from: this.from,
|
|
53
|
+
limit: this.limit,
|
|
54
|
+
}));
|
|
55
|
+
/* eslint-disable multiline-ternary */
|
|
56
|
+
$.export("$summary", `Successfully fetched ${resp.length} message${resp.length === 1 ? "" : "s"}${
|
|
57
|
+
this.from ? ` from ${this.from}` : ""}${this.to ? ` to ${this.to}` : ""}`);
|
|
58
|
+
return resp;
|
|
59
|
+
},
|
|
60
|
+
};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import twilio from "../../twilio.app.mjs";
|
|
2
|
+
import { omitEmptyStringValues } from "../../common/utils.mjs";
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
key: "twilio-list-recording-transcriptions",
|
|
6
|
+
name: "List Recording Transcriptions",
|
|
7
|
+
description: "Return a set of transcriptions available for a recording. [See the docs](https://www.twilio.com/docs/voice/api/recording#fetch-a-recordings-transcriptions) for more information",
|
|
8
|
+
version: "0.1.0",
|
|
9
|
+
type: "action",
|
|
10
|
+
props: {
|
|
11
|
+
twilio,
|
|
12
|
+
recordingID: {
|
|
13
|
+
propDefinition: [
|
|
14
|
+
twilio,
|
|
15
|
+
"recordingID",
|
|
16
|
+
],
|
|
17
|
+
},
|
|
18
|
+
limit: {
|
|
19
|
+
propDefinition: [
|
|
20
|
+
twilio,
|
|
21
|
+
"limit",
|
|
22
|
+
],
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
async run({ $ }) {
|
|
26
|
+
const resp = await this.twilio.listRecordingTranscriptions(
|
|
27
|
+
this.recordingID,
|
|
28
|
+
omitEmptyStringValues({
|
|
29
|
+
limit: this.limit,
|
|
30
|
+
}),
|
|
31
|
+
);
|
|
32
|
+
$.export("$summary", `Successfully fetched ${resp.length} recording transcription${resp.length === 1
|
|
33
|
+
? ""
|
|
34
|
+
: "s"} for the recording, "${this.recordingID}"`);
|
|
35
|
+
return resp;
|
|
36
|
+
},
|
|
37
|
+
};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { phone } from "phone";
|
|
2
|
+
import twilio from "../../twilio.app.mjs";
|
|
3
|
+
import { callToString } from "../../common/utils.mjs";
|
|
4
|
+
|
|
5
|
+
export default {
|
|
6
|
+
key: "twilio-make-phone-call",
|
|
7
|
+
name: "Make a Phone Call",
|
|
8
|
+
description: "Make a phone call, passing text that Twilio will speak to the recipient of the call. [See the docs](https://www.twilio.com/docs/voice/api/call-resource#create-a-call-resource) for more information",
|
|
9
|
+
version: "0.1.0",
|
|
10
|
+
type: "action",
|
|
11
|
+
props: {
|
|
12
|
+
twilio,
|
|
13
|
+
from: {
|
|
14
|
+
propDefinition: [
|
|
15
|
+
twilio,
|
|
16
|
+
"from",
|
|
17
|
+
],
|
|
18
|
+
},
|
|
19
|
+
to: {
|
|
20
|
+
propDefinition: [
|
|
21
|
+
twilio,
|
|
22
|
+
"to",
|
|
23
|
+
],
|
|
24
|
+
},
|
|
25
|
+
text: {
|
|
26
|
+
label: "Text",
|
|
27
|
+
type: "string",
|
|
28
|
+
description: "The text you'd like Twilio to speak to the user when they pick up the phone.",
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
async run({ $ }) {
|
|
32
|
+
// Parse the given number into its E.164 equivalent
|
|
33
|
+
// The E.164 phone number will be included in the first element
|
|
34
|
+
// of the array, but the array will be empty if parsing fails.
|
|
35
|
+
// See https://www.npmjs.com/package/phone
|
|
36
|
+
const toParsed = phone(this.to);
|
|
37
|
+
console.log(toParsed);
|
|
38
|
+
if (!toParsed || !toParsed.phoneNumber) {
|
|
39
|
+
throw new Error(`Phone number ${this.to} couldn't be parsed as a valid number.`);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const data = {
|
|
43
|
+
to: toParsed.phoneNumber,
|
|
44
|
+
from: this.from,
|
|
45
|
+
twiml: `<Response><Say>${this.text}</Say></Response>`,
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const resp = await this.twilio.getClient().calls.create(data);
|
|
49
|
+
$.export("$summary", `Successfully made a new phone call, "${callToString(resp)}"`);
|
|
50
|
+
return resp;
|
|
51
|
+
},
|
|
52
|
+
};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { phone } from "phone";
|
|
2
|
+
import twilio from "../../twilio.app.mjs";
|
|
3
|
+
import { messageToString } from "../../common/utils.mjs";
|
|
4
|
+
|
|
5
|
+
export default {
|
|
6
|
+
key: "twilio-send-mms",
|
|
7
|
+
name: "Send MMS",
|
|
8
|
+
description: "Send an SMS with text and media files. [See the docs](https://www.twilio.com/docs/sms/api/message-resource#create-a-message-resource) for more information",
|
|
9
|
+
type: "action",
|
|
10
|
+
version: "0.1.0",
|
|
11
|
+
props: {
|
|
12
|
+
twilio,
|
|
13
|
+
from: {
|
|
14
|
+
propDefinition: [
|
|
15
|
+
twilio,
|
|
16
|
+
"from",
|
|
17
|
+
],
|
|
18
|
+
},
|
|
19
|
+
to: {
|
|
20
|
+
propDefinition: [
|
|
21
|
+
twilio,
|
|
22
|
+
"to",
|
|
23
|
+
],
|
|
24
|
+
},
|
|
25
|
+
body: {
|
|
26
|
+
propDefinition: [
|
|
27
|
+
twilio,
|
|
28
|
+
"body",
|
|
29
|
+
],
|
|
30
|
+
},
|
|
31
|
+
mediaUrl: {
|
|
32
|
+
propDefinition: [
|
|
33
|
+
twilio,
|
|
34
|
+
"mediaUrl",
|
|
35
|
+
],
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
async run({ $ }) {
|
|
39
|
+
// Parse the given number into its E.164 equivalent
|
|
40
|
+
// The E.164 phone number will be included in the first element
|
|
41
|
+
// of the array, but the array will be empty if parsing fails.
|
|
42
|
+
// See https://www.npmjs.com/package/phone
|
|
43
|
+
const toParsed = phone(this.to);
|
|
44
|
+
if (!toParsed || !toParsed.phoneNumber) {
|
|
45
|
+
throw new Error(`Phone number ${this.to} couldn't be parsed as a valid number.`);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const data = {
|
|
49
|
+
to: toParsed.phoneNumber,
|
|
50
|
+
from: this.from,
|
|
51
|
+
body: this.body,
|
|
52
|
+
mediaUrl: this.mediaUrl,
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
const resp = await this.twilio.getClient().messages.create(data);
|
|
56
|
+
$.export("$summary", `Successfully sent a new MMS, "${messageToString(resp)}"`);
|
|
57
|
+
return resp;
|
|
58
|
+
},
|
|
59
|
+
};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { phone } from "phone";
|
|
2
|
+
import twilio from "../../twilio.app.mjs";
|
|
3
|
+
import { messageToString } from "../../common/utils.mjs";
|
|
4
|
+
|
|
5
|
+
export default {
|
|
6
|
+
key: "twilio-send-sms",
|
|
7
|
+
name: "Send SMS",
|
|
8
|
+
description: "Send a simple text-only SMS. [See the docs](https://www.twilio.com/docs/sms/api/message-resource#create-a-message-resource) for more information",
|
|
9
|
+
type: "action",
|
|
10
|
+
version: "0.1.0",
|
|
11
|
+
props: {
|
|
12
|
+
twilio,
|
|
13
|
+
from: {
|
|
14
|
+
propDefinition: [
|
|
15
|
+
twilio,
|
|
16
|
+
"from",
|
|
17
|
+
],
|
|
18
|
+
},
|
|
19
|
+
to: {
|
|
20
|
+
propDefinition: [
|
|
21
|
+
twilio,
|
|
22
|
+
"to",
|
|
23
|
+
],
|
|
24
|
+
},
|
|
25
|
+
body: {
|
|
26
|
+
propDefinition: [
|
|
27
|
+
twilio,
|
|
28
|
+
"body",
|
|
29
|
+
],
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
async run({ $ }) {
|
|
33
|
+
// Parse the given number into its E.164 equivalent
|
|
34
|
+
// The E.164 phone number will be included in the first element
|
|
35
|
+
// of the array, but the array will be empty if parsing fails.
|
|
36
|
+
// See https://www.npmjs.com/package/phone
|
|
37
|
+
const toParsed = phone(this.to);
|
|
38
|
+
if (!toParsed || !toParsed.phoneNumber) {
|
|
39
|
+
throw new Error(`Phone number ${this.to} couldn't be parsed as a valid number.`);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const data = {
|
|
43
|
+
to: toParsed.phoneNumber,
|
|
44
|
+
from: this.from,
|
|
45
|
+
body: this.body,
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const resp = await this.twilio.getClient().messages.create(data);
|
|
49
|
+
$.export("$summary", `Successfully sent a new SMS, "${messageToString(resp)}"`);
|
|
50
|
+
return resp;
|
|
51
|
+
},
|
|
52
|
+
};
|
package/common/utils.mjs
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
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
|
+
timeBetween,
|
|
140
|
+
omitEmptyStringValues,
|
|
141
|
+
callToString,
|
|
142
|
+
messageToString,
|
|
143
|
+
recordingToString,
|
|
144
|
+
};
|