Introducing TeleYapper: Free Asterisk Message Broadcasting System

There's nothing quite like starting the new year with an application that exposes an ugly bug in Asterisk® 1.2, but that's what yesterday's original article did. So here's a second stab at the article ... and Asterisk ... without reliance on the buggy code. The revised article requires and will work reliably with Asterisk@Home 1.5 or Asterisk@Home 2.2. For those using Asterisk@Home 2.4 or later, use this updated tutorial and software.

It's free software day again at Nerd Vittles, and today we're pleased to (re)introduce the first of several tutorials on TeleYapper, an Asterisk@Home-based telephone broadcasting service for neighborhoods, schools, little leagues, fundraisers, municipal governments, and anyone else that just wants to pester folks with annoying, but free, prerecorded phone calls. It works like this. You create a recorded message using Asterisk. Then you create a list of phone numbers to call in a MySQL database using a tool such as phpMyAdmin which is bundled with Asterisk@Home. Finally, you place a phone call to kick off TeleYapper. The software will dutifully swing into action and call every phone number from any of ten calling categories that you specify when you set up your database of callees. TeleYapper then will deliver the message you've recorded. It's even smart enough to detect answering machines and wait for the announcement to end before playing your message. In short, it works much like call-em-all.com and numerous other telephone broadcasting services with one important difference: TeleYapper is FREE! So, instead of paying 15¢ a call or $35 to $100 a month for a commercial service or spending thousands of dollars for a commercial dialer, now you can do it yourself using TeleYapper and your (also free) Asterisk@Home 1.5 or 2.2 PBX. Of course, it also gives us an opportunity to introduce you to some new Asterisk@Home tips and tricks, not to mention bugs, that should keep you burning the midnight oil (like we did last night) with enhancements and tweaks for the next few weeks.

What's the catch? Well, there are a couple actually. If you have residential VoIP service with unlimited calling, be very careful about using this software without first checking with your provider or at least reading your provider's terms of service. Many prohibit such uses of residential VoIP service, and it's very easy for automated systems to figure out what you're doing since TeleYapper can place literally hundreds of calls per hour in very rapid succession. We plan to throttle the application down to 60 calls per hour, but it still will set off red flags with many VoIP providers. If, on the other hand, you're paying by the call or by the minute, those VoIP providers typically could care less and some will even let you specify your CallerID for such calls. There's nothing quite like using the White House phone number to relay those Little League sports scores to your friends and neighbors. Heh heh!

In case you've never gotten to experience pre-recorded phone calls before (not likely in the U.S. of A!), think of it as podcasting in reverse. It's the old "don't call us, we'll call you" deal. Instead of people pulling content from your site, you push it to theirs ... in this case, their phones. But seriously, there are some legitimate uses for such a tool other than bugging the crap out of your neighbors. Here are a few that come to mind: event reminders, announcement of sports scores or practice times and locations, emergency notifications, medical appointment reminders, inclement weather alerts and schedules (think T-O-R-N-A-D-O!), neighborhood security warnings, schedule changes, and utility outage alerts. In short, such a system is ideal for many constructive purposes in the business world as well as in charitible organizations, schools, athletic programs, and neighborhood associations. But, for most of these purposes, you need the callee's written permission before making any calls. Just don't abuse it, and the feds and your neighbors won't come calling on you. We strongly recommend that you either obtain the written permission of every person you intend to call using this software or consult with an attorney before making any calls because of new Do Not Call legislation enacted in many states as well as the federal Do Not Call List. Our foreign visitors are well advised to take similar precautions. Failure to heed this advice may result in serious civil and criminal penalties including substantial fines imposed on a per call basis. For an excellent summary of current statutes in the United States, visit this site which pretty well documents why you still need either a TeleZapper hardware device or Asterisk's Zapateller software to protect your own phones from unwanted calls.


Creative Commons LicenseLicensing. We are retaining ownership of this software as well as the copyright. It is licensed for use under the terms of the Creative Commons Attribution Non-Commercial license. A Plain English summary is available here. We've done this primarily to do our part to stamp out the telemarketing creeps of the world. Those wishing to use TeleYapper in a commercial environment must first request a license outlining your proposed terms of use. We will promptly respond with a yay or nay. Telemarketers need not apply!

Editor's Note: We'd suggest you stop reading here and move on to Part II which covers everything you'll need to get TeleYapper yapping. You'll also avoid having to do some things twice.

In this updated first installment, we'll put the framework in place to let you actually record messages and begin building your MySQL database of callees to support TeleYapper calls. We'll also point out some of the differences between AAH 1.5 and AAH 2.2 for those of you contemplating a career in Asterisk programming. Part I also will give you something to play with until we tie everything together and get TeleYapper dialing away in Part II. And someday, if we get a burst of energy, we may actually build a little database application like AsteriDex to help you add and edit entries in your TeleYapper database instead of having to rely upon phpMyAdmin. But, first things first.

Adding TeleYapper to Your Dialplan. We need a simple facility for building voice messages for the TeleYapper project and for managing the call process. Using some of Asterisk's built-in tools and voice prompts, we've created something that's easy to use and simple to maintain. While the voice prompts are not quite perfect for this application, they're close enough for government work. Using a web browser, open the Asterisk Management Portal (AMP) by entering the IP address of your Asterisk machine. To add TeleYapper to your dialplan, just cut-and-paste the following code into the [from-internal-custom] context near the top of extensions_custom.conf: AMP->Maintenance->Config Edit->extensions_custom.conf. Be sure to change the 1234 password below to something secure for your system since this will be used to gain access to your TeleYapper system!

