У Asterisk есть свой механизм для работы с базами данных, я Вам расскажу про альтернативный метод работы с базами данных из диалплана Asterisk! Его можно применить не только для работы с базами, но и с любым другим софтом на сервере. Статья про функцию «SHELL».
В документации про SHELL написано:
SHELL(command)
Runs command and returns its output

В отличии от SYSTEM, SHELL возвращает результат выполнения команды. А в отличии от func_odbc.conf, всю логику обработки результатов запроса к базе данных можно вынести из диалплана Asterisk. С помощью SHELL и bash можно горы свернуть, при этот диалплан можно оставить практически без изменений. Кстати я его пишу на AEL(отличная статья про AEL).

Контекст обработки звонков на мобильные номера
context  outgoing_calls_mobile {
_89XXXXXXXXX => {
        Noop( file_conf outgoing_calls.ael context outcoming_calls_mobile);
        Noop(Звонок от ${CALLERID(num)} на номер ${EXTEN});
        Set(mobile_operator_info=${SHELL(/etc/asterisk/scripts/operatorIF.sh ${EXTEN:1} ${CALLERID(num)})});
// Проверим нет ли ошибки в запросе если есть, уйдем в контекст "error"
                       if ("${mobile_operator_trunk_cid}" = "ERROR") {
                           Gosub(error,s,1(${CALLERID(num)},${EXTEN}));
                             };
// Воспользоватся функцией CUT, в качестве разделителя у нас запятые
        Set(mobile_operator_name=${CUT(mobile_operator_info,\,,1)});
        Set(mobile_operator_id_region=${CUT(mobile_operator_info,\,,2)});
        Set(mobile_operator_region=${CUT(mobile_operator_info,\,,3)});
        Set(mobile_operator_region_id=${CUT(mobile_operator_info,\,,4)});
// У нас есть четыре переменные:
// mobile_operator_name - Имя оператора
// mobile_operator_id_region - id оператора
// mobile_operator_region - регион оператора
// mobile_operator_region_id - id - региона оператора
// У вас должны быть сопоставлены имена операторов с транками, у себя я делаю отдельный //
// запрос в базу для этого сопоставления, здесь же предположим, что имена сопоставлены.
Dial(SIP/${mobile_operator_name}/${EXTEN:1},60,);
// Проверка статуса звонка
Gosub(test_dial,s,1(${DIALSTATUS},${exten}));
Hangup();
        };
        };


Я в скрипт передаю внутренний номер звонящего, просто так, этот номер добавляется в базу.
И сам скрипт на BASH, он делает запрос в базу для поиска старых записей, добавляет новые в базу и спрашивает у мегафона, у какого оператора сейчас находится номер.

Подробнее про API Мегафона
Скрипт использует запрос к публичному API Мегафона
На запрос:
http://www.megafon.ru/api/mfn/info?msisdn=79XXXXXXXXX

API возвращает строчку вида:
{"operator":"Билайн","operator_id":99,"region":"Новосибирская обл.","region_id":56}


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

вот он bash скрипт
#!/bin/bash
sql='mysql -uprovisioning -pxkYyNFuyc3nEKsFj -Dasterisk -e' # Имя  базы данных, имя пользователя и пароль для доступа к базе данных

lifetime=30     # срок в днях, после которого запись в базе данных считается устаревшей

# Поищем записи в базе данных, которые не старше 30 дней, не стоит лишний раз беспокоить чужой сайт.
array_operator_old=($($sql "SELECT operator,operator_id,region,region_id FROM operators WHERE to_phon_nomber like '$1' and data >DATE_ADD(NOW(), INTERVAL -$lifetime DAY) limit 1"| awk 'NR>1'))

# Проверим не пустой ли ответ от базы, если не пустой, то выведем данные и выйдем из скрипта.
if [ -n  "${array_operator_old[1]}" ]
then

operator_old=${array_operator_old[0]}
operator_id_old=${array_operator_old[1]}
region_old=${array_operator_old[2]}
region_id_old=${array_operator_old[3]}

echo -n  $operator_old,$operator_id_old,$region_old,$region_id_old
exit 0
fi

