{---------------------------------------------------------------------------------
Unit:                 msgcast.pas

Purpose:              Simple script to broadcast a voice message to a single
                      channel (telephone number or extension).  Validates against a user
                      table in a FirebirdSQL database.  If validated, script prompts
                      caller for basic info and then initiates broadcast call.  A
                      call consists of a recorded message being broacast to a single
                      endpoint.

Objects Used:         Swift:       Text to Speech,
                      CallFile:    Create call file
                      SQLDB:       connecting to FirebirdSQL

Requirements:         Requires FirebirdSQL server available on network and
                      Cepstral Swift engine to be available on the Asterisk server.

Include Files:        msg-cast-utils.pas - Provides supporting functions, constants and
                      enumerated types for use in this unit.
-----------------------------------------------------------------------------------}


{uses Swift, Callfile, SQLDB} // <==== load internal objects for use in script
                              // Nice that these objects are available.  Even Nicer
                              // that they are only instantiated when explicitly
                              // needed.
program msgcast;

{$I msg-cast-utils.pas}       // <==== include file
                              // The contents of the include file are placed here before
                              // compiling the script.

var
Strut: TBroadcastMsg;
sOrigTimeout, sRet: String;
sUnique, sCmd: string;
sPass, sExten: string;
iMins: integer;
User: TUser;
ValReturn: TValidateReturn;

begin

// save original SocketTimeout value.  Use try..finally to
// ensure that it gets set back
sOrigTimeout := AGI.GetProp('SocketTimeout');
try

// Change SocketTimeout to 30 seconds
AGI.SetProp('SocketTimeout', '30000');

// play intro to caller
Swift.PlayString(PROMPT_INTRO, true);

// get extension number
sExten := GetResponse(PROMPT_EXTEN, PROMPT_CHANCES, 8, -1, PROMPT_TIMEOUT);
if ((sExten = '') or (sExten = '9')) then
  exit;

// get passcode
sPass := GetResponse(PROMPT_PASSCODE, PROMPT_CHANCES, 4, 9999, PROMPT_TIMEOUT);
if ((sPass = '') OR (sPass = '9')) then
  exit;

// Validate Passcode and extension using ValidateUser function defined
// in INCLUDE FILE msg-cast-utils.pas
ValReturn := ValidateUser(sPass, sExten, User);

if (ValReturn <> vrValidated) then
   begin
   Swift.PlayString(PROMPT_FAILURE, false);      // <==== Not Validated.  Play error msg
   exit;                                         // and get out of dodge.
   end;

// Play validation confirmation back to caller.
if (User.IsAdmin) then
   Swift.PlayString('Your Majesty\, ' + User.UserFirst + ' ' +
      User.UserLast + '.  You have been validated and your ' + 'User ID is ' + User.UserID, false)
else
   Swift.PlayString('Thank you\, ' + User.UserFirst + ' ' +
      User.UserLast + '.  You have been validated and your ' + 'User ID is ' + User.UserID, false);


// Get Number to call
sRet := GetResponse(PROMPT_TOCALL, PROMPT_CHANCES, 10, -1, PROMPT_TIMEOUT);
if ((sRet = '') OR (sRet = '9')) then
  exit;

// add to Strut structure for use later
Strut.Channel := TECHNOLOGY + sRet;

// Get Retries
sRet := GetResponse(PROMPT_RETRIES, PROMPT_CHANCES, 2, 30, PROMPT_TIMEOUT);
if ((sRet = '') OR (sRet = '9')) then
  exit;
// add to Strut structure for use later
Strut.Retries := StrToInt(sRet);

// Get Ringtime (WaitTime)
sRet := GetResponse(PROMPT_RINGTIME, PROMPT_CHANCES, 2, 60, PROMPT_TIMEOUT);
if ((sRet = '') OR (sRet = '9')) then
  exit;
// add to Strut structure for use later
Strut.RingTime := StrToInt(sRet);

// Get SecondsBetweenTries (RetryTime)
sRet := GetResponse(PROMPT_RETRYTIME, PROMPT_CHANCES, 6, 999999, PROMPT_TIMEOUT);
if ((sRet = '') OR (sRet = '9')) then
  exit;
// add to Strut structure for use later
Strut.SecondsBetweenTries := StrToInt(sRet);

// create a unique file name for the recorded file
sUnique := AGI.GetUniqueID;
sUnique := 'prompt_' + sUnique;

// prompt the caller to record the message
Swift.PlayString(PROMPT_RECORD, false);

// record caller's message to be broadcast
AGI.RecordFile('/tmp/' + sUnique, 'wav', '#', 30000, 0, true, 2);

// Playback the recorded file to the caller.
AGI.ExecCommand('PLAYBACK', '"/tmp/' + sUnique + '"');

// create a command delete the file using linux "at" and schedule for 3 hours.
sCmd := '"echo \"rm -f /tmp/' + sUnique + '.wav\" | at now + 3 hours"';

// execute the command
AGI.ExecCommand('SYSTEM', sCmd);

// create the call file using the CallFile object.
with CallFile do
   begin
   SetProp('Channel', Strut.Channel);
   SetProp('Context', AST_CONTEXT);
   SetProp('Extension', AST_EXTENSION);
   SetProp('Priority', AST_PRIORITY);
   SetProp('MaxRetries', IntToStr(Strut.Retries));
   SetProp('WaitTime', IntToStr(Strut.RingTime));
   SetProp('ATCommand', 'at now + 3 minutes');
   SetProp('SetVar', 'MSGPATH=/tmp/' + sUnique);          // set this variable for use in the named context
   Execute;                                               // See a commented out sample extension.conf context
   end;                                                   // at the bottom of this script.

// confirm execute with the caller.
Swift.PlayString('The call will be initiated in 3 minutes.', false);

finally;
  // set the SocketTimeout back to original settings
  AGI.SetProp('SocketTimeout', sOrigTimeout);
  // send call back into the dialplan
  AGI.SetExitAll('check_time', 's', '1');
  end;

end.




// ***********************************************************************************
// Sample Context to Return call to.
// Could be more sophisticated such as requiring the
// caller person to acknowledge the call and flag them
// off in a database table, etc, etc.
// ***********************************************************************************

//      [broadcast-return]
//      
//      exten=> s,1,Answer()
//      exten=> s,2,Playback(${MSGPATH})
//      exten=> s,3,Hangup()