exten => 674,1,Answer ; dial MSG on any extension to manage your TeleYapper system
exten => 674,2,Wait(1)
exten => 674,3,Authenticate(1234)
exten => 674,4,Goto(yapper,s,1)

If you're a long-time reader of Nerd Vittles and you're using either our Stealth AutoAttendant or some other AutoAttendant, then you already know why you need to be careful about putting extensions like 6-7-4 in your extensions_custom.conf file because anyone can call you, dial 6-7-4 while your AutoAttendant is playing, and insert their own obscene message into your TeleYapper system. The solution is adding your own secure password in line 3 above rather than using the default 1234. Another precaution you should always perform is to first play your outgoing TeleYapper message to yourself to make certain it says what you think it should before you kick off a dialing spree to a thousand of your closest friends or business associates.


Adding the TeleYapper IVR. Now that we have a way to call into the TeleYapper system, we need something for it to do once we connect. So you'll need to cut-and-paste some code to the bottom of the extensions_custom.conf file while you still have the file open. Just scroll down to the bottom of the file. The actual code you need to paste depends upon the version of Asterisk@Home you're running. We initially thought we could demonstrate how to use Asterisk's built-in MySQL tools for some of the IVR interaction, but there appears to be a bug in Asterisk 1.2 upon which AAH 2.2 relies. Every query yields a zero record set when a search is implemented using our original code so that obviously won't be of much use with AAH 2.2. Another issue that those using AAH 1.5 should be aware of is this. Asterisk has no built in MySQL function to return a count of records matching a given search criteria. The only way to get the count is to loop through all the matching records and count them as you go. This works fine with a handful of records, but I have no idea how it would work with 500 or more records. Using a PHP/AGI script on the other hand lets us decipher the count of matching records for a search in one line of code. Bottom line: We're providing the "old" internal way to use MySQL because no one ever has correctly documented how it works, and it does work with Asterisk@Home 1.5. Then we'll provide the "new" PHP/AGI script version for use with Asterisk@Home 1.5. And finally we'll provide the "new" PHP/AGI script version for use with Asterisk@Home 2.2. Why two new versions? Well, the Asterisk developers changed the way variables are stored in Asterisk 1.09 (included in AAH 1.5) and Asterisk 1.2.1 (included in AAH 2.2). Dumb move! It's one thing to add new commands to a programming language (which Asterisk is). It's quite another to eliminate existing commands (which breaks functioning code) or to change the way variables are initialized or set (which yields different results when existing code is executed). End of rant.

Option #1 for Asterisk@Home 1.5 Only. For those that want to experiment with using Asterisk's internal MySQL commands, here is the original TeleYapper code for you to cut-and-paste to the bottom of extensions_custom.conf. This code only works with Asterisk@Home 1.5, not Asterisk@Home 2.2:

[yapper]
exten => s,1,DigitTimeout(7)
exten => s,2,ResponseTimeout(10)
exten => s,3,Background(T-to-hear-cur-ancmnt)
exten => s,4,Background(press-1)
exten => s,5,Background(to-rerecord-yr-message)
exten => s,6,Background(press-2)
exten => s,7,Background(to-place-outgoing-call)
exten => s,8,Background(press-3)
exten => s,9,Background(to-hear-menu-again)
exten => s,10,Background(press-4)
exten => s,11,Background(to-hang-up)
exten => s,12,Background(press-5)
exten => 1,1,Playback(custom/broadcast)
exten => 1,2,Wait(2)
exten => 1,3,Goto(s,3)
exten => 2,1,Goto(yapper2,s,1)
exten => 3,1,Goto(yapper-options,s,1)
exten => 4,1,Goto(s,3)
exten => 5,1,Playback(goodbye)
exten => 5,2,Goto(h,1)
exten => t,1,Goto(s,3)
exten => i,1,Goto(s,3)
exten => o,1,Goto(s,3)
exten => h,1,Hangup

[yapper2]
exten => s,1,Playback(after-the-tone)
exten => s,2,Playback(say-temp-msg-prs-pound)
exten => s,3,Wait(2)
exten => s,4,Record(custom/broadcast:gsm)
exten => s,5,Wait(2)
exten => s,6,Playback(custom/broadcast)
exten => s,7,Wait(2)
exten => s,8,Playback(your-msg-has-been-saved)
exten => s,9,Wait(2)
exten => s,10,Goto(yapper,s,1)

