From fa09c2c2c762463764a4312640e81439ce71350a Mon Sep 17 00:00:00 2001 From: sbrij001 Date: Thu, 5 Sep 2024 15:43:06 -0400 Subject: [PATCH 1/9] updated functions file with comments so it is more readable --- masked-number/.env | 2 +- .../functions/relay-sms.protected.js | 59 ++++++++++++++++++- masked-number/package.json | 11 +++- 3 files changed, 69 insertions(+), 3 deletions(-) diff --git a/masked-number/.env b/masked-number/.env index fb964af7..aed0a93b 100644 --- a/masked-number/.env +++ b/masked-number/.env @@ -2,7 +2,7 @@ # format: phone_number # required: true # link: https://www.twilio.com/docs/glossary/what-e164 -MY_PHONE_NUMBER=+12223334444 +MY_PHONE_NUMBER=+13525739399 # description: The path to the webhook # configurable: false diff --git a/masked-number/functions/relay-sms.protected.js b/masked-number/functions/relay-sms.protected.js index c3d9f801..38658c8b 100644 --- a/masked-number/functions/relay-sms.protected.js +++ b/masked-number/functions/relay-sms.protected.js @@ -1,32 +1,89 @@ +/* + * Masking your phone number for SMS Forwarding and Responding + * + * Description: + * This function acts as a message-forwarding service + * If the message comes from the user, it forwards the message to another number. + * If it comes from someone else, it forwards it to the user. + * + * Contents: + * 1. Initialize Client and Response + * 2. Sender Check + * 3. Extracting Recipient and Message + * 4. Sending the Message + * 5. Handling Messages from Other Senders + */ + +/* + * 1. Initialize client and response + * + * Here you can initialize a Twilio client (client) to interact with Twilio's API. + * + * A twiml object is created to generate TwiML (Twilio Markup Language) responses, + * which are instructions that tell Twilio how to respond to an incoming message. + */ + +// Defines the main function handler for the Twilio Function. exports.handler = async function (context, event, callback) { const client = context.getTwilioClient(); const twiml = new Twilio.twiml.MessagingResponse(); +/* + * 2. Checking the Sender + * + * Here you can checks if the message came from a specific number. + * This condition ensures that only the user with this phone number can send outgoing messages. + */ if (event.From === context.MY_PHONE_NUMBER) { + // Looks for a : in the message body to separate the recipient's phone number from the message text. const separatorPosition = event.Body.indexOf(':'); + // If there is no :, a response is sent to the sender with a message explaining the required format: recipientPhoneNumber: message. if (separatorPosition < 1) { twiml.message( 'You need to specify a recipient number and a ":" before the message. For example, "+12223334444: message".' ); + + /* + * 3. Extracting Recipient and Message + * + * Here you can processes the incoming message body + * to extract the recipient's phone number and the actual message content + */ + } else { + // Extracts the recipient's phone number from the part of the message before the : and removes any extra whitespace. const recipientNumber = event.Body.substr(0, separatorPosition).trim(); + // Extracts the actual message from the part of the message after the ':' const messageBody = event.Body.substr(separatorPosition + 1).trim(); + /* + * 4. Sending the Message + * + * Here a try-catch block attempts to send an SMS message using the Twilio API + */ try { + // Sends the SMS to recipientNumber with the message messageBody. await client.messages.create({ to: recipientNumber, from: event.To, body: messageBody, }); - + // If successful, callback(null) is called to signal that the function executed successfully without returning any TwiML. return callback(null); + // If there is an error (e.g., an invalid phone number), a failure message is sent to the sender explaining that the phone number might be incorrect. } catch (err) { twiml.message( 'There was an issue with the phone number you entered; please verify it is correct and try again.' ); } } + /* + * 5. Handling Messages from Other Senders + * + * If the message is not from context.MY_PHONE_NUMBER, + * the function forwards it to the number stored in context.MY_PHONE_NUMBER, + */ } else { twiml.message( { to: context.MY_PHONE_NUMBER }, diff --git a/masked-number/package.json b/masked-number/package.json index 249bce8d..687bc06a 100644 --- a/masked-number/package.json +++ b/masked-number/package.json @@ -2,5 +2,14 @@ "name": "masked-number", "version": "1.0.0", "private": true, - "dependencies": {} + "description": "Uses a Twilio phone number to relay SMS messages to and from your phone; since the other party only sees your Twilio number, this effectively allows you to mask your phone number for privacy purposes.", + "main": "index.js", + "directories": { + "test": "tests" + }, + "scripts": { + "test": "jest" + }, + "author": "", + "license": "ISC" } From b95fae0acb22a9c83cc60ce7f94cb671a45905f3 Mon Sep 17 00:00:00 2001 From: sbrij001 Date: Thu, 5 Sep 2024 15:48:08 -0400 Subject: [PATCH 2/9] Fix code formatting with Prettier --- masked-number/assets/index.html | 246 +++++++++++------- masked-number/changelog.md | 3 +- .../functions/relay-sms.protected.js | 59 +++-- 3 files changed, 178 insertions(+), 130 deletions(-) diff --git a/masked-number/assets/index.html b/masked-number/assets/index.html index 1e172050..528925a9 100644 --- a/masked-number/assets/index.html +++ b/masked-number/assets/index.html @@ -1,105 +1,153 @@ - + - - - - - Get started with your Twilio Functions! + + + + + Get started with your Twilio Functions! - - + + - - - - -
-
- - -
+ + + + +
+
+ -
-
-

