mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-05 20:20:07 +00:00
add privacy/screening functionality to app_dial (bug #752)
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@6102 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
1
Makefile
1
Makefile
@@ -462,6 +462,7 @@ clean:
|
||||
datafiles: all
|
||||
sh mkpkgconfig $(DESTDIR)/usr/lib/pkgconfig
|
||||
mkdir -p $(DESTDIR)$(ASTVARLIBDIR)/sounds/digits
|
||||
mkdir -p $(DESTDIR)$(ASTVARLIBDIR)/sounds/priv-callerintros
|
||||
for x in sounds/digits/*.gsm; do \
|
||||
if $(GREP) -q "^%`basename $$x`%" sounds.txt; then \
|
||||
install -m 644 $$x $(DESTDIR)$(ASTVARLIBDIR)/sounds/digits ; \
|
||||
|
314
apps/app_dial.c
314
apps/app_dial.c
@@ -42,6 +42,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
#include "asterisk/app.h"
|
||||
#include "asterisk/causes.h"
|
||||
#include "asterisk/manager.h"
|
||||
#include "asterisk/privacy.h"
|
||||
|
||||
static char *tdesc = "Dialing Application";
|
||||
|
||||
@@ -63,6 +64,10 @@ static char *descrip =
|
||||
"n is the priority of the dialer instance), then it will be the next\n"
|
||||
"executed extension (this allows you to setup different behavior on busy from\n"
|
||||
"no-answer).\n"
|
||||
" For the Privacy and Screening Modes, the DIALSTATUS variable will be set to DONTCALL, \n"
|
||||
"if the called party chooses to send the calling party to the 'Go Away' script, and \n"
|
||||
"the DIALSTATUS variable will be set to TORTURE, if the called party wants to send the caller to \n"
|
||||
"the TORTURE scripts\n"
|
||||
" This application returns -1 if the originating channel hangs up, or if the\n"
|
||||
"call is bridged and either of the parties in the bridge terminate the call.\n"
|
||||
"The option string may contain zero or more of the following characters:\n"
|
||||
@@ -92,7 +97,10 @@ static char *descrip =
|
||||
" 'h' -- allow callee to hang up by hitting *.\n"
|
||||
" 'H' -- allow caller to hang up by hitting *.\n"
|
||||
" 'C' -- reset call detail record for this call.\n"
|
||||
" 'P[(x)]' -- privacy mode, using 'x' as database if provided.\n"
|
||||
" 'P[(x)]' -- privacy mode, using 'x' as database if provided, or the extension is used if not provided.\n"
|
||||
" 'p' -- screening mode. Basically Privacy mode without memory.\n"
|
||||
" 'n' -- modifier for screen/privacy mode. No intros are to be saved in the priv-callerintros dir.\n"
|
||||
" 'N' -- modifier for screen/privacy mode. if callerID is present, do not screen the call.\n"
|
||||
" 'g' -- goes on in context if the destination channel hangs up\n"
|
||||
" 'G(context^exten^pri)' -- If the call is answered transfer both parties to the specified exten.\n"
|
||||
" 'A(x)' -- play an announcement to the called party, using x as file\n"
|
||||
@@ -112,7 +120,7 @@ static char *descrip =
|
||||
" * LIMIT_WARNING_FILE File to play as warning if 'y' is defined.\n"
|
||||
" 'timeleft' is a special sound macro to auto-say the time \n"
|
||||
" left and is the default.\n"
|
||||
" 'n' -- Do not jump to n+101 if all of the channels were busy.\n\n"
|
||||
" 'j' -- Do not jump to n+101 if all of the channels were busy.\n\n"
|
||||
" In addition to transferring the call, a call may be parked and then picked\n"
|
||||
"up by another user.\n"
|
||||
" The optional URL will be sent to the called party if the channel supports it.\n"
|
||||
@@ -122,7 +130,7 @@ static char *descrip =
|
||||
" DIALEDTIME Time from dial to answer\n"
|
||||
" ANSWEREDTIME Time for actual call\n"
|
||||
" DIALSTATUS The status of the call as a text string, one of\n"
|
||||
" CHANUNAVAIL | CONGESTION | NOANSWER | BUSY | ANSWER | CANCEL\n"
|
||||
" CHANUNAVAIL | CONGESTION | NOANSWER | BUSY | ANSWER | CANCEL | DONTCALL | TORTURE\n"
|
||||
"";
|
||||
|
||||
/* RetryDial App by Anthony Minessale II <anthmct@yahoo.com> Jan/2005 */
|
||||
@@ -610,12 +618,17 @@ static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags
|
||||
struct localuser *u;
|
||||
char *info, *peers, *timeout, *tech, *number, *rest, *cur;
|
||||
char privdb[256] = "", *s;
|
||||
char privcid[256] = "";
|
||||
char privintro[1024];
|
||||
char announcemsg[256] = "", *ann;
|
||||
struct localuser *outgoing=NULL, *tmp;
|
||||
struct ast_channel *peer;
|
||||
int to;
|
||||
int hasmacro = 0;
|
||||
int privacy=0;
|
||||
int screen=0;
|
||||
int no_save_intros = 0;
|
||||
int no_screen_callerid = 0;
|
||||
int announce=0;
|
||||
int resetcdr=0;
|
||||
int numbusy = 0;
|
||||
@@ -629,6 +642,7 @@ static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags
|
||||
char *newnum;
|
||||
char *l;
|
||||
char *url=NULL; /* JDG */
|
||||
int privdb_val=0;
|
||||
unsigned int calldurationlimit=0;
|
||||
char *cdl;
|
||||
time_t now;
|
||||
@@ -814,7 +828,7 @@ static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags
|
||||
*(ann++) = 'X';
|
||||
if (*ann)
|
||||
*ann = 'X';
|
||||
/* Now find the end of the privdb */
|
||||
/* Now find the end of the announce */
|
||||
ann = strchr(announcemsg, ')');
|
||||
if (ann)
|
||||
*ann = '\0';
|
||||
@@ -906,11 +920,19 @@ static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags
|
||||
} else if (strchr(transfer, 'P')) {
|
||||
/* No specified privdb */
|
||||
privacy = 1;
|
||||
} else if (strchr(transfer, 'p')) {
|
||||
screen = 1;
|
||||
} else if (strchr(transfer, 'C')) {
|
||||
resetcdr = 1;
|
||||
} else if (strchr(transfer, 'n')) {
|
||||
} else if (strchr(transfer, 'j')) {
|
||||
nojump = 1;
|
||||
}
|
||||
if (strchr(transfer, 'n')) {
|
||||
no_save_intros = 1;
|
||||
}
|
||||
if (strchr(transfer, 'N')) {
|
||||
no_screen_callerid = 1;
|
||||
}
|
||||
}
|
||||
if (resetcdr && chan->cdr)
|
||||
ast_cdr_reset(chan->cdr, 0);
|
||||
@@ -918,11 +940,97 @@ static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags
|
||||
/* If privdb is not specified and we are using privacy, copy from extension */
|
||||
ast_copy_string(privdb, chan->exten, sizeof(privdb));
|
||||
}
|
||||
if (privacy) {
|
||||
if (privacy || screen) {
|
||||
char callerid[60];
|
||||
|
||||
l = chan->cid.cid_num;
|
||||
if (!l)
|
||||
l = "";
|
||||
ast_log(LOG_NOTICE, "Privacy DB is '%s', privacy is %d, clid is '%s'\n", privdb, privacy, l);
|
||||
if (l && !ast_strlen_zero(l)) {
|
||||
ast_shrink_phone_number(l);
|
||||
if( privacy ) {
|
||||
if (option_verbose > 2)
|
||||
ast_verbose( VERBOSE_PREFIX_3 "Privacy DB is '%s', privacy is %d, clid is '%s'\n", privdb, privacy, l);
|
||||
privdb_val = ast_privacy_check(privdb, l);
|
||||
}
|
||||
else {
|
||||
if (option_verbose > 2)
|
||||
ast_verbose( VERBOSE_PREFIX_3 "Privacy Screening, clid is '%s'\n", l);
|
||||
privdb_val = AST_PRIVACY_UNKNOWN;
|
||||
}
|
||||
} else {
|
||||
char *tnam, *tn2;
|
||||
|
||||
tnam = ast_strdupa(chan->name);
|
||||
/* clean the channel name so slashes don't try to end up in disk file name */
|
||||
for(tn2 = tnam; *tn2; tn2++) {
|
||||
if( *tn2=='/')
|
||||
*tn2 = '='; /* any other chars to be afraid of? */
|
||||
}
|
||||
if (option_verbose > 2)
|
||||
ast_verbose( VERBOSE_PREFIX_3 "Privacy-- callerid is empty\n");
|
||||
|
||||
snprintf(callerid, sizeof(callerid), "NOCALLERID_%s%s", chan->exten, tnam);
|
||||
l = callerid;
|
||||
privdb_val = AST_PRIVACY_UNKNOWN;
|
||||
}
|
||||
|
||||
ast_copy_string(privcid,l,sizeof(privcid));
|
||||
|
||||
if( strncmp(privcid,"NOCALLERID",10) != 0 && no_screen_callerid ) { /* if callerid is set, and no_screen_callerid is set also */
|
||||
if (option_verbose > 2)
|
||||
ast_verbose( VERBOSE_PREFIX_3 "CallerID set (%s); N option set; Screening should be off\n", privcid);
|
||||
privdb_val = AST_PRIVACY_ALLOW;
|
||||
}
|
||||
else if( no_screen_callerid && strncmp(privcid,"NOCALLERID",10) == 0 ) {
|
||||
if (option_verbose > 2)
|
||||
ast_verbose( VERBOSE_PREFIX_3 "CallerID blank; N option set; Screening should happen; dbval is %d\n", privdb_val);
|
||||
}
|
||||
|
||||
if( privdb_val == AST_PRIVACY_DENY ) {
|
||||
ast_verbose( VERBOSE_PREFIX_3 "Privacy DB reports PRIVACY_DENY for this callerid. Dial reports unavailable\n");
|
||||
res=0;
|
||||
goto out;
|
||||
}
|
||||
else if( privdb_val == AST_PRIVACY_KILL ) {
|
||||
if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 201, chan->cid.cid_num))
|
||||
chan->priority+=200;
|
||||
|
||||
res = 0;
|
||||
goto out; /* Is this right? */
|
||||
}
|
||||
else if( privdb_val == AST_PRIVACY_TORTURE ) {
|
||||
if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 301, chan->cid.cid_num))
|
||||
chan->priority+=300;
|
||||
res = 0;
|
||||
goto out; /* is this right??? */
|
||||
|
||||
}
|
||||
else if( privdb_val == AST_PRIVACY_UNKNOWN ) {
|
||||
/* Get the user's intro, store it in priv-callerintros/$CID,
|
||||
unless it is already there-- this should be done before the
|
||||
call is actually dialed */
|
||||
|
||||
/* make sure the priv-callerintros dir exists? */
|
||||
|
||||
snprintf(privintro,sizeof(privintro),"priv-callerintros/%s", privcid);
|
||||
if( ast_fileexists(privintro,NULL,NULL ) > 0 && strncmp(privcid,"NOCALLERID",10) != 0) {
|
||||
/* the DELUX version of this code would allow this caller the
|
||||
option to hear and retape their previously recorded intro.
|
||||
*/
|
||||
}
|
||||
else {
|
||||
int duration; /* for feedback from play_and_wait */
|
||||
/* the file doesn't exist yet. Let the caller submit his
|
||||
vocal intro for posterity */
|
||||
/* priv-recordintro script:
|
||||
|
||||
"At the tone, please say your name:"
|
||||
|
||||
*/
|
||||
ast_play_and_record(chan, "priv-recordintro", privintro, 4, "gsm", &duration, 128, 2000, 0); /* NOTE: I've reduced the total time to 4 sec */
|
||||
/* don't think we'll need a lock removed, we took care of
|
||||
conflicts by naming the privintro file */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If a channel group has been specified, get it for use when we create peer channels */
|
||||
@@ -1172,6 +1280,194 @@ static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags
|
||||
ast_log(LOG_DEBUG, "app_dial: sendurl=%s.\n", url);
|
||||
ast_channel_sendurl( peer, url );
|
||||
} /* /JDG */
|
||||
if( privacy || screen ) {
|
||||
int res2;
|
||||
int loopcount = 0;
|
||||
if( privdb_val == AST_PRIVACY_UNKNOWN ) {
|
||||
|
||||
/* Get the user's intro, store it in priv-callerintros/$CID,
|
||||
unless it is already there-- this should be done before the
|
||||
call is actually dialed */
|
||||
|
||||
/* all ring indications and moh for the caller has been halted as soon as the
|
||||
target extension was picked up. We are going to have to kill some
|
||||
time and make the caller believe the peer hasn't picked up yet */
|
||||
|
||||
if ( strchr(transfer, 'm') ) {
|
||||
ast_indicate(chan, -1);
|
||||
ast_moh_start(chan, mohclass);
|
||||
} else if ( strchr(transfer, 'r') ) {
|
||||
ast_indicate(chan, AST_CONTROL_RINGING);
|
||||
sentringing++;
|
||||
}
|
||||
|
||||
/* Start autoservice on the other chan ?? */
|
||||
res2 = ast_autoservice_start(chan);
|
||||
/* Now Stream the File */
|
||||
if (!res2) {
|
||||
do {
|
||||
if (!res2)
|
||||
res2 = ast_play_and_wait(peer,"priv-callpending");
|
||||
if( res2 < '1' || (privacy && res2>'5') || (screen && res2 > '4') ) /* uh, interrupting with a bad answer is ... ignorable! */
|
||||
res2 = 0;
|
||||
|
||||
/* priv-callpending script:
|
||||
"I have a caller waiting, who introduces themselves as:"
|
||||
*/
|
||||
if (!res2)
|
||||
res2 = ast_play_and_wait(peer,privintro);
|
||||
if( res2 < '1' || (privacy && res2>'5') || (screen && res2 > '4') ) /* uh, interrupting with a bad answer is ... ignorable! */
|
||||
res2 = 0;
|
||||
/* now get input from the called party, as to their choice */
|
||||
if( !res2 ) {
|
||||
if( privacy )
|
||||
res2 = ast_play_and_wait(peer,"priv-callee-options");
|
||||
if( screen )
|
||||
res2 = ast_play_and_wait(peer,"screen-callee-options");
|
||||
}
|
||||
/* priv-callee-options script:
|
||||
"Dial 1 if you wish this caller to reach you directly in the future,
|
||||
and immediately connect to their incoming call
|
||||
Dial 2 if you wish to send this caller to voicemail now and
|
||||
forevermore.
|
||||
Dial 3 to send this callerr to the torture menus, now and forevermore.
|
||||
Dial 4 to send this caller to a simple "go away" menu, now and forevermore.
|
||||
Dial 5 to allow this caller to come straight thru to you in the future,
|
||||
but right now, just this once, send them to voicemail."
|
||||
*/
|
||||
|
||||
/* screen-callee-options script:
|
||||
"Dial 1 if you wish to immediately connect to the incoming call
|
||||
Dial 2 if you wish to send this caller to voicemail.
|
||||
Dial 3 to send this callerr to the torture menus.
|
||||
Dial 4 to send this caller to a simple "go away" menu.
|
||||
*/
|
||||
if( !res2 || res2 < '1' || (privacy && res2 > '5') || (screen && res2 > '4') ) {
|
||||
/* invalid option */
|
||||
res2 = ast_play_and_wait(peer,"vm-sorry");
|
||||
}
|
||||
loopcount++; /* give the callee a couple chances to make a choice */
|
||||
} while( (!res2 || res2 < '1' || (privacy && res2 > '5') || (screen && res2 > '4')) && loopcount < 2 );
|
||||
}
|
||||
|
||||
switch(res2) {
|
||||
case '1':
|
||||
if( privacy ) {
|
||||
if (option_verbose > 2)
|
||||
ast_verbose( VERBOSE_PREFIX_3 "--Set privacy database entry %s/%s to ALLOW\n", privdb, privcid);
|
||||
ast_privacy_set(privdb,privcid,AST_PRIVACY_ALLOW);
|
||||
}
|
||||
break;
|
||||
case '2':
|
||||
if( privacy ) {
|
||||
if (option_verbose > 2)
|
||||
ast_verbose( VERBOSE_PREFIX_3 "--Set privacy database entry %s/%s to DENY\n", privdb, privcid);
|
||||
ast_privacy_set(privdb,privcid,AST_PRIVACY_DENY);
|
||||
}
|
||||
if ( strchr(transfer, 'm') ) {
|
||||
ast_moh_stop(chan);
|
||||
} else if ( strchr(transfer, 'r') ) {
|
||||
ast_indicate(chan, -1);
|
||||
sentringing=0;
|
||||
}
|
||||
res2 = ast_autoservice_stop(chan);
|
||||
ast_hangup(peer); /* hang up on the callee -- he didn't want to talk anyway! */
|
||||
res=0;
|
||||
goto out;
|
||||
break;
|
||||
case '3':
|
||||
if( privacy ) {
|
||||
ast_privacy_set(privdb,privcid,AST_PRIVACY_TORTURE);
|
||||
if (option_verbose > 2)
|
||||
ast_verbose( VERBOSE_PREFIX_3 "--Set privacy database entry %s/%s to TORTURE\n", privdb, privcid);
|
||||
}
|
||||
ast_copy_string(status, "TORTURE", sizeof(status));
|
||||
|
||||
res = 0;
|
||||
if ( strchr(transfer, 'm') ) {
|
||||
ast_moh_stop(chan);
|
||||
} else if ( strchr(transfer, 'r') ) {
|
||||
ast_indicate(chan, -1);
|
||||
sentringing=0;
|
||||
}
|
||||
res2 = ast_autoservice_stop(chan);
|
||||
ast_hangup(peer); /* hang up on the caller -- he didn't want to talk anyway! */
|
||||
goto out; /* Is this right? */
|
||||
break;
|
||||
case '4':
|
||||
if( privacy ) {
|
||||
if (option_verbose > 2)
|
||||
ast_verbose( VERBOSE_PREFIX_3 "--Set privacy database entry %s/%s to KILL\n", privdb, privcid);
|
||||
ast_privacy_set(privdb,privcid,AST_PRIVACY_KILL);
|
||||
}
|
||||
|
||||
ast_copy_string(status, "DONTCALL", sizeof(status));
|
||||
res = 0;
|
||||
if ( strchr(transfer, 'm') ) {
|
||||
ast_moh_stop(chan);
|
||||
} else if ( strchr(transfer, 'r') ) {
|
||||
ast_indicate(chan, -1);
|
||||
sentringing=0;
|
||||
}
|
||||
res2 = ast_autoservice_stop(chan);
|
||||
ast_hangup(peer); /* hang up on the caller -- he didn't want to talk anyway! */
|
||||
goto out; /* Is this right? */
|
||||
break;
|
||||
case '5':
|
||||
if( privacy ) {
|
||||
if (option_verbose > 2)
|
||||
ast_verbose( VERBOSE_PREFIX_3 "--Set privacy database entry %s/%s to ALLOW\n", privdb, privcid);
|
||||
ast_privacy_set(privdb,privcid,AST_PRIVACY_ALLOW);
|
||||
|
||||
if ( strchr(transfer, 'm') ) {
|
||||
ast_moh_stop(chan);
|
||||
} else if ( strchr(transfer, 'r') ) {
|
||||
ast_indicate(chan, -1);
|
||||
sentringing=0;
|
||||
}
|
||||
res2 = ast_autoservice_stop(chan);
|
||||
ast_hangup(peer); /* hang up on the caller -- he didn't want to talk anyway! */
|
||||
res=0;
|
||||
goto out;
|
||||
break;
|
||||
} /* if not privacy, then 5 is the same as "default" case */
|
||||
default:
|
||||
/* well, if the user messes up, ... he had his chance... What Is The Best Thing To Do? */
|
||||
/* well, there seems basically two choices. Just patch the caller thru immediately,
|
||||
or,... put 'em thru to voicemail. */
|
||||
/* since the callee may have hung up, let's do the voicemail thing, no database decision */
|
||||
if (option_verbose > 2)
|
||||
ast_log(LOG_NOTICE,"privacy: no valid response from the callee. Sending the caller to voicemail, the callee isn't responding\n");
|
||||
if ( strchr(transfer, 'm') ) {
|
||||
ast_moh_stop(chan);
|
||||
} else if ( strchr(transfer, 'r') ) {
|
||||
ast_indicate(chan, -1);
|
||||
sentringing=0;
|
||||
}
|
||||
res2 = ast_autoservice_stop(chan);
|
||||
ast_hangup(peer); /* hang up on the callee -- he didn't want to talk anyway! */
|
||||
res=0;
|
||||
goto out;
|
||||
break;
|
||||
}
|
||||
if ( strchr(transfer, 'm') ) {
|
||||
ast_moh_stop(chan);
|
||||
} else if ( strchr(transfer, 'r') ) {
|
||||
ast_indicate(chan, -1);
|
||||
sentringing=0;
|
||||
}
|
||||
res2 = ast_autoservice_stop(chan);
|
||||
/* if the intro is NOCALLERID, then there's no reason to leave it on disk, it'll
|
||||
just clog things up, and it's not useful information, not being tied to a CID */
|
||||
if( strncmp(privcid,"NOCALLERID",10) == 0 || no_save_intros ) {
|
||||
ast_filedelete(privintro, NULL);
|
||||
if( ast_fileexists(privintro,NULL,NULL ) > 0 )
|
||||
ast_log(LOG_NOTICE,"privacy: ast_filedelete didn't do its job on %s\n", privintro);
|
||||
else if (option_verbose > 2)
|
||||
ast_verbose( VERBOSE_PREFIX_3 "Successfully deleted %s intro file\n", privintro);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (announce && announcemsg) {
|
||||
/* Start autoservice on the other chan */
|
||||
res = ast_autoservice_start(chan);
|
||||
|
@@ -304,6 +304,31 @@ exten => _s-.,1,Goto(s-NOANSWER,1) ; Treat anything else as no answer
|
||||
|
||||
exten => a,1,VoicemailMain(${ARG1}) ; If they press *, send the user into VoicemailMain
|
||||
|
||||
[macro-stdPrivacyexten];
|
||||
;
|
||||
; Standard extension macro:
|
||||
; ${ARG1} - Extension (we could have used ${MACRO_EXTEN} here as well
|
||||
; ${ARG2} - Device(s) to ring
|
||||
; ${ARG3} - Optional DONTCALL context name to jump to (assumes the s,1 extension-priority)
|
||||
; ${ARG4} - Optional TORTURE context name to jump to (assumes the s,1 extension-priority)`
|
||||
;
|
||||
exten => s,1,Dial(${ARG2},20|p) ; Ring the interface, 20 seconds maximum, call screening option (or use P for databased call screening)
|
||||
exten => s,2,Goto(s-${DIALSTATUS},1) ; Jump based on status (NOANSWER,BUSY,CHANUNAVAIL,CONGESTION,ANSWER)
|
||||
|
||||
exten => s-NOANSWER,1,Voicemail(u${ARG1}) ; If unavailable, send to voicemail w/ unavail announce
|
||||
exten => s-NOANSWER,2,Goto(default,s,1) ; If they press #, return to start
|
||||
|
||||
exten => s-BUSY,1,Voicemail(b${ARG1}) ; If busy, send to voicemail w/ busy announce
|
||||
exten => s-BUSY,2,Goto(default,s,1) ; If they press #, return to start
|
||||
|
||||
exten => s-DONTCALL,1,Goto(${ARG3},s,1) ; Callee chose to send this call to a polite "Don't call again" script.
|
||||
|
||||
exten => s-TORTURE,1,Goto(${ARG4},s,1) ; Callee chose to send this call to a telemarketer torture script.
|
||||
|
||||
exten => _s-.,1,Goto(s-NOANSWER,1) ; Treat anything else as no answer
|
||||
|
||||
exten => a,1,VoicemailMain(${ARG1}) ; If they press *, send the user into VoicemailMain
|
||||
|
||||
[demo]
|
||||
;
|
||||
; We start with what to do when a call first comes in.
|
||||
|
361
doc/README.privacy
Executable file
361
doc/README.privacy
Executable file
@@ -0,0 +1,361 @@
|
||||
Title: Everything About The Privacy Options In The Dial Command That
|
||||
You Never Wanted To Know, And Even A Little More On Zapateller and
|
||||
PrivacyManager:
|
||||
|
||||
by Steve Murphy
|
||||
|
||||
|
||||
So, you want to avoid talking to pesky telemarketers/charity
|
||||
seekers/poll takers/magazine renewers/etc?
|
||||
|
||||
=============
|
||||
First of all:
|
||||
=============
|
||||
|
||||
Try the FTC "Don't call" database, this alone will reduce your
|
||||
telemarketing call volume considerably. (see:
|
||||
https://www.donotcall.gov/default.aspx ) But, this list won't protect
|
||||
from the Charities, previous business relationships, etc.
|
||||
|
||||
|
||||
=================================
|
||||
Next, Fight against autodialers!!
|
||||
=================================
|
||||
|
||||
Zapateller detects if callerid is present, and if not, plays the
|
||||
da-da-da tones that immediately precede messages like, "I'm sorry,
|
||||
the number you have called is no longer in service."
|
||||
|
||||
Most humans, even those with unlisted/callerid-blocked numbers, will
|
||||
not immediately slam the handset down on the hook the moment they hear
|
||||
the three tones. But autodialers seem pretty quick to do this.
|
||||
|
||||
I just counted 40 hangups in Zapateller over the last year in my
|
||||
CDR's. So, that is possibly 40 different telemarketers/charities that have
|
||||
hopefully slashed my back-waters, out-of-the-way, humble home phone
|
||||
number from their lists.
|
||||
|
||||
I highly advise Zapateller for those seeking the nirvana of "privacy".
|
||||
|
||||
|
||||
=======================================
|
||||
Next, Fight against the empty CALLERID!
|
||||
=======================================
|
||||
|
||||
A considerable percentage of the calls you don't want, come from
|
||||
sites that do not provide CallerID.
|
||||
|
||||
Null callerid's are a fact of life, and could be a friend with an
|
||||
unlisted number, or some charity looking for a handout. The
|
||||
PrivacyManager application can help here. It will ask the caller to
|
||||
enter a 10-digit phone number. They get 3 tries(configurable), and this is
|
||||
configurable, with control being passed to priority+101 if they won't
|
||||
supply one.
|
||||
|
||||
PrivacyManager can't guarantee that the number they supply is any
|
||||
good, tho, as there is no way to find out, short of hanging up and
|
||||
calling them back. But some answers are obviously wrong. For instance,
|
||||
it seems a common practice for telemarketers to use your own number
|
||||
instead of giving you theirs. A simple test can detect this. More
|
||||
advanced tests would be to look for -555- numbers, numbers that count
|
||||
up or down, numbers of all the same digit, etc.
|
||||
|
||||
My logs show that 39 have hung up in the PrivacyManager script over
|
||||
the last year.
|
||||
|
||||
(Note: Demanding all unlisted incoming callers to enter their CID may
|
||||
not always be appropriate for all users. Another option might be to
|
||||
use call screening. See below.)
|
||||
|
||||
==========================
|
||||
Next, use a WELCOME MENU !
|
||||
==========================
|
||||
|
||||
Experience has shown that simply presenting incoming callers with
|
||||
a set of options, no matter how simple, will deter them from calling
|
||||
you. In the vast majority of situations, a telemarketer will simply
|
||||
hang up rather than make a choice and press a key.
|
||||
|
||||
This will also immediately foil all autodialers that simply belch a
|
||||
message in your ear and hang up.
|
||||
|
||||
|
||||
----------------------------------------------
|
||||
Example usage of Zapateller and PrivacyManager:
|
||||
----------------------------------------------
|
||||
|
||||
[homeline]
|
||||
exten => s,1,Answer
|
||||
exten => s,2,SetVar,repeatcount=0
|
||||
exten => s,3,Zapateller,nocallerid
|
||||
exten => s,4,PrivacyManager
|
||||
exten => s,105,Background(tt-allbusy) ;; do this if they don't enter a number to Privacy Manager
|
||||
exten => s,106,Background(tt-somethingwrong)
|
||||
exten => s,107,Background(tt-monkeysintro)
|
||||
exten => s,108,Background(tt-monkeys)
|
||||
exten => s,109,Background(tt-weasels)
|
||||
exten => s,110,Hangup
|
||||
exten => s,5,GotoIf($[ "${CALLERIDNUM}" = "7773334444" & "${CALLERIDNAME}" : "Privacy Manager" ]?callerid-liar|s|1:s|7)
|
||||
|
||||
I suggest using Zapateller at the beginning of the context, before
|
||||
anything else, on incoming calls.This can be followed by the
|
||||
PrivacyManager App.
|
||||
|
||||
Make sure, if you do the PrivacyManager app, that you take care of the
|
||||
error condition! or their non-compliance will be rewarded with access
|
||||
to the system. In the above, if they can't enter a 10-digit number in
|
||||
3 tries, they get the humorous "I'm sorry, but all household members
|
||||
are currently helping other telemarketers...", "something is terribly
|
||||
wrong", "monkeys have carried them away...", various loud monkey
|
||||
screechings, "weasels have...", and a hangup. There are plenty of
|
||||
other paths to my torture scripts, I wanted to have some fun.
|
||||
|
||||
In nearly all cases now, the telemarketers/charity-seekers that
|
||||
usually get thru to my main intro, hang up. I guess they can see it's
|
||||
pointless, or the average telemarketer/charity-seeker is instructed
|
||||
not to enter options when encountering such systems. Don't know.
|
||||
|
||||
===================
|
||||
Next: Torture Them!
|
||||
===================
|
||||
|
||||
I have developed an elaborate script to torture Telemarketers, and
|
||||
entertain friends. (See
|
||||
http://www.voip-info.org/wiki-Asterisk+Telemarketer+Torture )
|
||||
|
||||
While mostly those that call in and traverse my teletorture scripts
|
||||
are those we know, and are doing so out of curiosity, there have been
|
||||
these others from Jan 1st,2004 thru June 1st, 2004:
|
||||
(the numbers may or may not be correct.)
|
||||
|
||||
603890zzzz hung up telemarket options.
|
||||
"Integrated Sale" called a couple times. hung up in telemarket options
|
||||
"UNITED STATES GOV" (-- maybe a military recruiter, trying to lure one of my sons).
|
||||
800349zzzz -- hung up in charity intro
|
||||
800349zzzz -- hung up in charity choices, intro, about the only one who actually travelled to the bitter bottom of the scripts!
|
||||
216377zzzz -- hung up the magazine section
|
||||
626757zzzz = "LIR " (pronounced "Liar"?) hung up in telemarket intro, then choices
|
||||
757821zzzz -- hung up in new magazine subscription options.
|
||||
|
||||
That averages out to maybe 1 a month. That puts into question whether
|
||||
the ratio of the amount of labor it took to make the scripts versus
|
||||
the benefits of lower call volumes was worth it, but, well, I had fun,
|
||||
so what the heck.
|
||||
|
||||
but, that's about it. Not a whole lot. But I haven't had to say "NO"
|
||||
or "GO AWAY" to any of these folks for about a year now ...!
|
||||
|
||||
========================================
|
||||
Using Call Screening
|
||||
=======================================
|
||||
|
||||
Another option is to use call screening in the Dial command. It has
|
||||
two main privacy modes, one that remembers the CID of the caller, and
|
||||
how the callee wants the call handled, and the other, which does not
|
||||
have a "memory".
|
||||
|
||||
Turning on these modes in the dial command results in this sequence of
|
||||
events, when someone calls you at an extension:
|
||||
|
||||
1. The caller calls the Asterisk system, and at some point, selects an
|
||||
option or enters an extension number that would dial your extension.
|
||||
|
||||
2. Before ringing your extension, the caller is asked to supply an
|
||||
introduction. The application asks them: "After the tone, say your
|
||||
name". They are allowed 4 seconds of introduction.
|
||||
|
||||
3. After that, they are told "Hang on, we will attempt to connect you
|
||||
to your party. Depending on your dial options, they will hear ringing
|
||||
indications, or get music on hold. I suggest music on hold.
|
||||
|
||||
4. Your extension is then dialed. When (and if) you pick up, you are
|
||||
told that a caller presenting themselves as <their recorded intro is
|
||||
played> is calling, and you have options, like being connected,
|
||||
sending them to voicemail, torture, etc.
|
||||
|
||||
5. You make your selection, and the call is handled as you chose.
|
||||
|
||||
|
||||
There are some variations, and these will be explained in due course.
|
||||
|
||||
|
||||
To use these options, set your Dial to something like:
|
||||
|
||||
exten => 3,3,Dial(Zap/5r3&Zap/6r3|35|tmPA(beep))
|
||||
|
||||
or
|
||||
|
||||
exten => 3,3,Dial(Zap/5r3&Zap/6r3|35|tmP(something)A(beep))
|
||||
|
||||
or
|
||||
|
||||
exten => 3,3,Dial(Zap/5r3&Zap/6r3|35|tmpA(beep))
|
||||
|
||||
|
||||
The 't' allows the dialed party to transfer the call using '#'. It's
|
||||
optional.
|
||||
|
||||
The 'm' is for music on hold. I suggest it. Otherwise, the calling
|
||||
party gets to hear all the ringing, and lack thereof. It is generally
|
||||
better to use Music On Hold. Lots of folks hang up after the 3rd or
|
||||
4th ring, and you might lose the call before you can enter an option!
|
||||
|
||||
The 'P' option alone will database everything using the extension as a
|
||||
default 'tree'. To get multiple extensions sharing the same database, use
|
||||
P(some-shared-key). Also, if the same person has multiple extensions,
|
||||
use P(unique-id) on all their dial commands.
|
||||
|
||||
Use little 'p' for screening. Every incoming call will include a
|
||||
prompt for the callee's choice.
|
||||
|
||||
the A(beep), will generate a 'beep' that the callee will hear if they
|
||||
choose to talk to the caller. It's kind of a prompt to let the callee
|
||||
know that he has to say 'hi'. It's not required, but I find it
|
||||
helpful.
|
||||
|
||||
When there is no CallerID, P and p options will always record an intro
|
||||
for the incoming caller. This intro will be stored temporarily in the
|
||||
/var/lib/asterisk/sounds/priv-callerintros dir, under the name
|
||||
NOCALLERID_<extension><channelname> and will be erased after the
|
||||
callee decides what to do with the call.
|
||||
|
||||
Of course, NOCALLERID is not stored in the database. All those with no
|
||||
CALLERID will be considered "Unknown".
|
||||
|
||||
========================
|
||||
The 'N' and 'n' options
|
||||
========================
|
||||
|
||||
Two other options exist, that act as modifiers to the privacy options
|
||||
'P' and 'p'. They are 'N' and 'n'. You can enter them as dialing
|
||||
options, but they only affect things if P or p are also in the
|
||||
options.
|
||||
|
||||
'N' says, "Only screen the call if no CallerID is present". So, if a
|
||||
callerID were supplied, it will come straight thru to your extension.
|
||||
|
||||
'n' says, "Don't save any introductions". Folks will be asked to
|
||||
supply an introduction ("At the tone, say your name") every time they
|
||||
call. Their introductions will be removed after the callee makes a
|
||||
choice on how to handle the call. Whether the P option or the p option
|
||||
is used, the incoming caller will have to supply their intro every
|
||||
time they call.
|
||||
|
||||
=======================
|
||||
Recorded Introductions
|
||||
=======================
|
||||
|
||||
[Philosophical Side Note:
|
||||
The 'P' option stores the CALLERID in the database, along with the
|
||||
callee's choice of actions, as a convenience to the CALLEE, whereas
|
||||
introductions are stored and re-used for the convenience of the CALLER.]
|
||||
|
||||
Unless instructed to not save introductions (see the 'n' option above),
|
||||
the screening modes will save the recordings of the caller's names in
|
||||
the directory /var/lib/asterisk/sounds/priv-callerintros, if they have
|
||||
a CallerID. Just the 10-digit callerid numbers are used as filenames,
|
||||
with a ".gsm" at the end.
|
||||
|
||||
Having these recordings around can be very useful, however...
|
||||
|
||||
First of all, if a callerid is supplied, and a recorded intro for that
|
||||
number is already present, the caller is spared the inconvenience of
|
||||
having to supply their name, which shortens their call a bit.
|
||||
|
||||
Next of all, these intros can be used in voicemail, played over
|
||||
loudspeakers, and perhaps other nifty things. For instance:
|
||||
|
||||
exten => s,7,System(/usr/bin/play /var/lib/asterisk/sounds/priv-callerintros/${CALLERIDNUM}.gsm&|0)
|
||||
|
||||
When a call comes in at the house, the above priority gets executed,
|
||||
and the callers intro is played over the phone systems speakers. This
|
||||
gives us a hint who is calling.
|
||||
|
||||
(Note: the |0 option at the end of the System command above, is a
|
||||
local mod I made to the System command. It forces a 0 result code to
|
||||
be returned, whether the play command successfully completed or
|
||||
not. Therefore, I don't have to ensure that the file exists or
|
||||
not. While I've turned this mod into the developers, it hasn't been
|
||||
incorporated yet. You might want to write an AGI or shell script to
|
||||
handle it a little more intelligently)
|
||||
|
||||
And one other thing. You can easily supply your callers with an option
|
||||
to listen to, and re-record their introductions. Here's what I did in
|
||||
the home system's extensions.conf. (assume that a
|
||||
Goto(home-introduction|s|1) exists somewhere in your main menu as an
|
||||
option):
|
||||
|
||||
[home-introduction]
|
||||
exten => s,1,Background,intro-options ;; Script: To hear your Introduction, dial 1.
|
||||
;; to record a new introduction, dial 2.
|
||||
;; to return to the main menu, dial 3.
|
||||
;; to hear what this is all about, dial 4.
|
||||
exten => 1,1,Playback,priv-callerintros/${CALLERIDNUM}
|
||||
exten => 1,2,Goto(s,1)
|
||||
exten => 2,1,Goto(home-introduction-record,s,1)
|
||||
exten => 3,1,Goto(homeline,s,7)
|
||||
exten => 4,1,Playback,intro-intro ;; Script:
|
||||
;; This may seem a little strange, but it really is a neat
|
||||
;; thing, both for you and for us. I've taped a short introduction
|
||||
;; for many of the folks who normally call us. Using the Caller ID
|
||||
;; from each incoming call, the system plays the introduction
|
||||
;; for that phone number over a speaker, just as the call comes in.
|
||||
;; This helps the folks
|
||||
;; here in the house more quickly determine who is calling.
|
||||
;; and gets the right ones to gravitate to the phone.
|
||||
;; You can listen to, and record a new intro for your phone number
|
||||
;; using this menu.
|
||||
exten => 4,2,Goto(s,1)
|
||||
exten => t,1,Goto(s,1)
|
||||
exten => i,1,Background,invalid
|
||||
exten => i,2,Goto(s,1)
|
||||
exten => o,1,Goto(s,1)
|
||||
|
||||
[home-introduction-record]
|
||||
exten => s,1,Background,intro-record-choices ;; Script:
|
||||
;; If you want some advice about recording your
|
||||
;; introduction, dial 1.
|
||||
;; otherwise, dial 2, and introduce yourself after
|
||||
;; the beep.
|
||||
exten => 1,1,Playback,intro-record
|
||||
;; Your introduction should be short and sweet and crisp.
|
||||
;; Your introduction will be limited to 4 seconds.
|
||||
;; This is NOT meant to be a voice mail message, so
|
||||
;; please, don't say anything about why you are calling.
|
||||
;; After we are done making the recording, your introduction
|
||||
;; will be saved for playback.
|
||||
;; If you are the only person that would call from this number,
|
||||
;; please state your name. Otherwise, state your business
|
||||
;; or residence name instead. For instance, if you are
|
||||
;; friend of the family, say, Olie McPherson, and both
|
||||
;; you and your kids might call here a lot, you might
|
||||
;; say: "This is the distinguished Olie McPherson Residence!"
|
||||
;; If you are the only person calling, you might say this:
|
||||
;; "This is the illustrious Kermit McFrog! Pick up the Phone, someone!!"
|
||||
;; If you are calling from a business, you might pronounce a more sedate introduction,like,
|
||||
;; "Fritz from McDonalds calling.", or perhaps the more original introduction:
|
||||
;; "John, from the Park County Morgue. You stab 'em, we slab 'em!".
|
||||
;; Just one caution: the kids will hear what you record every time
|
||||
;; you call. So watch your language!
|
||||
;; I will begin recording after the tone.
|
||||
;; When you are done, hit the # key. Gather your thoughts and get
|
||||
;; ready. Remember, the # key will end the recording, and play back
|
||||
;; your intro. Good Luck, and Thank you!"
|
||||
exten => 1,2,Goto(2,1)
|
||||
exten => 2,1,Background,intro-start
|
||||
;; OK, here we go! After the beep, please give your introduction.
|
||||
exten => 2,2,Background,beep
|
||||
exten => 2,3,Record,priv-callerintros/${CALLERIDNUM}:gsm|4
|
||||
exten => 2,4,Background,priv-callerintros/${CALLERIDNUM}
|
||||
exten => 2,5,Goto(home-introduction,s,1)
|
||||
exten => t,1,Goto(s,1)
|
||||
exten => i,1,Background,invalid
|
||||
exten => i,2,Goto(s,1)
|
||||
exten => o,1,Goto(s,1)
|
||||
|
||||
|
||||
In the above, you'd most likely reword the messages to your liking,
|
||||
and maybe do more advanced things with the 'error' conditions (i,o,t priorities),
|
||||
but I hope it conveys the idea...
|
||||
|
||||
|
10
sounds.txt
10
sounds.txt
@@ -250,6 +250,16 @@
|
||||
|
||||
%priv-instruct.gsm%Press 1 to accept this call. Press 2 to not accept this call. Press 3 to always accept calls from this number. Press 4 to never accept calls from this number. Press 5 to reject calls from this number and request that they add you to their do not call list.
|
||||
|
||||
%priv-callee-options.gsm%Dial 1 if you wish this caller to reach you directly now, and in the future. Dial 2 if you wish to send this caller to voicemail now and forevermore. Dial 3 to send this caller to the torture menus, now and forevermore. Dial 4 to send this caller to a polite "don't call" menu, now and forevermore. Dial 5 to allow this caller to come straight thru to you in the future, but just this once, send them to voicemail.
|
||||
|
||||
%screen-callee-options.gsm%You have these options: Dial 1 if you wish to immediately connect to the incoming call. Dial 2 if you wish to send this caller to voicemail. Dial 3 to send this callerr to the torture menus. Dial 4 to send this caller to a polite "don't call" menu.
|
||||
|
||||
%priv-introsaved.gsm%Thank you. Please hold, while I attempt to connect you with your party!
|
||||
|
||||
%priv-recordintro.gsm%At the tone, please say your name.
|
||||
|
||||
%priv-callpending.gsm%I have a caller waiting, who introduces themselves as:
|
||||
|
||||
%privacy-unident.gsm%The party you are trying to reach does not accept unidentified calls.
|
||||
|
||||
%privacy-prompt.gsm%Please enter your phone number, starting with the area code.
|
||||
|
BIN
sounds/priv-callee-options.gsm
Executable file
BIN
sounds/priv-callee-options.gsm
Executable file
Binary file not shown.
BIN
sounds/priv-callpending.gsm
Executable file
BIN
sounds/priv-callpending.gsm
Executable file
Binary file not shown.
BIN
sounds/priv-introsaved.gsm
Executable file
BIN
sounds/priv-introsaved.gsm
Executable file
Binary file not shown.
BIN
sounds/priv-recordintro.gsm
Executable file
BIN
sounds/priv-recordintro.gsm
Executable file
Binary file not shown.
BIN
sounds/screen-callee-options.gsm
Executable file
BIN
sounds/screen-callee-options.gsm
Executable file
Binary file not shown.
Reference in New Issue
Block a user