Asterisk GotoIf - примеры, операторы, выражения и RegExp

Использование команды GotoIf и примеры использования операторов и регулярных выражений в условиях.

Обзор

Переход по условию на другой контекст или расширение в текущем контексте.

Описание

Приложение GotoIf устанавливает текущий контекст, расширение и приоритет по результатам сравнения заданного условия. И продолжает после этого выполнение диалплана в указанном контексте, расширении и приоритете. Метки указывающие на контекст имеют такой же синтаксис как и в приложении GoTo. Т.е. вы можете указать полный путь

  • context,extension,priority

или пропустить какой-то из параметров, например:

  • extension,priority - выполнение диалплана будет продолжено в этом же контексте, но на указанном расширении и приоритете.
  • priority - выполнение диалплана будет продолжено в текущем контексте и расширении, но в указанном приоритете.

Также вы можете пропустить любую из меток, в этом случае при совпадении условия с пропущенной меткой будет выполнен следующий приоритет диалплана.

Если указанные метки содержат некорректные данные (контекст или раширение не существуют), приложение попытается найти и выполнить стандартные расширения 'i' или 'h' в текущем контексте. Если же и они не существуют, то разорвет соединение.

Эта чрезвычайно мощная команда позволяет решать сложные задачи. Напрашивается сравнение со структурой IF ELSE присутствующей во многих языках программирования. Обратите также внимание на схожее приложение диалплана Asterisk ExecIf и функцию If

Синтаксис

GotoIf(condition?[labeliftrue][:labeliffalse])

Аргументы
  • labeliftrue

Продолжать в <labeliftrue> если условие верно. Принимает формат как в goto - [[context,]extension,]priority.

  • labeliffalse

Продолжать в <labeliffalse> если условие неверно. Принимает формат как в goto - [[context,]extension,]priority.

Условие

Классический пример условия это выражение (expression) с использованием конструкции $[...].

exten => s,1,GotoIf($["${CALLERID(num)}" = "2666"]?true:false)
    same => n(true),Verbose(true)
    same => n(false),Verbose(false)

Если CallerID вызывающего абонента = 2666, условие вернет 1 и перейдет на приоритет true, если нет то 0 и приоритет false. В приведенном примере использован оператор сравнения.

  • Операторы сравнения
    • expr1 = expr2
    • expr1 != expr2
    • expr1 < expr2
    • expr1 > expr2
    • expr1 <= expr2
    • expr1 >= expr2

Но по сути condition - это просто строка:

 exten => s,1,GotoIf(0?:3)
     same => n,Verbose(Next)
     same => n,Verbose(False)

В данном примере пропущен лейбл true. Если бы condition было 1 а не 0, вызов бы перешел на строку диалплана Verbose(Next), но так как condition всегда 0, то приоритет 2 никогда не будет выполнен, а диаллан будет продолжаться с приоритета 3 (Verbose(False)).

Логические операторы
  • expr1 | expr2 (Logical OR- ИЛИ)

Если expr1 показывает не пустое или не равное нулю значение, возвращает -true, если пустое, то проверяется expr2 по тому же принципу. Если ничего нет, то - false.

  • expr1 & expr2 (Logical AND -И)

Если оба выражения не пустые или не равны 0, то true, иначе - false.

  • !expr

Логическое дополнение НЕ, может использоваться с OR и AND. Между expr и '!' не должно быть пробела.

exten => s,n,gotoif($[$["${CALLERID(num)}" = "2666"] & $["${CALLERID(name)}" = "Phone Dwarf"]]?true:false)

Предположим некоторое время назад произошло некое событие и мы хотим задать условие по времени прошедшем в того момента:

 exten => s,1,set(timeout=$[${STRFTIME(,,%s)} - $[3600 * 3] ])
     same => n,GotoIf($[${STRFTIME(,,%s)} - ${timeout} >= $[3600 * 2] ]?true:false)
         same => n(false),Verbose(Timeout On)
	 same => n,Playback(goodbye)
	 same => n,hangup
     same => n(true),Verbose(TImeout Off)
     same => n,Playback(welcome)

Сначала задана переменная timeout, которая будет имитировать время события - текущее время и дата минус 3600 * 3, т.е. три дня назад. А потом проверим прошло ли два дня с того момента, и на основании этого выберем действие. Если изменить выражение в первой строке и сделать, например 3600 * 1.5 станет false, а так true. В приведенном примере использованы операторы сравнения и
арифметические операторы.

  • expr1 + expr2
  • expr1 - expr2
  • expr1 * expr2
  • expr1 / expr2

Вышеприведенный пример, кстати, вполне жизненный и может быть использован, например, для автоматического удаления абонентов из черного списка по прошествии периода бана или для ограничения количества международных звонков за заданный промежуток времени.

Регулярные выражения в условии

RegExp

  • expr1 : regexp

Оператор ':' ищет совпадение expr1 в регулярном выражении regexp. Использование оператора ':' подразумевает неявный знак начала выражения '^' вначале строки.

Если совпадение найдено, а регулярное выражение заключено в скобки /(.../), возвращаются совпадающие знаки - true. Если совпадение найдено, но RegEx без скобок возвращается количество совпадающих знаков - true. Если же совпадения не найдено, возвращается 0 - false.

  • expr1 =~ expr2

Оператор '=~' работает также как и ':' но не подразумевает якорь начала выражения. Рассмотрим работу обоих операторов в примере с фальшивым CallerID.

exten => s,1,set(CALLERID(num)=81${RAND(2,3)}3216111)
    same => n,gotoif($[${CALLERID(num)} : "(812.+)"]?true:false)
	same => n(true),Verbose(SPb)
	   same => n,hangup
    same => n(false),Verbose(Len Oblast)

В данном примере приходит CallerID начинающееся с def кода 812 или 813 ( RAND(2,3) ).
При совпадении (812) возвращает "8123216111?true:false" - 1, иначе ничего "?true:false", расценивается как 0, т.е. false.

Во втором примере добавим 7 в начало CallerID и заменим оператор на '=~', а также уберем скобки. При совпадении (812) получим: "10?true:false", где 10 кол-во совпавших знаков - true. Иначе получим "0?true:false" - false. Работает точно также как и первый пример, за исключением того, что 7 вначале не считается false, т.к. символ ^ начала строки в регулярном выражении не подразумевается.

exten => s,1,set(CALLERID(num)=781${RAND(2,3)}3216111)
    same => n,gotoif($[${CALLERID(num)} =~ "812.+"]?true:false)
	same => n(true),Verbose(SPb)
	   same => n,hangup
    same => n(false),Verbose(Len Oblast)

[см. также]

Asterisk app: Goto(), Asterisk App: GotoIfTime(), Asterisk app:GosubIf(), Asterisk app: MacroIf()

Команды диалплана Asterisk

  • asterisk/app/gotoif.txt
  • Последние изменения: 2019/09/26