- -
-

Welcome!

-

Your live application with Twilio is ready to use!

-
-

-
-

Get started with your application

-

- Follow these steps to try out your new app: -

-

- This app masks your phone number for SMS messages by relaying them through a - Twilio phone number. -

-
    -
  1. - Text your Twilio phone number with a recipient phone number, a - :, and a message. For example, to send the message "hello" to - the number "+12223334444", text your Twilio phone number with: - +12223334444: hello. -
  2. -
  3. Your recipient should receive your message from your Twilio phone number.
  4. -
  5. - When that recipient sends a reply to your Twilio phone number, it will be - relayed to your personal phone number. -
  6. -
-
+ +
+
+
+
+

+ +
+

Welcome!

+

Your live application with Twilio is ready to use!

+
+

+
+

Get started with your application

+

Follow these steps to try out your new app:

+

+ This app masks your phone number for SMS messages by relaying them + through a Twilio phone number. +

+
    +
  1. + Text your Twilio phone number with a recipient phone number, a + :, and a message. For example, to send the message + "hello" to the number "+12223334444", text your Twilio phone + number with: +12223334444: hello. +
  2. +
  3. + Your recipient should receive your message from your Twilio phone + number. +
  4. +
  5. + When that recipient sends a reply to your Twilio phone number, it + will be relayed to your personal phone number. +
  6. +
+
-
- -
-
-

Troubleshooting

-
    -
  • - Check the - - phone number configuration - - and make sure the Twilio phone number you want for your app has a SMS webhook - configured to point at the following URL -
    - - -
    -
  • -
  • - Ensure that MY_PHONE_NUMBER is set to the phone number you want - to relay messages to, in - - E.164 format - . -
  • -
-
-
-
-
- We can't wait to see what you build. -
- +
+ +
+
+

Troubleshooting

+
    +
  • + Check the + + phone number configuration + + and make sure the Twilio phone number you want for your app has a + SMS webhook configured to point at the following URL +
    + + +
    +
  • +
  • + Ensure that MY_PHONE_NUMBER is set to the phone + number you want to relay messages to, in + + E.164 format . +
  • +
