A cloud-based Martian swiss army knife for voice calls, VoIP, conferencing, and voicemail. Powered by VoxImplant.
The code is for an open source version of Evil Martians' very own telephony platform that runs all our phone numbers.
This is a swiss army knife for everything we do with our phone numbers at Evil Martians. It currently runs on the VoxImplant cloud platform, is implemented in JavaScript, and is designed to run via continuous integration and continuous deployment tools.
You can use it to build your simple telephony solutions, with one or multiple office locations, managers scheduled to answer a call, conferencing, and short numbers.
It should be relatively easy to change the system for your specific usage requirements and integrations, or configure and run it as-is.
The application is mostly designed for engineering-friendly companies. It is intended for advanced users who know their way around Git and can alter the address book or schedule by editing JSON and pushing the code or making a pull request. This way, we can avoid monstrous integrations, and every single change is right there in the git repository.
Address book: | address_book.json |
Schedule: | ZONE-schedule.json |
Extension numbers: | 3 digits, dial immediately after the machine answers |
Forward and hang up: | #NUMBER , for instance, #001 |
Add to a conference, stay: | ##NUMBER , for instance ##001 |
The application shares code between zones. Think of "zone" as an office location or an application. Each zone is defined by its config and schedule. Some companies would only require a single zone.
In our use case, "US", "RU" and "JP" are the zones that we have—assigned to every country we have an office in.
The application requires a shared address book for all zones and one schedule per each zone.
N.B.: For end-users, it is advised to use a programming code editor to edit the file. Great if you have a JavaScript/JSON linter turned on. As soon as you commit the file into the repository, the software is designed to use the continuous integration server to build and push the configuration to the production environment. If there are any errors, syntax or otherwise, you will get an email. If everything is fine, changes will be applied in under a couple of minutes.
The address book is shared company-wide and available for all zones. That means that you can dial or forward calls to any user in the address book, no matter the phone number called or the current active zone.
Most importantly, everyone in the company should be encouraged to add themselves to the address book. You don't have any obligations when you pick a short number/extension code, so it's completely safe even if you're not a manager. You will get an extension number that works on all phones and all zones, an ability to forward calls to you or be invited to a conference, and a voicemail feature for your extension number.
The address book itself is a JSON file called address_book.json
.
Example:
[
{
"email": "[email protected]",
"ext": "001",
"name": "Jane Doe",
"number": "+1 206 555 0001"
}
]
All fields are mandatory. email
is the email address where you will get notifications about missed calls and voicemails. Use your primary corporate email address.
ext
is your extension number. Three digits, no more, no less.
name
is your name.
number
is your phone number in full international form, starting with country code and a +
. Make sure to update it frequently if you travel.
A schedule is where the call queue/schedule is defined. When a call goes to a zone number, the system will try each person from the list, top to bottom, with respect to their schedule and timezone.
The schedule is a file called like ZONE-schedule.json
.
Let's take a look:
[
{
"email": "[email protected]",
"timeZone": "America/New_York",
"schedule": {
"Mon": [9, 18],
"Tue": [9, 18],
"Wed": [9, 18],
"Thu": [9, 18],
"Fri": [9, 18]
}
},
{
"email": "[email protected]",
"timeZone": "America/Los_Angeles",
"schedule": {
"All": [7, 20]
}
}
]
In this example, Jane is the first one to get a call. Her schedule is defined in the New York time zone, from Monday to Friday, from 9 to 18. In case Jane is not available on her phone—or the call was not received at business hours—John is next on the line, working at Los Angeles time zone (PST), from 7 to 20 every day. If John is unavailable as well, the call goes to voicemail.
email
is a person's email, and it should be the same as the email in the Address book. It is also not possible to add a person to schedule if they are not in an Address book. Again, make sure to use your primary email.
timeZone
is the time zone for the following schedule. Note that your time zone is not the same thing as the nearest larger city. For a precise list of time zone identifiers, check https://momentjs.com/timezone/. Usually, it's America/Los_Angeles
for PST and America/New_York
for EST.
schedule
is your working hours schedule. You can use the All
key to define a unified schedule for all days of the week or specify a different schedule for each day of the week using the three-letter short form. All hours are in 24-hour format, to prevent any mixup.
As a caller, I will be greeted with a pre-recorded message telling me to stay on the line or dial an extension number.
If I don't know any extension numbers, I will stay on the line, and the software will try each person from the schedule list for the zone. The software will seek only the people who can answer the call right now, according to the schedule. Each person will be tried for 15 seconds, there will be an outgoing call, and I will hear the beeps. If there was no answer, or there was an error of any kind, networking, cellular or otherwise, the software will automatically try the next number.
Once I am connected to a manager, I can have a regular old-fashioned talk. Once the manager or I hang up, the call will end. The manager could also redirect me to a different person or make a conference call, adding another person.
If nobody can answer or if the queue is empty (for instance, if the call is late at night and zero people are working at that time, according to schedule), my call will go straight to voicemail, with a helpful message. I can hang the phone immediately; in this case, managers will receive an SMS and an email message stating my number to get back to me. Alternatively, I can leave a voicemail, and in this case, the email with my info will also have a link to the voicemail.
If I want to reach a specific person, I can use my tone dial to dial three digits (001
, for instance).
If the number I dialed is wrong (no such number or I've made a mistake), there will be a helpful message advising me to hang up and try again or stay on the line. If I stay on the line, the call will be treated as a general call to a company number, and hopefully, one of the managers will pick up.
If the number is correct, I will hear the beeps while the software is trying to call a person. If the person picks up, I can have a regular call; the manager on the other side will be able to redirect me to someone or make a conference call as well.
If the number is correct, but the person did not answer, I will get a helpful message asking me to leave a voicemail. I can hang up immediately; in this case, the manager will get an SMS and an email with my number. Alternatively, I can leave a voicemail, and in this case, the email to the manager will include the recording.
As a manager, I may be on one of the schedules for a zone. I must update my phone number each time it is changed and fine-tune my scheduling as discussed with other managers from my zone.
Once I get a call from the client to a general company phone number, my phone will display that client's number, so that I can get back to them later. When I pick the phone, a pre-recorded message will state that this is a call to a company. Following the message, I can have a regular call with a caller and hang up later. The call ends when one of us hangs up.
If it is not my turn to receive calls, according to the schedule, the software will never try to call me at all.
If I cannot answer, I can decline the call, and the software will try another manager automatically or go straight to voicemail.
If no one were able to answer, because of scheduling or unavailability, there would be an SMS stating that there was a missing call and an email; both will contain that person's number. The email will include the caller's phone number and call time in various timezones specific to each zone. If the person did leave a voicemail, the email would contain a link to the recording. Keep in mind that the file will be available for several months only, so make sure to download it if it is useful.
As any person in the address book, I can get direct calls by my extension number.
I will get a call, and my phone will display the client's number. If I'm available, I can pick the phone. It will start with the software instructing me that this is a call to my extension number through the system. I will have a regular call; it will end as soon as one of us leaves the call.
If I can't answer or if there is any mistake, I will receive an SMS saying I have missed the call from that specific number as well as an email message with the number. The email will include the caller's phone number and call time in various timezones specific to each zone. If the person did leave a voicemail, the email would contain a link to the recording. Keep in mind that the file will be available for several months only, so make sure to download it if it is useful.
As a manager, at any given moment during a call, I can add another person from the address book to the call.
I can redirect the client to a specific person—for instance, if they've talked before or if that person is in the loop.
In this case, I do a tone dial oh my phone: #NUMBER
, where NUMBER is the desired person's extension code, for instance, #001
. I will be disconnected momentarily, and the client will hear beeps while the software is trying to call a person.
The person I'm redirecting to will get a regular call as if they are being called by their extension number.
If there is a mistake connecting (no answer, for instance), the software will treat this call as a call to a personal extension number: there will be an option to leave a voicemail and the person specified will receive SMS and email messages.
I can make a conference call with the desired person. Unlike the redirect, in this case, I will have an option to continue the call and stay on the line. It is best if I want to introduce people one to another, give some context and feedback.
To do that, I dial ##NUMBER
, for instance, ##001
. There will be an audio indication when I dial the person, and there will be an audio indication if the call failed—or when a person joins a conference call.
The person receiving a call will get a pre-recorded message that they are being summoned to a conference call.
Technically, I can add as many people as I want—from the address book.
The call will end as soon as there are no people from our side present.
Each zone is defined by a configuration file (ZONE-config.json.erb
), a schedule (ZONE-schedule.json
), and a sound samples directory that is hosted on the web (see examples/
for examples). The address book is shared company-wide.
You'll need Ruby to run the validation scripts.
If you're only planning to compile and validate from your continuous integration server, you can safely skip this step.
Otherwise, install the latest stable Ruby version, followed by
gem install bundler
and then run
bundle install
in the project directory.
You will need a VoxImplant application, at least one phone number connected to it (you should be able to receive testing phone numbers for free), and a Mandrill account to send email notifications.
First, create a VoxImplant application.
Get the API keys to use with your application. Either use them as environment variables (VOX_ACCOUNT_ID
, VOX_API_KEY
, the sample zone configuration file encourages that approach), or later replace ERB template instructions with just copy-pasting the values.
Sign up to Mandrill, if you don't have an account yet, and get an API key. Again, use it as an environment variable (MANDRILL_API_KEY
) or later copy and paste in the zone configuration file.
donenv or its clones might come it handy to manage environment variables.
We use Circle CI for continuous integration and continuous deployment, but you should be safe with any good CI service or server.
You can find a sample Circle CI config in circleci-config-example.yml
. Place it into .circleci/config.yml
and enable Circle CI for your repository.
Let's say you want to create a zone called zone
.
First, we'll need an address book—something that maps users' short extension numbers to their "real", mobile phone numbers for forwarding. The address_book.json
is shared between all zones, check out the sample file.
Now we'll jump to the configuration. Start with creating—or modifying—configuration files: zone-schedule.json
and zone-config.json.erb
in the project root. Be sure to check all fields and read inline documentation.
Next, we need to deploy the zone. Add the task to tasks/deploy.rake
:
task :zone do
deploy.call { write_production_bundle('zone') }
end
Also, add this task to the all
task right below that line:
desc 'Deploy all'
task all: [
:zone
]
The application works best with audio clips supplied.
Check the examples
folder for more info. There are two kinds of sounds—audio clips (see clips/en
) and sound effects (see clips/sfx
).
VoxImplant is designed to play remote MP3 files that are accessible over HTTP. Do use audio clips on production, record your own, place them into two folders that are accessible over HTTP, and configure your zone accordingly (see the baseMsgClipUrl
and baseSfxClipUrl
keys.)
N.B.: Please don't use the supplied files in production—they are there as a placeholder. Record your own; it's easy!
Audio clips are played to the caller (and to the manager) when a particular event happens:
begin.mp3
—Short greeting, announcing extension numbers
redirect.mp3
—This is what a manager hears when they get a call to a company number
redirect_person.mp3
—When a manager gets a redirected call via the extension number, or another manager redirects to him specifically
redirect_conference.mp3
—When a manager gets summoned to a conference call
incorrect_person.mp3
—When an extension number was dialed in but was incorrect
end.mp3
—Sorry, announcing voicemail
end_person.mp3
—Sorry, personal call (extension number), announcing voicemail
Sound effects are used to indicate an event to a user and are mostly used during conference calls.
connected.mp3
—a person joined the conference call
error.mp3
—there was an error summoning another person to a conference call
disconnected.mp3
—a person left the conference call
Next, let's check the configuration (or run continuous integration right away). Push your code or run
bundle exec rake deploy:all
manually. If you don't see any errors, you can continue.
Next, let's visit the VoxImplant admin interface. Visit Scenarios
and make sure that you have the zone-bundle
scenario in the Shared
folder.
Finally, we need to connect our compiled scenario to a phone number.
- Visit
Routing
, addNew rule
. - Input a rule name, for instance,
Zone
. - Choose the bundle
zone-bundle
. - Save the rule.
- Next, visit
Numbers
- Choose a previously bought number in
Attached
and edit it. If needed, attach it first from theAvailable
list. - Choose the
Zone
rule and save it.
All should be good! The scenario should be working now when you call your phone number. And if you've set up your CI, every time you commit to master or merge a pull request, every single configuration change (schedule, address book, application) should be applied automatically.
- Anton Lee, development
- Vladimir Kochnev, development
- Tanira Wiggins, voice
- Yaroslav Markin, production and idea
GNU GENERAL PUBLIC LICENSE version 3 (see LICENSE
).
Portions (sound effects at examples/sfx
for demonstration purposes) are by https://arnofaure.github.io/free-sfx/ and are licensed under CC BY 4.0