Accept or reject call with IVR and transfer call upon acception

Hi, first time freepbx user so be easy.

I’ve got most configured to my liking. Thanks for the excellent work. However I can not figure out one last goal.

I’m looking for the following functionality:
Caller’s without CID (hidden or anonymous) are answered by a custom destination. Which triggers a macro. The macro prompts the caller the speak their name and press the # to try to connect them. After the caller’s name has been recorded. The ringgroup should be dialed. The first extension to pickup should hear the caller’s name recording followed by a press 1 to accept menu or hangup to goto voicemail. If the user presses 1 to original incoming call should be transfered to the extension.

What works:
Via a macro in extensions_custom.conf I can record the callers name to a temporary file and get that recording in a voicemail box. See snippet below.

What doesn’t work:

  • How to dial an extension and present an IVR upon answer? (the reverse, freepbx answers and plays IVR works out the box)
  • How to transfer the call when user presses 1 to accept. Should I park the call or can it be transferred?

Please note that this is not the same as the privacy manager application which ask the caller to enter digits. Many government bodies don’t have direct phonenumbers. So asking them to enter their number is pointless. But asking them for their name isn’t.

Thank you for looking into this.

exten => s,1,answer()
exten => s,n,playback(/var/lib/asterisk/sounds/nl/custom/message356)
exten => s,n,Record(${UNIQUEID}.ulaw,3,15,a)

