Published
Monday, February 18, 2013 - 13:56
Written by

One of the most common phone calls we receive at Bay Area Children's Theatre is "Are tickets still available for performance xyz?"  That call is especially common on show days, when most of our staff is at the performance venue and not in the office to answer the phone.

BACT already uses Asterisk to provide our virtual PBX and I wanted to see if there was a way to automatically give callers a list of sold-out performances based on CiviCRM event data.  I discovered an Asterisk AGI script called GoogleTTS that uses Google's text-to-speach API to read arbitrary text to callers:

http://zaf.github.com/asterisk-googletts/

The only thing that was left was to come up with a little php to get the list of sold-out events from CiviCRM and pass it to GoogleTTS to read it to callers.  The php is pretty straightforward -- it uses the CiviCRM API to fetch the list of events with start_date > today.  Two small complications though.  1) I wanted to include the location of the performance, and there's currently no way to get an event location via the API, so I had to use direct calls to BAO functions for that.  2) The API also provides no way to get the true participant count for an event that accounts for price set participant multipliers, so I had to use direct BAO function calls for that too.  Here's the PHP code:

require_once '/home/.................../civicrm.settings.php';
require_once 'CRM/Core/Config.php';
require_once('CRM/Core/BAO/Location.php');
require_once('CRM/Event/BAO/Event.php');

$config = CRM_Core_Config::singleton( );

# get set of all events with start_date > now

$events = civicrm_api('Event', 'Get', array('filters' => array('start_date_low' => date('Ymd')), 'event_type_id' => 5, 'options' => array('limit' => 200), 'version' => 3));

$soldoutshows = array();

foreach ($events['values'] as $ekey => $event) {

   # find sold-out events
   $soldseats = CRM_Event_BAO_Event::eventTotalSeats($ekey);
   if ($soldseats >= $event['max_participants']) {

     # look up city name
     $locparams = array('entity_table' => 'civicrm_event',
                      'entity_id' => $event['id']);
     $location = CRM_Core_BAO_Location::getValues($locparams);
     $stime = strtotime($event['start_date']);
     $newshow = $location['address'][1]['city'] . ': ' . date('l F j g', $stime);
     if (date('i', $stime) != "00") {
       $newshow .= date(':i', $stime);
     }
     if (date('a', $stime) == "am") {
       $newshow .= " ay-em";
     }
     else {
       $newshow .= " pee-em";
     }
     $soldoutshows[] = $newshow;
  }
}

$saystring = 'SET VARIABLE MYSHOWS "';

if (empty($soldoutshows)) {
  $saystring .= "Tickets are available for all upcoming performances.";
}
else {
  $saystring .= "The following upcoming performances are sold out, ";
  foreach ($soldoutshows as $skey => $show) {
    $saystring .= $show . ", ";
  }
}

$saystring .= '"';
print $saystring;

$text = '';
$in = fopen('php://stdin', 'r');
while(!feof($in)){
    $text = $text . fgets($in, 4096);
}

And here's how we call it from our Asterisk dialplan:

exten => 1,2,agi(events.php)
exten => 1,3,agi(googletts.agi, "${MYSHOWS}", en,,1)

The first line calls the "events.php" code above, which sets an Asterisk variable called $MYSHOWS with the text that needs to be read to the caller. The second line calls the "googletts.agi" which accesses the Google API to covert the text to speech and read it to the caller.