[yapper3]
exten => s,1,SetGlobalVar(COUNTER=0)
exten => s,2,MYSQL(Connect connid localhost root passw0rd teleyapper)
exten => s,3,MYSQL(Query resultid ${connid} SELECT `*` FROM `callees` WHERE `group` = ${GROUP})
exten => s,4,MYSQL(Fetch foundRow ${resultid} var1 var2 var3 var4 var5 var6) ; fetch row
exten => s,5,GotoIf($["${foundRow}" = "1"]?6:9) ; leave loop if no row found
exten => s,6,NoOp(${var2}: ${var3})
exten => s,7,SetGlobalVar(COUNTER=$[${COUNTER} + 1])
exten => s,8,Goto(4) ; continue loop if row found
exten => s,9,MYSQL(Clear ${resultid})
exten => s,10,MYSQL(Disconnect ${connid})
exten => s,11,GotoIf($["${COUNTER}" = "0"]?9,1)
exten => s,12,Playback(the-num-i-have-is)
exten => s,13,SayNumber(${COUNTER})
exten => s,14,Playback(vm-messages)
exten => s,15,Wait(1)
exten => s,16,DigitTimeout(7)
exten => s,17,ResponseTimeout(10)
exten => s,18,Background(to-call-this-number)
exten => s,19,Background(press-1)
exten => s,20,Background(to-hang-up)
exten => s,21,Background(press-2)
exten => 1,1,MYSQL(Disconnect ${connid})
exten => 1,2,Goto(yapper-gen,s,1)
exten => 2,1,Playback(goodbye)
exten => 2,2,MYSQL(Disconnect ${connid})
exten => 2,3,Hangup
exten => 9,1,Playback(dir-nomatch)
exten => 9,2,Wait(1)
exten => 9,3,MYSQL(Disconnect ${connid})
exten => 9,4,Goto(yapper,s,1)
exten => t,1,Playback(goodbye)
exten => t,2,MYSQL(Disconnect ${connid})
exten => t,3,Hangup
exten => i,1,Playback(goodbye)
exten => i,2,MYSQL(Disconnect ${connid})
exten => i,3,Hangup
exten => s,103,MYSQL(Disconnect ${connid})
exten => s,104,Hangup
exten => h,1,MYSQL(Disconnect ${connid})

[yapper-options]
exten => s,1,Wait(1)
exten => s,2,Playback(you-have-these-options)
exten => s,3,Playback(digits/0)
exten => s,4,Playback(through)
exten => s,5,Playback(digits/9)
exten => s,6,Playback(press-star-cancel)
exten => s,7,SetGlobalVar(GROUP=0)
exten => s,8,Read(GROUP,vm-enter-num-to-call,1)
exten => s,9,NoOp(${GROUP})
exten => s,10,GotoIf($["foo${GROUP}" = "foo"]?s,78)
exten => s,11,GotoIf($["foo${GROUP}" = "foo*"]?s,88)
exten => s,12,GotoIf($["foo${GROUP}" = "foo#"]?s,98)
exten => s,13,Goto(yapper3,s,1)
exten => s,78,Playback(connection-timed-out)
exten => s,79,Wait(1)
exten => s,80,Goto(yapper,s,1)
exten => s,88,Playback(cancelled)
exten => s,89,Wait(1)
exten => s,90,Goto(yapper,s,1)
exten => s,98,Playback(option-not-implemented)
exten => s,99,Goto(yapper,s,1)

[yapper-gen]
exten => s,1,Playback(speed-dial)
exten => s,2,Playback(activated)
exten => s,3,Wait(1)
exten => s,4,Playback(goodbye)
exten => s,5,Hangup

Option #2 for Asterisk@Home 1.5 Only. For those that want to use the new PHP/AGI scripting solution, here is the new TeleYapper code for you to cut-and-paste to the bottom of extensions_custom.conf. This code only works with Asterisk@Home 1.5, not Asterisk@Home 2.2:

[yapper]
exten => s,1,DigitTimeout(7)
exten => s,2,ResponseTimeout(10)
exten => s,3,Background(T-to-hear-cur-ancmnt)
exten => s,4,Background(press-1)
exten => s,5,Background(to-rerecord-yr-message)
exten => s,6,Background(press-2)
exten => s,7,Background(to-place-outgoing-call)
exten => s,8,Background(press-3)
exten => s,9,Background(to-hear-menu-again)
exten => s,10,Background(press-4)
exten => s,11,Background(to-hang-up)
exten => s,12,Background(press-5)
exten => 1,1,Playback(custom/broadcast)
exten => 1,2,Wait(2)
exten => 1,3,Goto(s,3)
exten => 2,1,Goto(yapper2,s,1)
exten => 3,1,Goto(yapper-options,s,1)
exten => 4,1,Goto(s,3)
exten => 5,1,Playback(goodbye)
exten => 5,2,Goto(h,1)
exten => t,1,Goto(s,3)
exten => i,1,Goto(s,3)
exten => o,1,Goto(s,3)
exten => h,1,Hangup

[yapper2]
exten => s,1,Playback(after-the-tone)
exten => s,2,Playback(say-temp-msg-prs-pound)
exten => s,3,Wait(2)
exten => s,4,Record(custom/broadcast:gsm)
exten => s,5,Wait(2)
exten => s,6,Playback(custom/broadcast)
exten => s,7,Wait(2)
exten => s,8,Playback(your-msg-has-been-saved)
exten => s,9,Wait(2)
exten => s,10,Goto(yapper,s,1)