+
+
+ +
+ We can't wait to see what you build. +
+ diff --git a/masked-number/changelog.md b/masked-number/changelog.md index 3982d461..144828c2 100644 --- a/masked-number/changelog.md +++ b/masked-number/changelog.md @@ -3,6 +3,7 @@ ## [Unreleased] ## [1.0.0] + ### Added -- Initial release. +- Initial release. diff --git a/masked-number/functions/relay-sms.protected.js b/masked-number/functions/relay-sms.protected.js index 38658c8b..55ca85cd 100644 --- a/masked-number/functions/relay-sms.protected.js +++ b/masked-number/functions/relay-sms.protected.js @@ -2,8 +2,8 @@ * Masking your phone number for SMS Forwarding and Responding * * Description: - * This function acts as a message-forwarding service - * If the message comes from the user, it forwards the message to another number. + * This function acts as a message-forwarding service + * If the message comes from the user, it forwards the message to another number. * If it comes from someone else, it forwards it to the user. * * Contents: @@ -15,11 +15,11 @@ */ /* - * 1. Initialize client and response + * 1. Initialize client and response * * Here you can initialize a Twilio client (client) to interact with Twilio's API. * - * A twiml object is created to generate TwiML (Twilio Markup Language) responses, + * A twiml object is created to generate TwiML (Twilio Markup Language) responses, * which are instructions that tell Twilio how to respond to an incoming message. */ @@ -28,40 +28,39 @@ exports.handler = async function (context, event, callback) { const client = context.getTwilioClient(); const twiml = new Twilio.twiml.MessagingResponse(); -/* - * 2. Checking the Sender - * - * Here you can checks if the message came from a specific number. - * This condition ensures that only the user with this phone number can send outgoing messages. - */ + /* + * 2. Checking the Sender + * + * Here you can checks if the message came from a specific number. + * This condition ensures that only the user with this phone number can send outgoing messages. + */ if (event.From === context.MY_PHONE_NUMBER) { // Looks for a : in the message body to separate the recipient's phone number from the message text. const separatorPosition = event.Body.indexOf(':'); - // If there is no :, a response is sent to the sender with a message explaining the required format: recipientPhoneNumber: message. + // If there is no :, a response is sent to the sender with a message explaining the required format: recipientPhoneNumber: message. if (separatorPosition < 1) { twiml.message( 'You need to specify a recipient number and a ":" before the message. For example, "+12223334444: message".' ); - - /* - * 3. Extracting Recipient and Message - * - * Here you can processes the incoming message body - * to extract the recipient's phone number and the actual message content - */ + /* + * 3. Extracting Recipient and Message + * + * Here you can processes the incoming message body + * to extract the recipient's phone number and the actual message content + */ } else { // Extracts the recipient's phone number from the part of the message before the : and removes any extra whitespace. const recipientNumber = event.Body.substr(0, separatorPosition).trim(); // Extracts the actual message from the part of the message after the ':' const messageBody = event.Body.substr(separatorPosition + 1).trim(); - /* - * 4. Sending the Message - * - * Here a try-catch block attempts to send an SMS message using the Twilio API - */ + /* + * 4. Sending the Message + * + * Here a try-catch block attempts to send an SMS message using the Twilio API + */ try { // Sends the SMS to recipientNumber with the message messageBody. await client.messages.create({ @@ -71,19 +70,19 @@ exports.handler = async function (context, event, callback) { }); // If successful, callback(null) is called to signal that the function executed successfully without returning any TwiML. return callback(null); - // If there is an error (e.g., an invalid phone number), a failure message is sent to the sender explaining that the phone number might be incorrect. + // If there is an error (e.g., an invalid phone number), a failure message is sent to the sender explaining that the phone number might be incorrect. } catch (err) { twiml.message( 'There was an issue with the phone number you entered; please verify it is correct and try again.' ); } } - /* - * 5. Handling Messages from Other Senders - * - * If the message is not from context.MY_PHONE_NUMBER, - * the function forwards it to the number stored in context.MY_PHONE_NUMBER, - */ + /* + * 5. Handling Messages from Other Senders + * + * If the message is not from context.MY_PHONE_NUMBER, + * the function forwards it to the number stored in context.MY_PHONE_NUMBER, + */ } else { twiml.message( { to: context.MY_PHONE_NUMBER }, From 061349b7f458409f51fbd291fe2480a90b7446e0 Mon Sep 17 00:00:00 2001 From: sbrij001 Date: Sun, 8 Sep 2024 12:24:32 -0400 Subject: [PATCH 3/9] improve relaySms function tests with constants and async handling --- masked-number/tests/relay-sms.test.js | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/masked-number/tests/relay-sms.test.js b/masked-number/tests/relay-sms.test.js index 19e6b293..943597c0 100644 --- a/masked-number/tests/relay-sms.test.js +++ b/masked-number/tests/relay-sms.test.js @@ -27,6 +27,10 @@ const baseEvent = { Body: '+16667778888: test message', }; +// Define your constant error messages here +const ERROR_MESSAGE = 'There was an issue with the phone number you entered; please verify it is correct and try again.'; +const NO_RECIPIENT_ERROR = 'You need to specify a recipient number and a ":" before the message. For example, "+12223334444: message".'; + beforeAll(() => { helpers.setup(context); }); @@ -41,16 +45,14 @@ beforeEach(() => { }); describe('masked-number function template', () => { - it('should send a message to a given phone number', (done) => { + it('should send a message to a given phone number', async () => { const event = { ...baseEvent }; const callback = (err, _result) => { expect(err).toBeFalsy(); expect(mockTwilioClient.messages.create).toHaveBeenCalled(); - - done(); }; - relaySms(context, event, callback); + await relaySms(context, event, callback); }); it('should relay messages from other phone numbers', (done) => { @@ -74,7 +76,7 @@ describe('masked-number function template', () => { expect(err).toBeFalsy(); const twiml = result.toString(); expect(twiml).toMatch( - `You need to specify a recipient number and a ":" before the message. For example, "+12223334444: message".` + `${NO_RECIPIENT_ERROR}` ); done(); @@ -90,7 +92,7 @@ describe('masked-number function template', () => { expect(err).toBeFalsy(); const twiml = result.toString(); expect(twiml).toMatch( - `There was an issue with the phone number you entered; please verify it is correct and try again.` + `${ERROR_MESSAGE}` ); done(); From d846c17a42e039af952e6bd6289336361439f920 Mon Sep 17 00:00:00 2001 From: sbrij001 Date: Sun, 8 Sep 2024 12:30:04 -0400 Subject: [PATCH 4/9] installed prettier --- masked-number/package.json | 9 +++++++-- masked-number/tests/relay-sms.test.js | 14 ++++++-------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/masked-number/package.json b/masked-number/package.json index 687bc06a..00db4c3d 100644 --- a/masked-number/package.json +++ b/masked-number/package.json @@ -8,8 +8,13 @@ "test": "tests" }, "scripts": { - "test": "jest" + "test": "jest", + "format": "prettier --write .", + "format:check": "prettier --check ." }, "author": "", - "license": "ISC" + "license": "ISC", + "devDependencies": { + "prettier": "^3.3.3" + } } diff --git a/masked-number/tests/relay-sms.test.js b/masked-number/tests/relay-sms.test.js index 943597c0..685b69fb 100644 --- a/masked-number/tests/relay-sms.test.js +++ b/masked-number/tests/relay-sms.test.js @@ -28,8 +28,10 @@ const baseEvent = { }; // Define your constant error messages here -const ERROR_MESSAGE = 'There was an issue with the phone number you entered; please verify it is correct and try again.'; -const NO_RECIPIENT_ERROR = 'You need to specify a recipient number and a ":" before the message. For example, "+12223334444: message".'; +const ERROR_MESSAGE = + 'There was an issue with the phone number you entered; please verify it is correct and try again.'; +const NO_RECIPIENT_ERROR = + 'You need to specify a recipient number and a ":" before the message. For example, "+12223334444: message".'; beforeAll(() => { helpers.setup(context); @@ -75,9 +77,7 @@ describe('masked-number function template', () => { const callback = (err, result) => { expect(err).toBeFalsy(); const twiml = result.toString(); - expect(twiml).toMatch( - `${NO_RECIPIENT_ERROR}` - ); + expect(twiml).toMatch(`${NO_RECIPIENT_ERROR}`); done(); }; @@ -91,9 +91,7 @@ describe('masked-number function template', () => { const callback = (err, result) => { expect(err).toBeFalsy(); const twiml = result.toString(); - expect(twiml).toMatch( - `${ERROR_MESSAGE}` - ); + expect(twiml).toMatch(`${ERROR_MESSAGE}`); done(); }; From 5076ecce8b4e0e4918c8316333eb33bc74d5ed2f Mon Sep 17 00:00:00 2001 From: sbrij001 Date: Sun, 8 Sep 2024 13:20:29 -0400 Subject: [PATCH 5/9] Added comments to the send-messages.js file so that it's more comprehensive --- .../sms-notifications/.gitignore | 133 ++++++++++++++++++ sms-notifications/sms-notifications/.nvmrc | 1 + .../sms-notifications/.twilioserverlessrc | 42 ++++++ .../sms-notifications/assets/index.html | 86 +++++++++++ .../assets/message.private.js | 6 + .../sms-notifications/assets/style.css | 73 ++++++++++ .../functions/hello-world.js | 5 + .../functions/private-message.js | 9 ++ .../functions/sms/reply.protected.js | 5 + .../sms-notifications/package.json | 20 +++ 10 files changed, 380 insertions(+) create mode 100644 sms-notifications/sms-notifications/.gitignore create mode 100644 sms-notifications/sms-notifications/.nvmrc create mode 100644 sms-notifications/sms-notifications/.twilioserverlessrc create mode 100644 sms-notifications/sms-notifications/assets/index.html create mode 100644 sms-notifications/sms-notifications/assets/message.private.js create mode 100644 sms-notifications/sms-notifications/assets/style.css create mode 100644 sms-notifications/sms-notifications/functions/hello-world.js create mode 100644 sms-notifications/sms-notifications/functions/private-message.js create mode 100644 sms-notifications/sms-notifications/functions/sms/reply.protected.js create mode 100644 sms-notifications/sms-notifications/package.json diff --git a/sms-notifications/sms-notifications/.gitignore b/sms-notifications/sms-notifications/.gitignore new file mode 100644 index 00000000..ca7e037f --- /dev/null +++ b/sms-notifications/sms-notifications/.gitignore @@ -0,0 +1,133 @@ +# Twilio Serverless +.twiliodeployinfo + +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* +.pnpm-debug.log* + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage +*.lcov + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# Snowpack dependency directory (https://snowpack.dev/) +web_modules/ + +# TypeScript cache +*.tsbuildinfo + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional stylelint cache +.stylelintcache + +# Microbundle cache +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variable files +.env +.env.development.local +.env.test.local +.env.production.local +.env.local + +# parcel-bundler cache (https://parceljs.org/) +.cache +.parcel-cache + +# Next.js build output +.next +out + +# Nuxt.js build / generate output +.nuxt +dist + +# Gatsby files +.cache/ +# Comment in the public line in if your project uses Gatsby and not Next.js +# https://nextjs.org/blog/next-9-1#public-directory-support +# public + +# vuepress build output +.vuepress/dist + +# vuepress v2.x temp and cache directory +.temp +.cache + +# Docusaurus cache and generated files +.docusaurus + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +# TernJS port file +.tern-port + +# Stores VSCode versions used for testing VSCode extensions +.vscode-test + +# yarn v2 +.yarn/cache +.yarn/unplugged +.yarn/build-state.yml +.yarn/install-state.gz +.pnp.* diff --git a/sms-notifications/sms-notifications/.nvmrc b/sms-notifications/sms-notifications/.nvmrc new file mode 100644 index 00000000..25bf17fc --- /dev/null +++ b/sms-notifications/sms-notifications/.nvmrc @@ -0,0 +1 @@ +18 \ No newline at end of file diff --git a/sms-notifications/sms-notifications/.twilioserverlessrc b/sms-notifications/sms-notifications/.twilioserverlessrc new file mode 100644 index 00000000..a7f5a1cb --- /dev/null +++ b/sms-notifications/sms-notifications/.twilioserverlessrc @@ -0,0 +1,42 @@ +{ + "commands": {}, + "environments": {}, + "projects": {}, + // "assets": true /* Upload assets. Can be turned off with --no-assets */, + // "assetsFolder": null /* Specific folder name to be used for static assets */, + // "buildSid": null /* An existing Build SID to deploy to the new environment */, + // "createEnvironment": false /* Creates environment if it couldn't find it. */, + // "cwd": null /* Sets the directory of your existing Serverless project. Defaults to current directory */, + // "detailedLogs": false /* Toggles detailed request logging by showing request body and query params */, + // "edge": null /* Twilio API Region */, + // "env": null /* Path to .env file for environment variables that should be installed */, + // "environment": "dev" /* The environment name (domain suffix) you want to use for your deployment. Alternatively you can specify an environment SID starting with ZE. */, + // "extendedOutput": false /* Show an extended set of properties on the output */, + // "force": false /* Will run deployment in force mode. Can be dangerous. */, + // "forkProcess": true /* Disable forking function processes to emulate production environment */, + // "functionSid": null /* Specific Function SID to retrieve logs for */, + // "functions": true /* Upload functions. Can be turned off with --no-functions */, + // "functionsFolder": null /* Specific folder name to be used for static functions */, + // "inspect": null /* Enables Node.js debugging protocol */, + // "inspectBrk": null /* Enables Node.js debugging protocol, stops execution until debugger is attached */, + // "legacyMode": false /* Enables legacy mode, it will prefix your asset paths with /assets */, + // "live": true /* Always serve from the current functions (no caching) */, + // "loadLocalEnv": false /* Includes the local environment variables */, + // "loadSystemEnv": false /* Uses system environment variables as fallback for variables specified in your .env file. Needs to be used with --env explicitly specified. */, + // "logCacheSize": null /* Tailing the log endpoint will cache previously seen entries to avoid duplicates. The cache is topped at a maximum of 1000 by default. This option can change that. */, + // "logLevel": "info" /* Level of logging messages. */, + // "logs": true /* Toggles request logging */, + // "ngrok": null /* Uses ngrok to create a public url. Pass a string to set the subdomain (requires a paid-for ngrok account). */, + // "outputFormat": "" /* Output the results in a different format */, + // "overrideExistingProject": false /* Deploys Serverless project to existing service if a naming conflict has been found. */, + // "port": "3000" /* Override default port of 3000 */, + // "production": false /* Promote build to the production environment (no domain suffix). Overrides environment flag */, + // "properties": null /* Specify the output properties you want to see. Works best on single types */, + // "region": null /* Twilio API Region */, + "runtime": "node18" /* The version of Node.js to deploy the build to. (node18) */, + // "serviceName": null /* Overrides the name of the Serverless project. Default: the name field in your package.json */, + // "serviceSid": null /* SID of the Twilio Serverless Service to deploy to */, + // "sourceEnvironment": null /* SID or suffix of an existing environment you want to deploy from. */, + // "tail": false /* Continuously stream the logs */, + // "template": null /* undefined */, +} \ No newline at end of file diff --git a/sms-notifications/sms-notifications/assets/index.html b/sms-notifications/sms-notifications/assets/index.html new file mode 100644 index 00000000..90e8acb6 --- /dev/null +++ b/sms-notifications/sms-notifications/assets/index.html @@ -0,0 +1,86 @@ + + + + + + + + Hello Twilio Serverless! + + +

