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"
-
-
-
Call your Twilio phone number
-
Be greeted by a robot voice saying "Hello World"
-
-
+
+
+
+
+
+
+
+
+
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"
+
+
+
Call your Twilio phone number
+
Be greeted by a robot voice saying "Hello World"
+
+
-
-
-
-
-
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
-
-
-
-
-
-
-
-
+
+
+
+
+
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
+
+
+
+
+
+
+
+
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 2ee54adc..3fe3b0c0 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);
};
diff --git a/masked-number/.env b/masked-number/.env
index fb964af7..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=+12223334444
+MY_PHONE_NUMBER=+1234567890
# description: The path to the webhook
# configurable: false
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!
-
-
+
+
-
-
-
-
-
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.
-
-
-
- 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.
-
-
Your recipient should receive your message from your Twilio phone number.
-
- When that recipient sends a reply to your Twilio phone number, it will be
- relayed to your personal phone number.
-
-
-
+
+
+
+
+
+
+
+
+
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.
+
+
+
+ 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.
+
+
+ Your recipient should receive your message from your Twilio phone
+ number.
+
+
+ When that recipient sends a reply to your Twilio phone number, it
+ will be relayed to your personal phone number.
+
+
+
-
-
-
-
-
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
- .
-
-
-
-
-
-
-
+
+
+
+
+
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 .
+
+
+
+
+
+
+
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 c3d9f801..55ca85cd 100644
--- a/masked-number/functions/relay-sms.protected.js
+++ b/masked-number/functions/relay-sms.protected.js
@@ -1,32 +1,88 @@
+/*
+ * 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..00db4c3d 100644
--- a/masked-number/package.json
+++ b/masked-number/package.json
@@ -2,5 +2,19 @@
"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",
+ "format": "prettier --write .",
+ "format:check": "prettier --check ."
+ },
+ "author": "",
+ "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 19e6b293..685b69fb 100644
--- a/masked-number/tests/relay-sms.test.js
+++ b/masked-number/tests/relay-sms.test.js
@@ -27,6 +27,12 @@ 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 +47,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) => {
@@ -73,9 +77,7 @@ describe('masked-number function template', () => {
const callback = (err, result) => {
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".`
- );
+ expect(twiml).toMatch(`${NO_RECIPIENT_ERROR}`);
done();
};
@@ -89,9 +91,7 @@ describe('masked-number function template', () => {
const callback = (err, result) => {
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.`
- );
+ expect(twiml).toMatch(`${ERROR_MESSAGE}`);
done();
};
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..7ea52f23
--- /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.
+