# Если в базе не нашли запись, то  делаем запрос на сайт:
array_operator=($(curl -s http://www.megafon.ru/api/mfn/info?msisdn=$1|tr -d '"{}'|tr -s ' ' '_'|tr -s ',' '\t'))

# Проверка на ошибку, если есть ошибка, то крикнем ERROR и выйдем из скрипта
test_error=$(echo -n ${array_operator[@]}|grep error)

if [ -n  "$(echo -n ${array_operator[@]}|grep error)" ]; then echo -n ERROR; exit 0; fi

# Если ошибки нет, то выводим данные и добавляем/обновляем запись в базе
# Формируем переменные и выводим их через запятую.
        operator=$(echo -n ${array_operator[0]} | tr -d 'operator:'|tr -d '\,')
        operator_id=$(echo -n ${array_operator[1]} | tr -d 'operator_id:')
        region=$(echo -n ${array_operator[2]} | tr -d 'region:')
        region_id=$(echo -n ${array_operator[3]} | tr -d 'region_id:')

        $sql "REPLACE INTO operators
        (id, data, to_phon_nomber, operator, operator_id, region, region_id, in_phon_nomber)         VALUES         (NULL,         NULL,         '$1',         '$operator',         '$operator_id',         '$region_old',         '$region_id',         '$2')"

#operator=$(curl -s https://phonenum.info/phone/$1|grep Оператор\:|head -n1| sed 's/Оператор\:\ //'|tr -s "[:space:]" "_"|sed -r 's/\..*//')
echo -n  $operator,$operator_id,$region,$region_id
exit 0


Дамп базы «operators».

Всем спасибо)

Комментарии (18)


  1. belousovsw
    05.09.2017 07:46

    Доброго дня!
    А если некоторые абоненты меняют оператора каждые 2 месяца, Ваш скрипт будет давать ложную информацию.


    1. Ash666 Автор
      05.09.2017 07:50

      Добрый день. В том виде, что я его опубликовал, скрипт считает актуальными данными если они не старше 30 дней. Измените значение переменной lifetime на 15 или вообще на 1.


  1. BoDRbI
    05.09.2017 07:51

    AEL уже не в тренде, есть lua и lua-sql для такого.
    Вызов bash скрипта с sql запросом не true-way.


    1. Ash666 Автор
      05.09.2017 09:05

      Я процитирую Вас:

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


  1. Dageron
    05.09.2017 08:29

    Если кому-то интересно про базу MNP безотносительно Asteriks, то у Мегафона есть публичный API (из плюсов — выводит еще и регион):

    www.megafon.ru/api/mfn/info?msisdn=7XXXXXXXXX


    1. Ash666 Автор
      05.09.2017 08:30
      +1

      А Вы читали статью?


      1. Dageron
        05.09.2017 08:34

        Читал как раз внимательно, у вас в баш-скрипте эта строчка и указана (но не уверен что до нее дочитают все). Просто сама по себе тема интересная и может иметь массу применений.


        1. Ash666 Автор
          05.09.2017 08:59

          Вы правы, стоило поподробнее остановится на этом моменте!
          Добавил в статью.


  1. osipov_dv
    05.09.2017 08:45

    Статья короткая, но тему раскрывает. Спасибо.


    1. Ash666 Автор
      05.09.2017 09:01

      Всегда пожалуйста!


  1. Sjam
    05.09.2017 11:31

    Спасибо. Как раз что-то подобное искал


  1. lnking
    06.09.2017 10:17
    +1

    Вот еще один сервис для определения оператора и наличия номера в базе mnp
    rosreestr.subnets.ru/?get=num&format=json&num=7XXXXXXXXXX
    Вообще достаточно полезен, поскольку отдает информацию о принадлежности к оператору, региону, и т.д.
    Использую для сложной маршрутизации вызовов на мобильные телефоны. Что-то через свой шлюз, что-то через местного оператора, и т.д.


    1. Ash666 Автор
      06.09.2017 12:47

      Спасибо, вот так можно получить массив со всеми данными через этот сервис:

      array_operator_rosreestr=($(curl -s "http://rosreestr.subnets.ru/?get=num&format=xml&num=$1" | sed -e 's/<[^>]*>//gm'| sed '/^$/d'| tr -d '\t' |tr -s '\ ' '_'))
      echo ${array_operator_rosreestr[9]} # покажет нужного оператора
      echo ${array_operator_rosreestr[5]} # старого оператора
      echo ${array_operator_rosreestr[7]} # регион


  1. mihmig
    06.09.2017 17:40

    Спасибо за сервис мегафона.
    А не знает ли кто аналога сервиса проверки номеров HLR-запросами типа:
    smsc.ru/testhlr


    1. eov
      07.09.2017 00:10

      В таком сервисе самое ценное — это определение IMSI по MSISDN-у (по номеру). Не знаю как по остальным операторам, но по МТС он показывает туфту.


  1. eov
    07.09.2017 11:02

    Посмотрел на сайт ЦНИИС (хранитель ЦБДПН).
    Там тоже можно проверить принадлежность номера оператору (правда без региона). И это сделано очень прикольно…


    А код можно найти вот так…



    1. Ash666 Автор
      07.09.2017 11:10

      Изначально я использовал вот этот сервис: phonenum.info, но на сайте часто появляется реклама и изза этого сложно его парсить. API мегафона и rosreestr позволяют это делать гораздо проще.
      Подобных сервисов много и с капчей и без.


    1. kilgur
      09.09.2017 00:30
      +1

      Эх… и зачем я это увидел «на ночь глядя»… плод ночного бдения. Спасибо, что заглянули в содержимое страницы.