Hello Twilio Serverless!

+ +
+

+ Congratulations you just started a new Twilio + Serverless project. +

+ +

Assets

+

+ Assets are static files, like HTML, CSS, JavaScript, images or audio + files. +

+ +

+ This HTML page is an example of a public asset, you can + access this by loading it in the browser. The HTML also refers to + another public asset for CSS styles. +

+

+ You can also have private assets, there is an example + private asset called message.private.js in the + /assets directory. This file cannot be loaded in the + browser, but you can load it as part of a function by finding its path + using Runtime.getAssets() and then requiring the file. + There is an example of this in + /functions/private-message.js. +

+ +

Functions

+

+ Functions are JavaScript files that will respond to incoming HTTP + requests. There are public and + protected functions. +

+ +

+ Public functions respond to all HTTP requests. There is + an example of a public function in + /functions/hello-world.js. +

+ +

+ Protected functions will only respond to HTTP requests + with a valid Twilio signature in the header. You can read more about + validating requests from Twilio in the documentation. There is an example of a protected function in + /functions/sms/reply.protected.js +

+ +

twilio-run

+ +

+ Functions and assets are served, deployed and debugged using + twilio-run. You can serve the project locally with the command + npm start which is really running + twilio-run --env under the hood. If you want to see what + else you can do with twilio-run enter + npx twilio-run --help on the command line or check out + the project documentation on GitHub. +

