Now that you’ve learned a bit about expressions and functions, it’s time to put them to use. By using expressions and functions, you can add even more advanced logic to your dialplan. To allow your dialplan to make decisions, you’ll use conditional branching. Let’s take a closer look.
The key to conditional branching is the GotoIf() application. GotoIf() evaluates an expression and sends the
      caller to a specific destination based on whether the expression
      evaluates to true or false.
GotoIf() uses a special syntax, often called
      the conditional syntax:
GotoIf(expression?destination1:destination2)
If the expression evaluates to true,
      the caller is sent to destination1. If the
      expression evaluates to false, the caller is sent to the second
      destination. So, what is true and what is false? An empty string and the
      number 0 evaluate as false. Anything else evaluates
      as true.
The destinations can each be one of the following:
Either of the destinations may be omitted, but not both. If the omitted destination is to be followed, Asterisk simply goes on to the next priority in the current extension.
Let’s use GotoIf() in an example:
exten => 345,1,Set(TEST=1)
   same => n,GotoIf($[${TEST} = 1]?weasels:iguanas)
   same => n(weasels),Playback(weasels-eaten-phonesys)
   same => n,Hangup()
   same => n(iguanas),Playback(office-iguanas)
   same => n,Hangup()You will notice that we have used
          the Hangup()
          application following each use of the Playback() application. This is done so
          that when we jump to the weasels
          label, the call stops before execution gets to the
          office-iguanas sound file. It is becoming
          increasingly common to see extensions broken up into multiple
          components (protected from each other by the Hangup() command), each one a distinct
          sequence of steps executed following a GotoIf().
Typically, when you have this type of layout where you end up wanting to prevent Asterisk from falling through to the next priority after you’ve performed that jump, it’s probably better to jump to separate extensions instead of priority labels. If anything, it makes it a bit more clear when reading the dialplan. We could rewrite the previous bit of dialplan like this:
exten => 345,1,Set(TEST=1)
   same => n,GotoIf($[${TEST} = 1]?weasels,1:iguanas,1) ; now we're going to
                                                        ; extension,priority
exten => weasels,1,Playback(weasels-eaten-phonesys)     ; this is NOT a label.
                                                        ; It is a different extension
   same => n,Hangup()
exten => iguanas,1,Playback(office-iguanas)
   same => n,Hangup()By changing the value assigned to
      TEST in the first line, you should be
      able to have your Asterisk server play a different greeting.
Let’s look at another example of
      conditional branching. This time, we’ll use both Goto() and GotoIf() to count down from 10 and then hang
      up:
exten => 123,1,Set(COUNT=10)
   same => n(start),GotoIf($[${COUNT} > 0]?:goodbye)
   same => n,SayNumber(${COUNT})
   same => n,Set(COUNT=$[${COUNT} - 1])
   same => n,Goto(start)
   same => n(goodbye),Hangup()Let’s analyze this example. In the
      first priority, we set the variable COUNT to 10. Next, we check to see if COUNT is greater than 0. If it is, we move on to the next priority.
      (Don’t forget that if we omit a destination in the GotoIf() application, control goes to the next
      priority.) From there, we speak the number, subtract 1 from COUNT, and go back to priority label start. If COUNT is less than or equal to 0, control goes to priority label goodbye, and the call is hung up.
The classic example of conditional branching is affectionately known as the anti-girlfriend logic. If the caller ID number of the incoming call matches the phone number of the recipient’s ex-girlfriend, Asterisk gives a different message than it ordinarily would to any other caller. While somewhat simple and primitive, it’s a good example for learning about conditional branching within the Asterisk dialplan.
This example uses the CALLERID function, which allows us to retrieve
      the caller ID information on the inbound call. Let’s assume for the sake
      of this example that the victim’s phone number is 888-555-1212:
