Автоматическая генерация Dial Patterns для Asterisk из DEF-кодов сотовых операторов

в 7:36, , рубрики: asterisk, def-коды, freepbx, linux, телефония, метки: , ,

В конторе используем шлюзы GSM, для исходящих звонков на сотовые. Но была задача ограничить диапазон номеров в outboud routes asterisk, чтобы пользователи не звонили куда попало. А именно разрешить исходящую связь только на сотовые своего региона.

Далее можно прочитать как автоматизировать обновление Dial Patterns исходящих звонков в Asterisk, используя общедоступный список DEF-кодов сотовых операторов.

Автоматизации подвергался сервер Asterisk 1.8.6.0, работающий на дистрибутиве FreePBX 2.10.1.1.

Итак, для начала нам необходимо было раздобыть где-то список DEF-кодов сотовых операторов, которые можно было бы анализировать.
Оказалось, что сайт россвязи обладает такой информацией, причем периодически ее обновляет.
Таким образом по данной ссылке можно получить последний обновленный список DEF-кодов сотовых операторов в формате html.

Так как хотелось бы запихать потом обновление Dial Patterns в crontab, то было принято решение парсить эту html-ку на bash.
Ну а так как bash не сказать, что удобен для обработки текста, основная функция перевода в Dial Patterns написанна на awk.

Итак, после загрузки переработки html всякими grep и sed командами получался файл csv, с разделителем ;, вида:

913;0000000;0199999;200000;Мобильные ТелеСистемы;Новосибирская область
913;0600000;0699999;100000;Мобильные ТелеСистемы;Новосибирская область
913;2000000;2099999;100000;Мобильные ТелеСистемы;Новосибирская область
913;3700000;3999999;300000;Мобильные ТелеСистемы;Новосибирская область

Первый столбец: DEF-код
Второй и третий столбцы: диапазон выделенных номеров (от и до)
Четвертый столбец: общее количество выделенных номеров
Пятый столбец: Оператор
Шестой столбец: Регион

Вот такой вид после требовалось преобразовать в формат Dial Patterns, что в общем-то и было основной задачей, которая была сделана при помощи языка awk. На выходе скрипта получался список:

901458XXXX
901459XXXX
903049XXXX
903076XXXX
90390[0-6]XXXX
90393XXXXX
90399[7-9]XXXX
90509[4-5]XXXX

Ну и чтобы совсем ничего самому не нажимать, после формирования Dial Patterns, они загружаются в БД FreePBX, и инициируется применение конфигурации в FreePBX через curl. (!!! Внимание!! надо знать id роута, к которому будут применяться шаблоны, ну и сами данные, записываемые в таблицы БД сугубо индивидуальны. Потому обратите внимание что конкретно вам надо)

Вот собственно сам скрипт, который выполняет все данные манипуляции, который можно после записать в планировщик на сервере:

#!/bin/bash

#файл DEF-кодов
DOWNFILE='http://www.rossvyaz.ru/docs/num/DEF-9x.html';
#рабочая папка
TMPDIR='./';
#файл, где сохраним csv формат кодов
FILENAME='codes';
#какой регион будем выделять
REGION='Новосибирская область';

#id outbound route в FreePBX mysql БД
ROUTE_ID=4

FREEPBX_LOGIN='admin'
FREEPBX_PASS='pass'
FREEPBX_ADRESS='192.168.1.15'

#качаем и преобразуем в формат csv
wget -c -q -O - $DOWNFILE | grep "^<tr>" | sed -e 's/</td>//g' -e 's/<tr>//g' -e 's/</tr>//g' -e 's/[t]//g' -e 's/^<td>//g' -e 's/<td>/;/g' | iconv -c -f WINDOWS-1251 -t UTF8 | grep "$REGION" > $TMPDIR/$FILENAME

#проверяем не скачали ли пустышку
check=`cat $TMPDIR/$FILENAME`
if [ "$check" == "" ]; then
exit 0
fi

#скрипт на awk генерации Dial Patterns
awk_code='
#функция определения диапазона
function ret_diap(from,to)
{
     if ((to-from)==0) return from;
     else if ((to-from)==9) return "X";
     else return "["from"-"to"]";
}
#основная функция
{
        DEF=$1;
        razm=1;
        delete out_str;
        for (i=1; i <= length($3);i++)
        {
                if ((substr($3,i,1)-substr($2,i,1))==0)
                        {
                                for (r=1; r <= razm;r++)
                                {
                                        out_str[r]=out_str[r] substr($3,i,1);
                                }

                        }
                else
                        {
                                if ((substr($3,i,1)-substr($2,i,1))==9)
                                {
                                        for (r=1; r <= razm;r++)
                                        {
                                                out_str[r]=out_str[r]"X";
                                        }

                                }
                                else
                                {
                                        if (substr($3,i,1)-substr($2,i,1)>=1 && substr($3,(i+1),1)-substr($2,(i+1),1)!=9)
                                        {
                                                count=1;
                                                init_str=out_str[1];
                                                for (j=substr($2,(i),1); j < substr($3,(i),1);j++)
                                                {
                                                        if (count==1)
                                                        {
                                                                out_str[count]=init_str j ret_diap(substr($2,(i+1),1),9);
                                                        }
                                                        else
                                                        {
                                                                out_str[count]=init_str ret_diap(j,(substr($3,(i),1)-1)) "X";
                                                                j=(substr($3,(i),1)-1);
                                                        }
                                                        count++;
                                                        if (razm<count) razm=count;
                                                }
                                                out_str[count]=init_str j ret_diap(0,substr($3,(i+1),1));
                                                i++;
                                        }
                                        else
                                        {
                                                for (r=1; r <= razm;r++)
                                                {
                                                        out_str[r]=out_str[r]"["substr($2,i,1)"-"substr($3,i,1)"]";
                                                }
                                        }
                                }
                        }
        }
        for (r in out_str)
        {
                print 8DEF out_str[r];
        }
}'

#исполняем код awk, на выходе - Dial Patterns
cat codes | awk -F ';' "$awk_code" > patterns

#удаляем старые паттерны
sql="DELETE FROM outbound_route_patterns WHERE route_id=$ROUTE_ID"
echo $sql
mysql -Dasterisk -e "$sql"

#формируем новые паттерны
sql="INSERT INTO outbound_route_patterns (route_id,match_pattern_pass,match_pattern_prefix) VALUES "
n=1
for i in `cat patterns_mts`
do
        if [ $n -eq 1 ]; then  sql="$sql ($ROUTE_ID,'$i','')"
        else sql="$sql, ($ROUTE_ID,'$i','')"
        fi
        let n=n+1
done
echo $sql
mysql -Dasterisk -e "$sql"

#авторизуемся на freepbx
curl -c cookies -d 'username=$FREEPBX_LOGIN&password=$FREEPBX_PASS&submit=Login' http://$FREEPBX_ADRESS/admin/config.php > /dev/null
#перезагружаем конфигурацию
curl -b cookies http://FREEPBX_ADRESS/admin/config.php?handler=reload > /dev/null

PS: скрипт и функция не претендует на идеальность и универсальность. Но при желании можно переделать под свои нужды очень легко.

Автор: AndrewKevich

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js