+
+ +
+

+ Made with 💖 by your friends at + Twilio +

+
+ + diff --git a/sms-notifications/sms-notifications/assets/message.private.js b/sms-notifications/sms-notifications/assets/message.private.js new file mode 100644 index 00000000..d7bbe31b --- /dev/null +++ b/sms-notifications/sms-notifications/assets/message.private.js @@ -0,0 +1,6 @@ +// This is an example of of a private message +const privateMessage = () => { + return 'This is private!'; +}; + +module.exports = privateMessage; diff --git a/sms-notifications/sms-notifications/assets/style.css b/sms-notifications/sms-notifications/assets/style.css new file mode 100644 index 00000000..2a4522db --- /dev/null +++ b/sms-notifications/sms-notifications/assets/style.css @@ -0,0 +1,73 @@ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +::selection { + background: #f22f46; + color: white; +} + +body { + font-family: -apple-system, system-ui, BlinkMacSystemFont, 'Segoe UI', Roboto, + 'Helvetica Neue', Arial, sans-serif; + color: #0d122b; + border-top: 5px solid #f22f46; +} + +header { + padding: 2em; + margin-bottom: 2em; + max-width: 800px; + margin: 0 auto; +} + +header h1 { + padding-bottom: 14px; + border-bottom: 1px solid rgba(148, 151, 155, 0.2); +} + +a { + color: #008cff; +} + +main { + margin: 0 auto 6em; + padding: 0 2em; + max-width: 800px; +} + +main p { + margin-bottom: 2em; +} + +main p code { + font-size: 16px; + font-family: 'Fira Mono', monospace; + color: #f22f46; + background-color: #f9f9f9; + box-shadow: inset 0 0 0 1px #e8e8e8; + font-size: inherit; + line-height: 1.2; + padding: 0.15em 0.4em; + border-radius: 4px; + display: inline-block; + white-space: pre-wrap; +} + +main h2 { + margin-bottom: 1em; +} + +footer { + margin: 0 auto; + max-width: 800px; + text-align: center; +} + +footer p { + border-top: 1px solid rgba(148, 151, 155, 0.2); + padding-top: 2em; + margin: 0 2em; +} diff --git a/sms-notifications/sms-notifications/functions/hello-world.js b/sms-notifications/sms-notifications/functions/hello-world.js new file mode 100644 index 00000000..9e1c9e44 --- /dev/null +++ b/sms-notifications/sms-notifications/functions/hello-world.js @@ -0,0 +1,5 @@ +exports.handler = function(context, event, callback) { + const twiml = new Twilio.twiml.VoiceResponse(); + twiml.say('Hello World!'); + callback(null, twiml); +}; diff --git a/sms-notifications/sms-notifications/functions/private-message.js b/sms-notifications/sms-notifications/functions/private-message.js new file mode 100644 index 00000000..60c888bf --- /dev/null +++ b/sms-notifications/sms-notifications/functions/private-message.js @@ -0,0 +1,9 @@ +exports.handler = function(context, event, callback) { + const assets = Runtime.getAssets(); + const privateMessageAsset = assets['/message.js']; + const privateMessagePath = privateMessageAsset.path; + const privateMessage = require(privateMessagePath); + const twiml = new Twilio.twiml.MessagingResponse(); + twiml.message(privateMessage()); + callback(null, twiml); +}; diff --git a/sms-notifications/sms-notifications/functions/sms/reply.protected.js b/sms-notifications/sms-notifications/functions/sms/reply.protected.js new file mode 100644 index 00000000..70916570 --- /dev/null +++ b/sms-notifications/sms-notifications/functions/sms/reply.protected.js @@ -0,0 +1,5 @@ +exports.handler = function(context, event, callback) { + const twiml = new Twilio.twiml.MessagingResponse(); + twiml.message('Hello World!'); + callback(null, twiml); +}; diff --git a/sms-notifications/sms-notifications/package.json b/sms-notifications/sms-notifications/package.json new file mode 100644 index 00000000..84cef996 --- /dev/null +++ b/sms-notifications/sms-notifications/package.json @@ -0,0 +1,20 @@ +{ + "name": "sms-notifications", + "version": "0.0.0", + "private": true, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "start": "twilio-run", + "deploy": "twilio-run deploy" + }, + "dependencies": { + "twilio": "5.0.3", + "@twilio/runtime-handler": "2.0.3" + }, + "devDependencies": { + "twilio-run": "^4.0.3" + }, + "engines": { + "node": "18" + } +} \ No newline at end of file From b8ea2fcbadd47e5b7f5f5c0e1522f45daff1ccf3 Mon Sep 17 00:00:00 2001 From: sbrij001 Date: Sun, 8 Sep 2024 13:24:26 -0400 Subject: [PATCH 6/9] Fix code formatting with Prettier --- sms-notifications/sms-notifications/assets/index.html | 2 +- sms-notifications/sms-notifications/functions/hello-world.js | 2 +- .../sms-notifications/functions/private-message.js | 2 +- .../sms-notifications/functions/sms/reply.protected.js | 2 +- sms-notifications/sms-notifications/package.json | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/sms-notifications/sms-notifications/assets/index.html b/sms-notifications/sms-notifications/assets/index.html index 90e8acb6..7ea52f23 100644 --- a/sms-notifications/sms-notifications/assets/index.html +++ b/sms-notifications/sms-notifications/assets/index.html @@ -1,4 +1,4 @@ - + diff --git a/sms-notifications/sms-notifications/functions/hello-world.js b/sms-notifications/sms-notifications/functions/hello-world.js index 9e1c9e44..8fde2a79 100644 --- a/sms-notifications/sms-notifications/functions/hello-world.js +++ b/sms-notifications/sms-notifications/functions/hello-world.js @@ -1,4 +1,4 @@ -exports.handler = function(context, event, callback) { +exports.handler = function (context, event, callback) { const twiml = new Twilio.twiml.VoiceResponse(); twiml.say('Hello World!'); callback(null, twiml); diff --git a/sms-notifications/sms-notifications/functions/private-message.js b/sms-notifications/sms-notifications/functions/private-message.js index 60c888bf..ec200d4a 100644 --- a/sms-notifications/sms-notifications/functions/private-message.js +++ b/sms-notifications/sms-notifications/functions/private-message.js @@ -1,4 +1,4 @@ -exports.handler = function(context, event, callback) { +exports.handler = function (context, event, callback) { const assets = Runtime.getAssets(); const privateMessageAsset = assets['/message.js']; const privateMessagePath = privateMessageAsset.path; diff --git a/sms-notifications/sms-notifications/functions/sms/reply.protected.js b/sms-notifications/sms-notifications/functions/sms/reply.protected.js index 70916570..6e768af1 100644 --- a/sms-notifications/sms-notifications/functions/sms/reply.protected.js +++ b/sms-notifications/sms-notifications/functions/sms/reply.protected.js @@ -1,4 +1,4 @@ -exports.handler = function(context, event, callback) { +exports.handler = function (context, event, callback) { const twiml = new Twilio.twiml.MessagingResponse(); twiml.message('Hello World!'); callback(null, twiml); diff --git a/sms-notifications/sms-notifications/package.json b/sms-notifications/sms-notifications/package.json index 84cef996..3e41ee57 100644 --- a/sms-notifications/sms-notifications/package.json +++ b/sms-notifications/sms-notifications/package.json @@ -17,4 +17,4 @@ "engines": { "node": "18" } -} \ No newline at end of file +} From f4b997fc653b4e71a88be96c8b32315cb67d6061 Mon Sep 17 00:00:00 2001 From: sbrij001 Date: Sun, 8 Sep 2024 13:39:48 -0400 Subject: [PATCH 7/9] Added comments to the hello-voice.js file so that it's more comprehensive --- hello-voice/functions/hello-voice.protected.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/hello-voice/functions/hello-voice.protected.js b/hello-voice/functions/hello-voice.protected.js index 2ee54adc..e4147452 100644 --- a/hello-voice/functions/hello-voice.protected.js +++ b/hello-voice/functions/hello-voice.protected.js @@ -1,5 +1,14 @@ +/* + * hello-voice.protected.js + * This file contains an AWS Lambda function handler that generates a Twilio Voice Response. When triggered, it creates a TwiML response that instructs Twilio to speak "Hello World" to the caller. + */ + +// This is an AWS Lambda function handler for a Twilio Voice Response exports.handler = function (context, event, callback) { + // Create a new TwiML VoiceResponse object const twiml = new Twilio.twiml.VoiceResponse(); + // Add a 'Say' verb to the TwiML response, which will speak the text 'Hello World' to the caller twiml.say('Hello World'); + // End the function by calling the callback with the generated TwiML response callback(null, twiml); }; From 7947aba5cf535d90fd36e7010113ce26a4bf5ac2 Mon Sep 17 00:00:00 2001 From: sbrij001 Date: Sun, 8 Sep 2024 13:41:47 -0400 Subject: [PATCH 8/9] Fix code formatting with Prettier --- hello-voice/assets/index.html | 217 +++++++++++------- hello-voice/changelog.md | 3 +- .../functions/hello-voice.protected.js | 2 +- 3 files changed, 134 insertions(+), 88 deletions(-) diff --git a/hello-voice/assets/index.html b/hello-voice/assets/index.html index ed4ef115..56836ea0 100644 --- a/hello-voice/assets/index.html +++ b/hello-voice/assets/index.html @@ -1,92 +1,137 @@ - + - - - - - Get started with your Twilio Functions! + + + + + Get started with your Twilio Functions! - - + + - - - - -
-
- - -
+ + + + +
+
+ -
-
-