[yapper3]
exten => s,1,AGI(checkgroup.php|${GROUP})
exten => s,2,NoOp(tmp variable: ${tmp})
exten => s,3,GotoIf($[${tmp} = 0]?9,1)
exten => s,4,SetGlobalVar(COUNTER=${tmp})
exten => s,5,Playback(the-num-i-have-is)
exten => s,6,SayNumber(${COUNTER})
exten => s,7,Playback(vm-messages)
exten => s,8,Wait(1)
exten => s,9,DigitTimeout(7)
exten => s,10,ResponseTimeout(10)
exten => s,11,Background(to-call-this-number)
exten => s,12,Background(press-1)
exten => s,13,Background(to-hang-up)
exten => s,14,Background(press-2)
exten => 1,1,Goto(yapper-gen,s,1)
exten => 2,1,Playback(goodbye)
exten => 2,2,Hangup
exten => 9,1,Playback(dir-nomatch)
exten => 9,2,Wait(1)
exten => 9,3,Goto(yapper,s,1)
exten => t,1,Playback(goodbye)
exten => t,2,Hangup
exten => i,1,Playback(goodbye)
exten => i,2,Hangup
exten => h,1,Hangup

[yapper-options]
exten => s,1,Wait(1)
exten => s,2,Playback(you-have-these-options)
exten => s,3,Playback(digits/0)
exten => s,4,Playback(through)
exten => s,5,Playback(digits/9)
exten => s,6,Playback(press-star-cancel)
exten => s,7,SetGlobalVar(GROUP=0)
exten => s,8,Read(GROUP,vm-enter-num-to-call,1)
exten => s,9,NoOp(${GROUP})
exten => s,10,GotoIf($["foo${GROUP}" = "foo"]?s,78)
exten => s,11,GotoIf($["foo${GROUP}" = "foo*"]?s,88)
exten => s,12,GotoIf($["foo${GROUP}" = "foo#"]?s,98)
exten => s,13,Goto(yapper3,s,1)
exten => s,78,Playback(connection-timed-out)
exten => s,79,Wait(1)
exten => s,80,Goto(yapper,s,1)
exten => s,88,Playback(cancelled)
exten => s,89,Wait(1)
exten => s,90,Goto(yapper,s,1)
exten => s,98,Playback(option-not-implemented)
exten => s,99,Goto(yapper,s,1)

[yapper-gen]
exten => s,1,Playback(speed-dial)
exten => s,2,Playback(activated)
exten => s,3,Wait(1)
exten => s,4,Playback(goodbye)
exten => s,5,Hangup

Option #3 for Asterisk@Home 2.2 Only. As indicated, only the new PHP/AGI scripting solution works with Asterisk@Home 2.2. Here is the new TeleYapper code for you to cut-and-paste to the bottom of extensions_custom.conf. Because of the way global variables are set, this code only works with Asterisk@Home 2.2, not Asterisk@Home 1.5:

[yapper]
exten => s,1,DigitTimeout(7)
exten => s,2,ResponseTimeout(10)
exten => s,3,Background(T-to-hear-cur-ancmnt)
exten => s,4,Background(press-1)
exten => s,5,Background(to-rerecord-yr-message)
exten => s,6,Background(press-2)
exten => s,7,Background(to-place-outgoing-call)
exten => s,8,Background(press-3)
exten => s,9,Background(to-hear-menu-again)
exten => s,10,Background(press-4)
exten => s,11,Background(to-hang-up)
exten => s,12,Background(press-5)
exten => 1,1,Playback(custom/broadcast)
exten => 1,2,Wait(2)
exten => 1,3,Goto(s,3)
exten => 2,1,Goto(yapper2,s,1)
exten => 3,1,Goto(yapper-options,s,1)
exten => 4,1,Goto(s,3)
exten => 5,1,Playback(goodbye)
exten => 5,2,Goto(h,1)
exten => t,1,Goto(s,3)
exten => i,1,Goto(s,3)
exten => o,1,Goto(s,3)
exten => h,1,Hangup

[yapper2]
exten => s,1,Playback(after-the-tone)
exten => s,2,Playback(say-temp-msg-prs-pound)
exten => s,3,Wait(2)
exten => s,4,Record(custom/broadcast:gsm)
exten => s,5,Wait(2)
exten => s,6,Playback(custom/broadcast)
exten => s,7,Wait(2)
exten => s,8,Playback(your-msg-has-been-saved)
exten => s,9,Wait(2)
exten => s,10,Goto(yapper,s,1)

[yapper3]
exten => s,1,AGI(checkgroup.php|${GROUP})
exten => s,2,NoOp(tmp variable: ${tmp})
exten => s,3,GotoIf($[${tmp} = 0]?9,1)
exten => s,4,Set(COUNTER=${tmp}|g)
exten => s,5,Playback(the-num-i-have-is)
exten => s,6,SayNumber(${COUNTER})
exten => s,7,Playback(vm-messages)
exten => s,8,Wait(1)
exten => s,9,DigitTimeout(7)
exten => s,10,ResponseTimeout(10)
exten => s,11,Background(to-call-this-number)
exten => s,12,Background(press-1)
exten => s,13,Background(to-hang-up)
exten => s,14,Background(press-2)
exten => 1,1,Goto(yapper-gen,s,1)
exten => 2,1,Playback(goodbye)
exten => 2,2,Hangup
exten => 9,1,Playback(dir-nomatch)
exten => 9,2,Wait(1)
exten => 9,3,Goto(yapper,s,1)
exten => t,1,Playback(goodbye)
exten => t,2,Hangup
exten => i,1,Playback(goodbye)
exten => i,2,Hangup
exten => h,1,Hangup

