Skip to content

Update voicemail template #554

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Aug 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion voicemail/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ twilio serverless:init sample --template=voicemail && cd sample
twilio serverless:start --ngrok
```

5. Set your incoming call webhook URL for the phone number you want to configure to `https://<your-ngrok-code>.ngrok.io/voicemail
5. Set your incoming call webhook URL for the phone number you want to configure to `https://<your-ngrok-code>.ngrok.io/voicemail`

ℹ️ Check the developer console and terminal for any errors, make sure you've set your environment variables.

Expand Down
3 changes: 2 additions & 1 deletion voicemail/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
## [Unreleased]

## [1.0.0]

### Added
- Initial release.

- Initial release.
29 changes: 29 additions & 0 deletions voicemail/functions/recording.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,32 @@
/*
* recording.js
* Description:
* This Twilio Function is executed when a voicemail
* recording has been processed by Twilio. This
* recording is initiated in the voicemail function
* located in voicemail.protected.js. Once the recording
* is finished and processed, it will send the
* generated recording URL to MY_PHONE_NUMBER
* specified in /.env.
*
* Contents:
* 1. Main Handler
*/

/*
* 1. Main Handler
*
* This is the entry point to your Twilio Function,
* which will send the provided recording URL as an SMS
* to MY_PHONE_NUMBER specified in /.env.
*
* The function will fetch the Twilio Client provided by
* Functions. The Twilio client will be used to find the Twilio Number
* the voicemail was left at. It will then use the Twilio Client
* send an SMS of the recording URL from that number to
* MY_PHONE_NUMBER specified in /.env.
*/

exports.handler = async function (context, event, callback) {
const client = context.getTwilioClient();

Expand Down
101 changes: 95 additions & 6 deletions voicemail/functions/voicemail.protected.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,54 @@
/**
* Call Forwarding with Voicemail
*
* Description:
* This file contains the main Twilio Function that forwards
* incoming calls to a specific phone number during a set work
* hours and records voicemail for calls that are unanswered or
* outside of the work hours.
*
* Contents:
* 1. Dependencies
* 2. Configuration
* 3. Helper Function
* 4. Main Handler
*/

/**
* 1. Dependencies
* These dependecies will be used in the main handler to assist
* in formatting the date and forwaring URL for the recorded voicemail.
*/

const moment = require('moment');
const url = require('url');

/*
* 2. Configuration
*
* Contains greeting messages which is spoken when a call
* is received out of work hours. Here you can change the default
* greetings, voice types, and add addional greetings for specified languages.
*
* The function chooses the greeting based on the FromCountry parameter provided
* by Twilio when the call request is sent to the function.
*
* You can also change the default UTC time offset, work hours
* start and end times, start and end days of the work week.
* These values are only used if they arent specified in /.env.
*
*/

const GREETINGS = {
// default greeting if there isn't one set for the callers FromCountry parameter
_default: {
// message that is spoken to the caller
text: 'Hi there! You are calling after my work hours. Please leave a message after the beep',

// language code for conversion of text-to-speech messages, e.g. 'en' or 'en-gb'
language: 'en-US',

// voice for text-to-speech messages, one of 'man', 'woman' or any supported Amazon Polly or Google voices
voice: 'Polly.Joey',
},
DE: {
Expand All @@ -14,44 +58,88 @@ const GREETINGS = {
},
};

/*
* default values to be used if they aren't provided as environment variables
* in /.env.
*/
const DEFAULT_UTC_OFFSET = 0;
const DEFAULT_WORK_WEEK_START = 1; // Monday
const DEFAULT_WORK_WEEK_END = 5; // Friday
const DEFAULT_WORK_HOUR_START = 8; // 8:00, 8AM
const DEFAULT_WORK_HOUR_END = 18; // 18:59, 6:59PM

function getInteger(stringValue, defaultValue) {
/*
* 2. Helper Function
*
* Helper function to parse string values to integers.
* Returns default value if string cannot parsed to an integer.
*
* stringValue - value to be converted into an integer
* defaultValue - default value to return if stringValue
* can't be parse into integer
*/

function parseInteger(stringValue, defaultValue) {
const parsedNumber = parseInt(stringValue, 10);
if (isNaN(parsedNumber)) {
return defaultValue;
}
return parsedNumber;
}

/*
* 3. Main Handler
*
* This is the entry point to your Twilio Function,
* which will create a new Voice Response using Twiml based on
* the current time and defined work hours. If the call is
* during work hours the Voice Response will forward the call
* and dial the MY_PHONE_NUMBER specified in /.env.
* If the call is placed outside work hours, the Voice Response
* will respond to the caller with a greeting and will record a voicemail
* which will be forwarded to the recording function in recording.js.
*
* The callback will be used to return from your function
* with the Twiml Voice Response you defined earlier.
* In the callback in non-error situations, the first
* parameter is null and the second parameter
* is the value you want to return.
*/

exports.handler = function (context, event, callback) {
// parse the environment variables and get the work hours and timezone
const phoneNumberToForwardTo = context.MY_PHONE_NUMBER;
const timezone = getInteger(context.TIMEZONE_OFFSET, DEFAULT_UTC_OFFSET);
const timezone = parseInteger(context.TIMEZONE_OFFSET, DEFAULT_UTC_OFFSET);
const workWeek = {
start: getInteger(context.WORK_WEEK_START, DEFAULT_WORK_WEEK_START),
end: getInteger(context.WORK_WEEK_END, DEFAULT_WORK_WEEK_END),
start: parseInteger(context.WORK_WEEK_START, DEFAULT_WORK_WEEK_START),
end: parseInteger(context.WORK_WEEK_END, DEFAULT_WORK_WEEK_END),
};
const workHour = {
start: getInteger(context.WORK_HOUR_START, DEFAULT_WORK_HOUR_START),
end: getInteger(context.WORK_HOUR_END, DEFAULT_WORK_HOUR_END),
start: parseInteger(context.WORK_HOUR_START, DEFAULT_WORK_HOUR_START),
end: parseInteger(context.WORK_HOUR_END, DEFAULT_WORK_HOUR_END),
};

// calculate the current day and time according to the timezone
const currentTime = moment().utcOffset(timezone);
const hour = currentTime.hour();
const day = currentTime.day();

// check if there is a translated greeting for callers country
const translatedGreeting = GREETINGS[event.FromCountry];
const hasTranslatedGreeting = typeof translatedGreeting !== 'undefined';

// between monday and friday
const isWorkingDay = day <= workWeek.end && day >= workWeek.start;
// between 8am and 7pm
const isWorkingHour = hour <= workHour.end && hour >= workHour.start;

// create a new TwiML response
const twiml = new Twilio.twiml.VoiceResponse();

/*
* If the current time is within work hours, forward the call to the specified phone number.
* Else play the greeting message and begin recording for a voicemail message.
*/
if (isWorkingDay && isWorkingHour) {
twiml.dial(phoneNumberToForwardTo);
} else {
Expand All @@ -76,5 +164,6 @@ exports.handler = function (context, event, callback) {
action: url.resolve(context.PATH, 'recording'),
});
}
// return the generated Twilio Voice Response
callback(null, twiml);
};
2 changes: 1 addition & 1 deletion voicemail/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@
"version": "1.0.0",
"private": true,
"dependencies": {
"moment": "^2.24.0"
"moment": "^2.30.1"
}
}
Loading