- -
-

Welcome!

-

Your live application with Twilio is ready to use!

-
-

-
-

Get started with your application

-

- Follow these steps to try out your new app: -

-

- This app is a basic Twilio Voice TwiML template Function that will return the - TwiML - to say "Hello World" -

-
    -
  1. Call your Twilio phone number
  2. -
  3. Be greeted by a robot voice saying "Hello World"
  4. -
-
+ +
+
+
+
+

+ +
+

Welcome!

+

Your live application with Twilio is ready to use!

+
+

+
+

Get started with your application

+

Follow these steps to try out your new app:

+

+ This app is a basic Twilio Voice TwiML template Function that will + return the + TwiML + to say "Hello World" +

+
    +
  1. Call your Twilio phone number
  2. +
  3. Be greeted by a robot voice saying "Hello World"
  4. +
+
-
- -
-
-

Troubleshooting

-
    -
  • - Check the - - phone number configuration - - and make sure the Twilio phone number you want for your app has a voice webhook - configured to point at the following URL -
    - - -
    -
  • -
-
-
-
-
- We can't wait to see what you build. -
- +
+ +
+
+

Troubleshooting

+
    +
  • + Check the + + phone number configuration + + and make sure the Twilio phone number you want for your app has a + voice webhook configured to point at the following URL +
    + + +
    +
  • +