[yapper-options]
exten => s,1,Wait(1)
exten => s,2,Playback(you-have-these-options)
exten => s,3,Playback(digits/0)
exten => s,4,Playback(through)
exten => s,5,Playback(digits/9)
exten => s,6,Playback(press-star-cancel)
exten => s,7,Read(tmp,vm-enter-num-to-call,1)
exten => s,8,Set(GROUP=${tmp}|g)
exten => s,9,NoOp(${GROUP})
exten => s,10,GotoIf($["foo${GROUP}" = "foo"]?s,78)
exten => s,11,GotoIf($["foo${GROUP}" = "foo*"]?s,88)
exten => s,12,GotoIf($["foo${GROUP}" = "foo#"]?s,98)
exten => s,13,Goto(yapper3,s,1)
exten => s,78,Playback(connection-timed-out)
exten => s,79,Wait(1)
exten => s,80,Goto(yapper,s,1)
exten => s,88,Playback(cancelled)
exten => s,89,Wait(1)
exten => s,90,Goto(yapper,s,1)
exten => s,98,Playback(option-not-implemented)
exten => s,99,Goto(yapper,s,1)

[yapper-gen]
exten => s,1,Playback(speed-dial)
exten => s,2,Playback(activated)
exten => s,3,Wait(1)
exten => s,4,Playback(goodbye)
exten => s,5,Hangup

Saving Your Additions. When you've finished pasting one of the three chunks of code above, click the Update button at the bottom of the editing window. Now reload your Asterisk configs: AMP->Setup->Incoming Calls->Submit Changes and then click the Red Bar. Don't be dialing 674 just yet. We haven't installed your database to support the application.

Installing the CheckGroup PHP/AGI Script. If you're running Asterisk@Home 1.5 with the Option #1 code above, you can skip this step. For those using one of the new PHP/AGI script solutions (Option #2 or Option #3 above), you'll need to install the checkgroup.php script in your /var/lib/asterisk/agi-bin directory and change file ownership and permissions on the file. Log in to your Asterisk server as root, and then execute the following commands:

cd /var/lib/asterisk/agi-bin
wget http://nerdvittles.com/checkgroup.zip
unzip checkgroup.zip
rm checkgroup.zip
chmod 775 checkgroup.php
chown asterisk:asterisk checkgroup.php

This script includes a debug log. The default settings are to create a new log file (/var/log/asterisk/telecheck.txt) each time the script is executed. This doesn't take up much room and is always there for you to read if something comes unglued: cat /var/log/asterisk/telecheck.txt. There are some other options. You can turn off the log file entirely ($debug=0). You can choose not to erase the previous log file each time the script is run ($newlogeachdebug=0) in which case the file continues to grow until your hard disk fills up. And you can have the log file emailed to you each time the script is executed ($emaildebuglog=1) by adding your email address ($email=youremailaddress). The last option obviously assumes you have followed our previous tutorials and gotten outbound email working reliably on your system. The functions are controlled by the following lines at the top of the checkgroup.php file. 1 means yes, and 0 means no. Just edit the file carefully: nano -w checkgroup.php. And save your changes when you're finished: Ctrl-X, Y, then press Enter.

$debug = 1;
$newlogeachdebug = 1;
$emaildebuglog = 0;
$email = "yourname@yourdomain" ;


TeleYapper in a Nutshell. Before we get to the database, let's briefly cover how the above code works. When you dial 674, the TeleYapper system will answer and prompt you for your password. Once you correctly enter the password, an interactive voice response (IVR) system will swing into action and give you several choices. That's what the [yapper] context handles. Pressing 1 lets you listen to your prerecorded TeleYapper message (if you have one). You don't yet so don't press 1. Pressing 2 lets you record a new TeleYapper message. This is handled by the [yapper2] context. Do this first and record something ... anything. You can rerecord a new message at any time by choosing option 2 again. Pressing 3 lets you kick off a TeleYapper dialing spree. It's handled by the [yapper3] context. Don't do this until we add your new database below, or you'll get smoke out of your system. For the technically inclined, [yapper3] in the Option #1 version actually performs some pretty hairy MySQL database tricks that won't work unless you're using Asterisk@Home 1.5. Pure Asterisk needs major patches to jump through the same hoops! (ATTN: Code Junkies -- Assuming you're running AAH 1.5, now you know how to query any MySQL database from inside your Asterisk dialplan!) Pressing 4 repeats the IVR menu choices. And pressing 5 disconnects you from the system.

If you choose option 3 to initiate a TeleYapper calling session, the system will first prompt you for a group option number to use. This is managed by the [yapper-options] context. Simply stated, when you build your database of callees for TeleYapper, you can specify a one-digit group number for each entry in the file. Then, when you begin a calling session, you can narrow down the calling group by telling TeleYapper which group of callees to call. If you want a callee to be in more than one group, you simply enter that callee into the database multiple times with different group numbers. If you want everyone in the same group, then enter 0 for every person in your database.