;Generate .call file that asterisk will use to send the call to a voicemail box
exten => s,n,system(echo "Channel: LOCAL/1000" > /var/lib/asterisk/sounds/
exten => s,n,system(echo "Context: macro-questionanswer1" >> /var/lib/asterisk/sounds/
exten => s,n,system(echo "Extension: s" >> /var/lib/asterisk/sounds/
exten => s,n,system(echo "Setvar: playfile=${UNIQUEID}" >> /var/lib/asterisk/sounds/;

exten => s,n,system(cp /var/lib/asterisk/sounds/ /var/spool/asterisk/outgoing/
exten => s,n,hangup()

exten => s,1,wait(1)
exten => s,n,senddtmf(#)
exten => s,n,playback(/var/lib/asterisk/sounds/${playfile})

Simple stuff first:

  1. I think the “Channel:” entry needs a context. ‘@from-internal’ on the end would probably work. Check it, though, since I’m not sure when the context is required and when it’s optional.
  2. Your last ‘system()’ call should use ‘mv’ instead of ‘cp’ to make sure the entire file is in place when you kick off the call. You run the risk of a half-copied file being executed this way.

Finally, I’m reasonably sure there’s a better way to do this than using a CallFile, since you can initiate a call from the context directly. I’m pretty sure this is going to end up with a dead call at the end of it since you never bridge the incoming call to the outgoing call to extension 1000.

With the power of the FreePBX Dialplan, I’m almost certain there’s another approach that would work just as well, if not better. This seems a little “Rube Goldberg” to me.

Finally, with your concern about “master numbers and names” taken, perhaps a more advantageous approach would be to take the Open Source Privacy Manager app and changing it to meet your specific need; perhaps even donating your changes back to the cause. Lots of people in the government have direct numbers, though, so part of your premise isn’t completely solid. I see more corporate locations having central numbers and extensions than government offices.

Thank you for your reply.

You’re completely right with point -2-, it should be mv. The cp instead of mv was a leftover from debugging. I had mv before the cp. For the rest it works as expected. I’ll look into your point -1-

The whole call file approach was more some fiddling around than the basis of a solid approach.
Those were my main questions:

  • How can I play an IVR to a dialed extension?
  • And how can I connect / transfer / unpark / brdige the original caller to the dialed extension?

I don’t understand what you mean by the privacy manager app. If you mean asterisk/apps/app_privacy.c, than I can inform you that I looked into that. But it lacks certain components. No dialing of another extension, no IVR for a dialed extension, no recording, no parking/bridging/transfering. It only changes the CLIP and CNIP. Lastly I lack the knowledge off to set this up properly. Do I need to implement this in C? Can this be implemented in the dialplan? If so what would be appropriate mechanisms to use (parking etc)

To all, I don’t ask for a complete solution. But for pointers in the general (correct) direction.

Thank you all for your time and interest.

It helps to think of the pieces as components of a larger stream of data.

As you move through the data, you move from context to context. You start out in your “inbound routes”, then transfer (based on CID) to an IVR. From the IVR, you branch into another context. Now, in your case, the context you are branching in to doesn’t exists - there’s nothing that records a name and plays it back (like your example should), but the idea of passing the call from context to context still applies.

So, for example, you don’t “play” an IVR to a dialed extension. The IVR can connect you to an extension (or ring group, etc.) based on the option chosen. Getting to the dialed extension also requires some custom context work, but the “${DID}” variable (or something similar) that the Inbound Route would interrogate is global within the subsequent context, so even if you end up writing a custom piece of code and connect it to the GUI through a Custom Application (for example), you should be able to build your application out to do what you are trying to accomplish.

One facility you might need to learn about is the “loopback” route, there you send a call (with DID and CID set) back into the Inbound Route for processing. This way, you could send a call to your “special” context, set up the environment, and drop it back onto the Inbound Routes with everything set.

As well it shouldn’t. It serves a single, simple purpose - to set up the Privacy Component and then route the call based on the database setting for your call strategy. In that regard, it works more like an announcement (which similarly doesn’t do any of those things) but is just the first step in the multi-context journey for your incoming call. From Call Privacy, you drop into (for example) an IVR, or an extension, or some other mechanism (and there are tons already built into the GUI) to continue processing the call.

In the Advanced Settings for an extension, you’ll find an option Call Screening, which is very similar to what you are trying to implement. From the tool tip:

Call Screening requires external callers to say their name, which will be played
back to the user and allow the user to accept or reject the call. ...

I suggest you experiment with it. You won’t be able to use it directly, but making a copy of its code and modifying it to meet your needs may be an easy way to achieve your application.

However, can you please explain the overall goal? If you are just trying to filter out spam/scam callers, the simplest IVR will do that. However, desired callbacks from large organizations are often partly automated and will fail to operate the IVR. Unfortunately, asking a robot to say his name would have the same problem.

This thread may be useful:

If most of the calls you receive without CID are ‘straightforwardly’ blocked (by dialing a code or asking the carrier to hide caller ID), you may be able to reveal them with a DID that passes ANI information. Assuming that the number in question is in the Netherlands, take a look at AnveoDirect (US based but has a POP in Germany) and Voxbeam (UK based with a POP in the Netherlands).

Thank you for your time.

Your last reply is more what I’m looking for, the components. I know a little bit about the context’s. I’ll look into the “loopback route” you introduced, as well as your other suggestions.

Could you please explain to me how the last goal below could be achieved (in general terms):
WORKS inbound route -> dial extension -> picks up -> start talking
WORKS inbound route -> dial extension -> picks up -> announcement ->
start talking
WORKS inbound route -> IVR -> if 1 pressed by caller dial extension -> picks up -> start talking
HOW?? inbound route -> dial extension -> picks up -> IVR for callee -> if 1 pressed by callee connect caller to callee -> start talking

I was already searching in the freepbx php code where the call screening feature was implemented. Found several pieces of glue but not the actual logic.

Again thank you for your time and patience.

@Stewart1, thank you for your reply. My reply to @cynjut crossed yours, so the thread is a bit messed up.

Your completely right, call screening is just what I want but only for hidden numbers.
As I wrote to @cynjut I’m searching the freepbx code for call_screen functionality. I’ve found some in macro-dial.php macro-dial-one.php and dialparties.agi. Only glue and setup not the actual logic.

I’ll look into the thread you posted and especially the attached code.

With regards to passing the ANI information, that’s an interesting suggestion. Yes my numbers are generic dutch numbers. However I would like to look into that as a last resort because I would need to migrate my numbers to yet another provider.

Again thank you as well for your time and suggestions.

Create a Virtual Extension. Enable Follow Me with Initial Ring Time set to 0, Ring Time as desired, Follow-Me List with the members of your existing Ring Group, Call Screening set to Screen Caller: No Memory.

Create an Inbound Route that sends anonymous calls to the virtual extension.

Edit: I tested this with only one member – there may be a problem where when one phone is answered the others will continue to ring while the callee decides whether to accept the call.

@Stewart1, your previous post led me to this post: zippee’s creep detector
Which led me to a working solution :tada:

I added this to extensions_custom.conf

exten => s,1,Zapateller(answer,nocallerid)
exten => s,2,Wait(1)
exten => s,3,Set(CHANNEL(musicclass)=default)
exten => s,4,GotoIf($["${CALLERID(num)}" = ""]?custom-screen,s,1)
exten => s,5,GotoIf($["foo${CALLERID(num)}" = "foo"]?custom-screen,s,1)
exten => s,6,GotoIf($["${CALLERID(name):0:9}" = "Anonymous"]?custom-screen,s,1)
exten => s,7,GotoIf($["${CALLERID(name):0:7}" = "Unknown"]?custom-screen,s,1)
exten => s,8,GotoIf($["${CALLERID(num):0:7}" = "Private"]?custom-screen,s,1)
exten => s,9,GotoIf($["${CALLERID(name):0:7}" = "Private"]?custom-screen,s,1)
exten => s,10,GotoIf($["${CALLERID(num):0:10}" = "Restricted"]?custom-screen,s,1)
exten => s,11,GotoIf($["${CALLERID(num):0:4}" = "PSTN"]?custom-screen,s,1)
exten => s,12,Dial(Local/[email protected])
exten => s,13,Hangup

exten => s,1,Background(privacy-unident)
exten => s,2,Dial(Local/[email protected]) ;replace with your screening enabled extension
exten => s,3,Hangup

In extension I created a custom extension 4599 and added to the dial field local/[email protected] Finally on the inbound route as destination I used Custom Destination “filter”
This just works as a charm. Tested with a ringroup (4003) with two extentions.

Now I’ll try your other solution. I already see one potential benefit of zippee’s solution and that it doesn’t require the extra follow-me module.

You shouldn’t need any custom dialplan to filter numbers. If CALLERID(num) is a properly formatted number, use it; otherwise treat the call as anonymous.

I’m guessing that your provider uses one of two formats for presenting caller ID:

+31202345678 (an Amsterdam number)
+33142345678 (a Paris number)


0202345678 (an Amsterdam number)
0033142345678 (a Paris number)

Set an Inbound Route that matches the valid CID patterns and sends the call to the ring group destination. A second Inbound Route with CID blank sends calls to screening.


I did what you suggested and it almost … works :disappointed:

  • Installed the follow me module.
  • Added a custom extension 4593, initial ringtimeout 0, ringstrategy ringallv2, ringtime 20, follow-me list 1000 and 4013, destination no answer voicemail 4013 (unavail) and call screening with no-memory
  • Changed the inbound route for the test DID and added “_0XXXXXXXXX” to CID as pattern and as destination ringgroup 4003 containing 1000 and 4013
  • Added an inbound route with the same DID but empty CID and as destination the custom extension 4593

WORKS Calling from a national number with proper CLIP matches the pattern in the first inbound route and ringgroup 4003 starts ringing , upon noanswer the VM menu is in Dutch/NL.

ALMOST WORKS Calling from a hidded number matches the second inbound route (with empty CID field) and goes to custom extension 4593. Now the announcement is played (because of the call screening) in Dutch/NL as expected. Next the follow me members are ringed. When a member answer the menu is played in English/EN???

The freepbx default language is dutch, all dutch sound files (in all formats) are present with the same permissions.

Here’s a snippet from the asterisk log:
2019-09-24 10:11:53] VERBOSE[23941][C-00000136] bridge_channel.c: Channel Local/[email protected];2 joined ‘simple_bridge’ basic-bridge <299be7e0-8fe7-487e-8608-00f1d695f076>
[2019-09-24 10:11:53] VERBOSE[23935][C-00000136] file.c: <Local/[email protected];1> Playing ‘priv-callpending.alaw’ (language ‘en’)
[2019-09-24 10:11:57] VERBOSE[23935][C-00000136] file.c: <Local/[email protected];1> Playing ‘priv-callerintros/anonymous.slin’ (language ‘en’)
[2019-09-24 10:11:58] VERBOSE[23935][C-00000136] file.c: <Local/[email protected];1> Playing ‘screen-callee-options.alaw’ (language ‘en’)
[2019-09-24 10:12:07] VERBOSE[23935][C-00000136] pbx.c: Executing [[email protected]:1] Set(“Local/[email protected];1”, “__MACRO_RESULT=”) in new stack

I’ve searched the log for anything language related but couldn’t find anything usefull apart from that the initial language was Dutch/NL

I searched online and found this language for incoming anonymous sip but didn’t mess with any config files before you told me to do so. Also the problem doesn’t occur when initially answering the anonymous sip call.

When in the asterisk cli and I’ve picked up the call and listen to the 4 options IVR call screening menu (in English) and run show channels, there are 3 active. Two of them named Local/[email protected];[1 and 2] show “Language: en” The other channel is in dutch.

If I add exten => s,n,Set(CHANNEL(language)=nl_NL) as second line to the [macro-dial] section in extensions_additional.conf and do a dialplan reload the messages are again played in Dutch.

Question is how do I set the language correctly?

Again thank you for your time and help.

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.