exten => 123,1,GotoIf($[${CALLERID(num)} = 8885551212]?reject:allow)
   same => n(allow),Dial(DAHDI/4)
   same => n,Hangup()
   same => n(reject),Playback(abandon-all-hope)
   same => n,Hangup()In priority 1, we
      call the GotoIf()
      application. It tells Asterisk to go to priority label reject if the caller ID number matches
      8885551212, and otherwise to go to
      priority label allow (we could have
      simply omitted the label name, causing the GotoIf() to fall through). If the caller ID
      number matches, control of the call goes to priority label reject, which plays back an uninspiring
      message to the undesired caller. Otherwise, the call attempts to dial
      the recipient on channel DAHDI/4.
Another way to use conditional branching in your dialplan
      is with the GotoIfTime() application.
      Whereas GotoIf() evaluates an
      expression to decide what to do, GotoIfTime() looks at the current system time
      and uses that to decide whether or not to follow a different branch in
      the dialplan.
The most obvious use of this application is to give your callers a different greeting before and after normal business hours.
The syntax for the GotoIfTime() application looks like
      this:
GotoIfTime(times,days_of_week,days_of_month,months?label)
In short, GotoIfTime() sends the call to the specified
      label if the current date and time match the
      criteria specified by times,
      days_of_week,
      days_of_month, and
      months. Let’s look at each argument in more
      detail:
times
          This is a list of one or more time ranges, in a
            24-hour format. As an example, 9:00 A.M. through 5:00 P.M. would
            be specified as 09:00-17:00.
            The day starts at 0:00 and ends at 23:59.
It is worth noting that
                times will properly wrap around. So, if you wish to specify
                the times your office is closed, you might write 18:00-9:00 in the
                times parameter, and it will
                perform as expected. Note that this technique works as well
                for the other components of GotoIfTime(). For example, you can
                write sat-sun to specify
                the weekend days.
days_of_week
          This is a list of one or more days of the week. The
            days should be specified as mon, tue, wed, thu, fri, sat, and/or sun. Monday through Friday would be
            expressed as mon-fri. Tuesday
            and Thursday would be expressed as tue&thu.
days_of_month
          This is a list of the numerical days of the month.
            Days are specified by the numbers 1 through 31. The 7th through the 12th would be
            expressed as 7-12, and the 15th
            and 30th of the month would be written as 15&30.
months
          This is a list of one or more months of the year.
            The months should be written as jan-apr for a range, and separated with
            ampersands when wanting to include nonsequential months, such as
            jan&mar&jun. You can
            also combine them like so: jan-apr&jun&oct-dec.
If you wish to match on all possible
      values for any of these arguments, simply put an * in for that argument.
The
      label argument can be any of the following:
Now that we’ve covered the syntax, let’s look at a couple of examples. The following example would match from 9:00 A.M. to 5:59 P.M., on Monday through Friday, on any day of the month, in any month of the year:
exten => s,1,GotoIfTime(09:00-17:59,mon-fri,*,*?open,s,1)
If the caller calls during these
      hours, the call will be sent to the first priority of the s extension in the context named open. If the call is made outside of the
      specified times, it will be sent to the next priority of the current
      extension. This allows you to easily branch on multiple times, as shown
      in the next example (note that you should always put your most specific
      time matches before the least specific ones):
; If it's any hour of the day, on any day of the week, ; during the fourth day of the month, in the month of July, ; we're closed exten => s,1,GotoIfTime(*,*,4,jul?closed,s,1) ; During business hours, send calls to the open context same => n,GotoIfTime(09:00-17:59,mon-fri,*,*?open,s,1) same => n,GotoIfTime(09:00-11:59,sat,*,*?open,s,1) ; Otherwise, we're closed same => n,Goto(closed,s,1)
If you run into the situation where
        you ask the question, “But I specified 17:58 and it’s now 17:59. Why
        is it still doing the same thing?” it should be noted that the
        granularity of the GotoIfTime()
        application is only to a two-minute period. So, if you specify 18:00
        as the ending time of a period, the system will continue to perform
        the same way until 18:01:59.