Once you specify the group number during your TeleYapper session, the system will actually look up and report back how many messages will be delivered to the callee group you've chosen. Allison will say something like this assuming there were 146 calls to be placed: "The number I have is one hundred and forty six messages." This will give you the count of qualifying records in the database and the option of proceeding with the calls or cancelling the transaction. In short, it's a safety mechanism to make sure you don't actually set off a calling spree to Group 7 with 500 callees when you meant to choose Group 8 with only 5. You'll still need to know what types of callees are in each group of callees that you create. TeleYapper doesn't quite do everything. Once we add our new database to your system and plug in a couple of entries, you'll have all week to experiment with the IVR system before TeleYapper actually begins making calls. So experiment away until you're comfortable with the menu system. As noted previously, we've endeavored to build this entire application using the voice prompts that are delivered with Asterisk@Home 1.5 or 2.x so they're not quite perfect. But they work reasonably well once you understand how the pieces fit together. You're supposed to be nodding in agreement now. If not, reread the last three paragraphs after you get another cup of coffee.


Creating the TeleYapper Database. Now we're ready to create the MySQL database to support TeleYapper. The easiest way to do this is using the Asterisk Management Portal (AMP) to gain access to phpMyAdmin: AMP->Maintenance->phpMyAdmin. When phpMyAdmin loads, click on the SQL icon in the left column. When the SQL window appears, clear the existing SQL query and then cut-and-paste the following SQL code into that box and then click the Go button. When the import completes, click the teleyapper.callees table entry in the left column to open the file. Then click the Insert tab at the top of the right column to add entries to the table. You only need to add information for the name, phonenum, and group fields in the corresponding values column. The id, lastokcall, and lastcall fields should be left as is. The id field gets calculated automatically. The lastokcall will record the time and date of the last successful call using TeleYapper. And the lastcall field identifies what happened during the last call to this person, e.g. ok means the call was completed successfully, no answer means no one answered the call, or answering machine means an answering machine took the call.

You can add up to two records at a time and, by clicking the Insert Another New Row button, you will be returned to this data entry screen after you save your entries by clicking the Go button. The name field allows you to quickly review entries you've made. It won't be used when making TeleYapper calls. The phonenum field is the important one. This is the exact dial string required to place a call on your Asterisk system to this callee using whatever VoIP or PSTN outbound trunk you plan to use with TeleYapper. For example, if your preferred provider requires 11-digit phone numbers with a 1, area code, and number, then that's the way the numbers should be entered into the TeleYapper database. The group field has already been discussed. Just enter a number between 0 and 9 to identify the group with whom this individual should be associated. Finally, after adding records to the table, you can click the Browse tab to review your entries. And, while Browsing, you can click the Pencil icon beside any record entry to edit it. Clicking the red X icon beside a record entry deletes the record. If, for some reason, you wish to delete ALL the records in the file, click the Empty tab at the top of the right column. Under no circumstances should you click on the Drop tab as this removes not only the table's contents but also the table structure itself. In short, you'd have to import the database table again.


Taking TeleYapper for a Spin. We're ready to try out the TeleYapper IVR. First, start up the Asterisk Command Line Interface (CLI) by typing asterisk -r from the command prompt on your system after you've logged in as root. Then issue the following command: set verbose 10. The CLI now will tell you every phone number that would have been called during your TeleYapper session if you review the CLI history after performing the following steps.

Dial 6-7-4 from an extension on your system and enter your password. Choose option 2 from the IVR menu and record an outgoing message to be delivered to your callees. Once you've recorded a message, you can play it back by choosing IVR option 1. Assuming you've added your callees in group 0, choose IVR option 3 and enter 0 for the calling group. The system should report how many messages will be delivered to this group. Select 1 to simulate placing calls to this group. Then check the CLI and make sure the phone numbers for each member of the group correctly appear in the CLI history. If everything went according to plan, you're ready to move on to TeleYapper, Part II.

Coming Attractions: TeleYapper, Part II. In our next chapter (available here), we'll actually wire the pieces together so that you can make a phone call from anywhere and start up a TeleYapper calling session. We'll be using some more new Asterisk tricks to make all of this work. We obviously don't want to stay on the line while TeleYapper makes all the outbound phone calls so we'll be using Asterisk's hangup functionality to execute a PHP script which does the heavy lifting. We'll start by passing the group number variable and the count of callees to the PHP script. For all you code warriors, we'll document the steps necessary to get a PHP session initialized to talk with Asterisk. And we'll show you how to read in the variables passed from the Asterisk IVR session. Then we'll do some standard MySQL processing to look up the correct records to obtain the phone numbers to call. Then we'll build the scripts to actually place the phone calls and interact with someone or some answering machine at the other end of the line. And finally we'll introduce a clever trick to let you schedule and place all of the outbound calls in the background ... after your PHP session and initiating phone call have ended. What is it? Well, it's none other than Andy Wysocki's WakeUp Calls engine which is already built into Asterisk@Home. By sending a five-line script to the wakeup call directory, we can kick off a phone call to anyone at any time we specify. And then leave it to Asterisk to sequentially place the calls after we've headed out to lunch. Pretty neat!

Want More Projects? For a complete catalog of all our previous Asterisk projects, click here. For the most recent articles including those you missed over the Christmas and New Year's holidays, click here and just scroll down the page.

