Skip to content

Instantly share code, notes, and snippets.

@solutious
Created December 4, 2008 12:17
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save solutious/31922 to your computer and use it in GitHub Desktop.
Save solutious/31922 to your computer and use it in GitHub Desktop.

#Basic voicemail system#

A basic voicemail system using Twilio.

##How to install##

  • Place check.php and twiliorest.php on some private server that only you have access too. You can run check.php on the command line too if you don't mind the HTML output.
  • Place all of the other .php files into the same directory on a publicly accessible server. Use a non-guessable name for the directory like an md5 hash of your favourite type of salt.
  • In check.php, plunk in your Account SID and API token
  • Change the recipient email address in 1_receive-voicemail.php
  • Note: You may need to replace the relative URIs to the .php files to absolute ones.
  • Log in to Twilio and change your Sandbox URI to point to your 0_receive-call.php

Enjoy!

<?php
// if the caller pressed anything but 1, 2 or 3 send them back
if($_REQUEST['Digits'] < 1 || $_REQUEST['Digits'] > 3) {
header("Location: 0_receive-call.php");
die;
}
if($_REQUEST['Digits'] == 1 ) {
header("Location: 1_record-voicemail.php");
die;
}
if($_REQUEST['Digits'] == 2) {
header("Location: 2_system-status.php");
die;
}
if($_REQUEST['Digits'] == 3) {
header("Location: 3_david-lee-roth.php");
die;
}
// otherwise, we send an error
header("content-type: text/xml");
echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
?>
<Response>
<!-- We use redirects above so if we should never get here -->
<Say voice="woman">Oops. Our voicemail system seems to be bunged up. You'll have to try again later.</Say>
</Response>
<?PHP
header("content-type: text/xml");
echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
?><Response>
<Gather numDigits="1" action="0_process-button.php" method="POST">
<Say voice="woman">Hi, you've reached the office of Solutious Incorporated.
You can press 1 now to leave a voicemail message,
press 2 to check our server status.
Or press 3 to hear some David Lee Roth.
</Say>
<!-- You can also record your own -->
<!--
<Play>0_receive_call.wav</Play>
-->
</Gather>
</Response>
<?PHP
header("content-type: text/xml");
echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
$email = "your@eeeeeeeeeeeeeeemail.com" ;
$message = "You have mail! Listen to the message here ";
$message .= "(".$_REQUEST['Duration']." seconds):\n";
$message .= $_REQUEST['RecordingUrl'] . "\n\n";
$message .= "Call Parameters:\n\n";
foreach ($_REQUEST as $key => $val) {
$message .= "$key -> $val\n";
}
$message .= "\nEnvironment:\n";
foreach ($_ENV as $key => $val) {
$message .= "$key -> $val\n";
}
$phone = $_REQUEST['Caller'];
$subject = "Voicemail from " . $phone . " at " . date("H:i:s O");
$subject .= " (".$_REQUEST['CallerCity'] . ", ";
$subject .= $_REQUEST['CallerState'] . ' ' . $_REQUEST['CallerCountry'] . ")";
mail( $email, $subject, $message, "From: $email" );
?>
<Response>
<Say voice="woman">Thanks for the message. Have a great day!</Say>
</Response>
<?PHP
header("content-type: text/xml");
echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
?><Response>
<Say voice="woman">Leave your message after the tone. Press star when complete.</Say>
<Record
action="1_receive-voicemail.php"
method="GET"
maxLength="120"
finishOnKey="*"
/>
<!-- Record should forward to the action. We'll only get here if there's a problem. -->
<Say voice="woman">Oops. Our voicemail system seems to be bunged up. You'll have to try again later.</Say>
</Response>
<?PHP
header("content-type: text/xml");
echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
//date_default_timezone_set('UTC'); // TODO: use the city and state to determine location.
$date_str = date("l F jS"); // Saturday the 3rd of March
$time_str = date("g i T");
// If you have a system to check you'll probably want to
// ping it here.
$status = "looking good. All services are available.";
?><Response>
<Say voice="woman">The system status for <?PHP echo $date_str ?> at <?PHP echo $time_str ?> is</Say>
<Pause length="1" />
<Say voice="woman"><?PHP echo $status ?></Say>
<Say voice="woman">Thanks for checking in and have a great day!</Say>
</Response>
<?PHP
header("content-type: text/xml");
echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
?><Response>
<Say voice="woman">Ladies and Gentleman, all the way from Bloomington Indiana. Here is David Lee Roth!</Say>
<Pause length="1" />
<Play>http://solutious.com/media/david-lee-roth.mp3</Play>
<Say voice="woman">Wow! Thank you David. That's all for now. Have a great day!</Say>
</Response>
<?php
/* Include the PHP TwilioRest library */
require "twiliorest.php";
/* Twilio REST API version */
$ApiVersion = "2008-08-01";
/* Set our AccountSid and AuthToken */
$AccountSid = "xxxxxxxxxxxxxxxxxxxxxxxxx";
$AuthToken = "xxxxxxxxxxxxxxxxxxxxxxxx";
/* Instantiate a new Twilio Rest Client */
$client = new TwilioRestClient($AccountSid, $AuthToken);
/* Get Recent Calls */
$response = $client->request("/$ApiVersion/Accounts/$AccountSid/Recordings", "GET");
if($response->IsError) {
echo "Error: {$response->ErrorMessage}
";
} else {
// iterate over calls
foreach($response->ResponseXml->Recordings->Recording AS $rec) {
$vm[$rec->CallSid.__toString] = $rec->Sid;
#echo "$rec->CallSid - $rec->Sid<br/>";
}
}
function vm_uri($apiv, $acct, $sid) {
return "http://api.twilio.com/$apiv/Accounts/$acct/Recordings/$sid.mp3";
}
echo "<h1>Solutious' Ill Phone System</h1>\n";
echo "<h2>Calls</h2>\n\n";
/* Get Recent Calls */
$response = $client->request("/$ApiVersion/Accounts/$AccountSid/Calls",
"GET");
if($response->IsError) {
echo "Error: {$response->ErrorMessage}
";
} else {
// iterate over calls
foreach($response->ResponseXml->Calls->Call AS $call) {
echo "Call from {$call->Caller} to {$call->Called} at {$call->StartTime} of length: {$call->Duration}";
if (isset($vm[$call->Sid.__toString]))
echo " (<a href='" . vm_uri($ApiVersion, $AccountSid, $vm[$call->Sid.__toString]) . "'>voicemail</a>)";
echo "<br/>\n";
}
}
?>
<?php
/*
Copyright (c) 2008 Twilio, Inc.
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
*/
// ensure Curl is installed
if(!extension_loaded("curl"))
throw(new Exception(
"Curl extension is required for TwilioRestClient to work"));
/*
* TwilioRestResponse holds all the REST response data
* Before using the reponse, check IsError to see if an exception
* occurred with the data sent to Twilio
* ResponseXml will contain a SimpleXml object with the response xml
* ResponseText contains the raw string response
* Url and QueryString are from the request
* HttpStatus is the response code of the request
*/
class TwilioRestResponse {
public $ResponseText;
public $ResponseXml;
public $HttpStatus;
public $Url;
public $QueryString;
public $IsError;
public $ErrorMessage;
public function __construct($url, $text, $status) {
preg_match('/([^?]+)\??(.*)/', $url, $matches);
$this->Url = $matches[1];
$this->QueryString = $matches[2];
$this->ResponseText = $text;
$this->HttpStatus = $status;
if($this->HttpStatus != 204)
$this->ResponseXml = @simplexml_load_string($text);
if($this->IsError = ($status >= 400))
$this->ErrorMessage =
(string)$this->ResponseXml->RestException->Message;
}
}
/* TwilioRestClient throws TwilioRestException on error
* Useful to catch this exception separately from general PHP
* exceptions, if you want
*/
class TwilioRestException extends Exception {}
/*
* TwilioRestBaseClient: the core Rest client, talks to the Twilio REST
* API. Returns a TwilioRestResponse object for all responses if Twilio's
* API was reachable Throws a TwilioRestException if Twilio's REST API was
* unreachable
*/
class TwilioRestClient {
protected $Endpoint;
protected $AccountSid;
protected $AuthToken;
/*
* __construct
* $username : Your AccountSid
* $password : Your account's AuthToken
* $endpoint : The Twilio REST Service URL, currently defaults to
* the proper URL
*/
public function __construct($accountSid, $authToken,
$endpoint = "https://api.twilio.com") {
$this->AccountSid = $accountSid;
$this->AuthToken = $authToken;
$this->Endpoint = $endpoint;
}
/*
* sendRequst
* Sends a REST Request to the Twilio REST API
* $path : the URL (relative to the endpoint URL, after the /v1)
* $method : the HTTP method to use, defaults to GET
* $vars : for POST or PUT, a key/value associative array of data to
* send, for GET will be appended to the URL as query params
*/
public function request($path, $method = "GET", $vars = array()) {
$encoded = "";
foreach($vars AS $key=>$value)
$encoded .= "$key=".urlencode($value)."&";
$encoded = substr($encoded, 0, -1);
// construct full url
$url = "{$this->Endpoint}/$path";
// if GET and vars, append them
if($method == "GET")
$url .= (FALSE === strpos($path, '?')?"?":"&").$encoded;
// initialize a new curl object
$curl = curl_init($url);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
switch(strtoupper($method)) {
case "GET":
curl_setopt($curl, CURLOPT_HTTPGET, TRUE);
break;
case "POST":
curl_setopt($curl, CURLOPT_POST, TRUE);
curl_setopt($curl, CURLOPT_POSTFIELDS, $encoded);
break;
case "PUT":
// curl_setopt($curl, CURLOPT_PUT, TRUE);
curl_setopt($curl, CURLOPT_POSTFIELDS, $encoded);
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "PUT");
file_put_contents($tmpfile = tempnam("/tmp", "put_"),
$encoded);
curl_setopt($curl, CURLOPT_INFILE, $fp = fopen($tmpfile,
'r'));
curl_setopt($curl, CURLOPT_INFILESIZE,
filesize($tmpfile));
break;
case "DELETE":
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "DELETE");
break;
default:
throw(new TestException("Unknown method $method"));
break;
}
// send credentials
curl_setopt($curl, CURLOPT_USERPWD,
$pwd = "{$this->AccountSid}:{$this->AuthToken}");
// do the request. If FALSE, then an exception occurred
if(FALSE === ($result = curl_exec($curl)))
throw(new TwilioRestException(
"Curl failed with error " . curl_error($curl)));
// get result code
$responseCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
// unlink tmpfiles
if($fp)
fclose($fp);
if(strlen($tmpfile))
unlink($tmpfile);
return new TwilioRestResponse($url, $result, $responseCode);
}
}
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment