{---------------------------------------------------------------------------------
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()