From Our Legal Department, moi: The TeleYapper product name (our feeble attempt at humor through parody) has absolutely no affiliation with TeleZapper, the terrific hardware product designed to keep telemarketers from bugging the hell out of you while you're eating your dinner. We confess that our sense of humor got the better of us in coming up with the name for this non-commerical (aka "free") utility designed primarily as an educational vehicle to assist the Asterisk community in recognizing the almost limitless potential of AGI and PHP programming. Our parody seeks to amuse, not to confuse. Our telephony software Yaps. Their telephony hardware Zaps. Other than a telephone line, there is no product similarity as the two conjoined words make clear. And, yes, that is the whole point! The products are opposites, not identical nor even similar. One letter makes all the difference in Night and Light. So it is with Yapper and Zapper. Brand confusion in trademark law arises from synonyms, not antonyms. It is systems like what we're writing about today that TeleZapper is designed to protect against. And it does that very well. In fact, we use TeleZapper hardware in our own home and have for many years. The only problem, of course, is when that tornado comes rolling down the neighbor's street, it would have been nice to get that automated phone call from TeleYapper at the neighborhood headquarters. But, who cares, right? It's only your house. Class dismissed.

Who Is This Guy? Ward Mundy, the author of this Asterisk@Home series of articles, is a retired attorney who spent more than 30 years providing legal and technology assistance to the federal courts in the United States. Today he serves as a principal in Ward Mundy & Associates, a technology consulting firm in Atlanta, Georgia.

Be Sociable, Share!

16 Responses to “Introducing TeleYapper: Free Asterisk Message Broadcasting System”

  1. Rob says:

    I gave yapper a shot. It couldn’t find my DB entries.

    OK, what I did wrong, running AAH 2.2

    [WM: Not a lotta detail there, Rob. Is your database installed? Does the group number in your database entries match the group number you’re choosing when you access the IVR? Are there typos in your code? Did you cut-and-paste everything correctly? What kind of errors does the CLI report? Try again.]

  2. Dov says:

    Can I translate this in portuguese and put in my website?

    http://familiabigio.locaweb.com.br/Asterisk

    [WM: With attribution and a link, we’d be happy for you to translate the TeleYapper article into Portuguese for posting on your site. Hold off a couple days until we get the issues in the other comments resolved.]

  3. Jim says:

    I’m having the same problem as Rob. I followed it to the letter and when i do a 3 to send and then choose group 0, it tells me that there was no match. Love your site… been referring to it for a couple weeks now. Each time there’s a new article, I’m re-amazed at how cool this stuff is. Keep up the great work!
    Jim

    [WM: Yep. There’s a problem with Asterisk@Home 2.2. The MySQL query gets ignored. The developers also have changed the way you set variables, but that’s easy to fix. Isn’t life fun! Hopefully we’ll have a work-around for both issues shortly. The usual apologies to our early adopters! p.s. We’re still running Asterisk@Home 1.5 for things that matter which is why this slipped through the cracks … not to mention an (over)abundance of holiday cheer. Cheers!]

  4. Rob says:

    Ward,

    Installed the DB, right group number and everything. The key CLI is below:

    == Setting global variable ‘GROUP’ to ‘0’
    — Executing Read(“SIP/203-7d8c”, “GROUP|vm-enter-num-to-call|1″) in new stack
    — Accepting a maximum of 1 digits.
    — Playing ‘vm-enter-num-to-call’ (language ‘en’)
    — User entered ‘0’
    — Executing NoOp(“SIP/203-7d8c”, “0”) in new stack
    — Executing GotoIf(“SIP/203-7d8c”, “0?s|78″) in new stack
    — Executing GotoIf(“SIP/203-7d8c”, “0?s|88″) in new stack
    — Executing GotoIf(“SIP/203-7d8c”, “0?s|98″) in new stack
    — Executing Goto(“SIP/203-7d8c”, “yapper3|s|1″) in new stack
    — Goto (yapper3,s,1)
    — Executing SetGlobalVar(“SIP/203-7d8c”, “COUNTER=0″) in new stack
    == Setting global variable ‘COUNTER’ to ‘0’
    — Executing MYSQL(“SIP/203-7d8c”, “Connect connid localhost root passw0rd teleyapper”) in new stack
    — Executing MYSQL(“SIP/203-7d8c”, “Query resultid 1 SELECT `*` FROM `callees` WHERE `group` = 0″) in new stack
    — Executing MYSQL(“SIP/203-7d8c”, “Fetch foundRow var1 var2 var3 var4 var5 var6″) in new stack
    — Executing GotoIf(“SIP/203-7d8c”, “0?6:9″) in new stack
    — Goto (yapper3,s,9)
    — Executing MYSQL(“SIP/203-7d8c”, “Clear “) in new stack
    — Executing MYSQL(“SIP/203-7d8c”, “Disconnect 1″) in new stack
    — Executing GotoIf(“SIP/203-7d8c”, “1?9|1″) in new stack
    — Goto (yapper3,9,1)
    — Executing Playback(“SIP/203-7d8c”, “dir-nomatch”) in new stack
    — Playing ‘dir-nomatch’ (language ‘en’)
    — Executing Wait(“SIP/203-7d8c”, “1”) in new stack
    — Executing MYSQL(“SIP/203-7d8c”, “Disconnect 1″) in new stack
    — Executing Goto(“SIP/203-7d8c”, “yapper|s|1″) in new stack
    — Goto (yapper,s,1)
    — Executing DigitTimeout(“SIP/203-7d8c”, “7”) in new stack
    — Set Digit Timeout to 7
    — Executing ResponseTimeout(“SIP/203-7d8c”, “10”) in new stack
    — Set Response Timeout to 10
    — Executing BackGround(“SIP/203-7d8c”, “T-to-hear-cur-ancmnt”) in new stack
    — Playing ‘T-to-hear-cur-ancmnt’ (language ‘en’)
    == Spawn extension (yapper, s, 3) exited non-zero on ‘SIP/203-7d8c’
    — Executing Hangup(“SIP/203-7d8c”, “”) in new stack
    == Spawn extension (yapper, h, 1) exited non-zero on ‘SIP/203-7d8c’

    [WM: Thanks. I’ve now loaded it on an AAH 2.2 machine as well. There are three problem areas with 2.2 actually. I bolded them above. The variables don’t get set correctly. In other words, whatever you enter as the group number gets read as a zero. And whatever search is executed gets a 0 result returned. I can fix the global variable issue, but the MySQL search seems to be a bug in Asterisk 1.2.1. So my plan on that one is to drop out of Asterisk to an AGI/PHP script to do MySQL duties. Then we’ll return the result. We were going to have to do this anyway in Part II. I just thought it would be informative to show everyone how the built-in MySQL stuff works. Unfortunately, it doesn’t … at least in Asterisk 1.2.1 which is now part of AAH 2.2. Check back. We’ll have something working soon.]

  5. Rob says:

    I hate to send two messages but I wanted to expand my situation. The SQL code worked and built a DB with 6 phone numbers, no problem. I gave them all group “0” and when I tried yapper, I got the CLI I sent you. It seems to have not seen the DB or not perceive the entries.

    BTW, the site is the Asterisk end of the world! Keep it gouing!

    Rob

  6. Rob says:

    One thing I thought of, what is the “passw0rd” to in the SQL call, perhaps I’ve changed that PW?

    [WM: I don’t think that’s the problem. I didn’t change mine, and it still fails.]

  7. Tom Lynn says:

    I’d been looking forward to the article I thought you’d promised on emulating key system functionality. Did I misread? Or am I confusing yours with another blog?

    [WM: Tom, We’ll get to the key system emulation soon. You’ve come to the right place. The order of the articles is a bit like throwing darts at the dart board unfortunately. If you need solutions quicker, that’s what consultants are for. :-)]

  8. rick says:

    Thoroughly enjoy all your articles. My youth sports group has about 550 people that we need to communicate urgent info about schedule changes, emergency meetings, etc. Looks like the data entry capabilities of adding numbers to the database are strictly manual. Is there any way to import from a standard file format?

    Thanks and keep up the very insightful series on using Asterisk

    [WM: phpMyAdmin has some import capabilities. Click on the table. Then click the Structure tab. At the bottom of the screen is an option to import data from a text file with a number of options. You’ll have to experiment to get it working, but it does work. Files with quotes delimiting each field or comma-separated fields are probably the easiest to import. Don’t get discouraged if you get a mess on the first few attempts. Just click the Empty tab to clear out the database table and try again. Good luck.]

  9. Rob says:

    I did not get all of the numbers listed in the CLI though it did correctly tell me how many numbers there were. Should I worry, or is all well?

    [WM: What does the log show? If you’re using the external version, the number listing is now in the log, not in the CLI. Both the count and the number listing should match in the log.]

  10. Wiley says:

    I have option #2 for AAH 1.5 installed. The script seems to work but never dials anything. I get to the end of the script, it gives teh correct count of target calls (2), then says speed dial activated. After that, nothing happens. I entered my phone number as 1234567890 with no formatting. Is that the problem?

    [WM: We haven’t gotten to the dialing part. Patience, patience.]

  11. Justin says:

    Any luck getting the mysql part figured out. I get the same thing as the guy above except I’m using 2.2

    [WM: The project was presented in parts. Part I didn’t dial. Part II does and now is available here.]

  12. su says:

    please ask:there is no /custom/broadcast in my asterisk sounds directory,where can i find it ??(i dont use asterisk@home,just asterisk on my fedora system) ,i just wanna that sounds file? where to find it .thanks

    [WM: Make sure you have a custom directory in /var/lib/asterisk/sounds. If not, mkdir /var/lib/asterisk/sounds/custom. Then the broadcast.gsm file will be generated and stored properly when you record the sound file for your broadcast.]

  13. Brian says:

    So this is great, but I need something that will then pass the caller to the Call Center Agent not just leave or play a message. Any suggestions?

  14. Pat says:

    Is it possible to set up a second extension say 675 and have 2 call list going at once?

  15. Jonathan Colby says:

    Ward, great app, and using for a while. Quick question. The system will not leave a message on an answering machine, or on an internal vm box on the same system it is on. The msg I am getting in the callees table is “ANSMACH” or “Replaye”, with no left message. Can I configure it to leave a message on an answering machine, or an internal extension that does not pick up, and how? Thanks for a great app!

    [WM: There’s no such limitation in the software. Sounds like your voicemail system is hanging up prematurely perhaps because the recorded message isn’t loud enough.]

  16. Stefan says:

    Hey great work! Very useful Asterisk application.
    My company is looking for something very similer to this, but of course with custom additional functionality.
    Do you work on commercial projects? Please, contact me on my email (few times, I got a nasty anti-spam filter).

    All the best ahead.

    [WM: Once in a while, we are tempted to actually work for money. But, as my wife would tell you, “not often.”]

Ringbinder theme by Themocracy