+
+
+ +
+ We can't wait to see what you build. +
+ diff --git a/hello-voice/changelog.md b/hello-voice/changelog.md index 3982d461..144828c2 100644 --- a/hello-voice/changelog.md +++ b/hello-voice/changelog.md @@ -3,6 +3,7 @@ ## [Unreleased] ## [1.0.0] + ### Added -- Initial release. +- Initial release. diff --git a/hello-voice/functions/hello-voice.protected.js b/hello-voice/functions/hello-voice.protected.js index e4147452..3fe3b0c0 100644 --- a/hello-voice/functions/hello-voice.protected.js +++ b/hello-voice/functions/hello-voice.protected.js @@ -1,6 +1,6 @@ /* * hello-voice.protected.js - * This file contains an AWS Lambda function handler that generates a Twilio Voice Response. When triggered, it creates a TwiML response that instructs Twilio to speak "Hello World" to the caller. + * This file contains an AWS Lambda function handler that generates a Twilio Voice Response. When triggered, it creates a TwiML response that instructs Twilio to speak "Hello World" to the caller. */ // This is an AWS Lambda function handler for a Twilio Voice Response From ed7cd74277f8d1592c61319317d0627e1771f0ac Mon Sep 17 00:00:00 2001 From: sbrij001 Date: Mon, 9 Sep 2024 16:10:18 -0400 Subject: [PATCH 9/9] updated env file --- masked-number/.env | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/masked-number/.env b/masked-number/.env index aed0a93b..77d1dffe 100644 --- a/masked-number/.env +++ b/masked-number/.env @@ -2,7 +2,7 @@ # format: phone_number # required: true # link: https://www.twilio.com/docs/glossary/what-e164 -MY_PHONE_NUMBER=+13525739399 +MY_PHONE_NUMBER=+1234567890 # description: The path to the webhook # configurable: false