В документации про 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, он делает запрос в базу для поиска старых записей, добавляет новые в базу и спрашивает у мегафона, у какого оператора сейчас находится номер.
На запрос:
http://www.megafon.ru/api/mfn/info?msisdn=79XXXXXXXXX
API возвращает строчку вида:
{"operator":"Билайн","operator_id":99,"region":"Новосибирская обл.","region_id":56}
В конце закомментирована строчка с альтернативным сервисом запроса, кто хочет, может допилить его как резервный канал.
#!/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)
BoDRbI
05.09.2017 07:51AEL уже не в тренде, есть lua и lua-sql для такого.
Вызов bash скрипта с sql запросом не true-way.Ash666 Автор
05.09.2017 09:05Я процитирую Вас:
В статье я постарался подробнее изложить суть, чтобы была возможность человеку далекому от Asterisk быстро сориентироваться в поставленной задаче
Dageron
05.09.2017 08:29Если кому-то интересно про базу MNP безотносительно Asteriks, то у Мегафона есть публичный API (из плюсов — выводит еще и регион):
www.megafon.ru/api/mfn/info?msisdn=7XXXXXXXXXAsh666 Автор
05.09.2017 08:30+1А Вы читали статью?
Dageron
05.09.2017 08:34Читал как раз внимательно, у вас в баш-скрипте эта строчка и указана (но не уверен что до нее дочитают все). Просто сама по себе тема интересная и может иметь массу применений.
Ash666 Автор
05.09.2017 08:59Вы правы, стоило поподробнее остановится на этом моменте!
Добавил в статью.
lnking
06.09.2017 10:17+1Вот еще один сервис для определения оператора и наличия номера в базе mnp
rosreestr.subnets.ru/?get=num&format=json&num=7XXXXXXXXXX
Вообще достаточно полезен, поскольку отдает информацию о принадлежности к оператору, региону, и т.д.
Использую для сложной маршрутизации вызовов на мобильные телефоны. Что-то через свой шлюз, что-то через местного оператора, и т.д.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]} # регион
mihmig
06.09.2017 17:40Спасибо за сервис мегафона.
А не знает ли кто аналога сервиса проверки номеров HLR-запросами типа:
smsc.ru/testhlreov
07.09.2017 00:10В таком сервисе самое ценное — это определение IMSI по MSISDN-у (по номеру). Не знаю как по остальным операторам, но по МТС он показывает туфту.
eov
07.09.2017 11:02Посмотрел на сайт ЦНИИС (хранитель ЦБДПН).
Там тоже можно проверить принадлежность номера оператору (правда без региона). И это сделано очень прикольно…
А код можно найти вот так…
Ash666 Автор
07.09.2017 11:10Изначально я использовал вот этот сервис: phonenum.info, но на сайте часто появляется реклама и изза этого сложно его парсить. API мегафона и rosreestr позволяют это делать гораздо проще.
Подобных сервисов много и с капчей и без.
kilgur
09.09.2017 00:30+1Эх… и зачем я это увидел «на ночь глядя»… плод ночного бдения. Спасибо, что заглянули в содержимое страницы.
belousovsw
Доброго дня!
А если некоторые абоненты меняют оператора каждые 2 месяца, Ваш скрипт будет давать ложную информацию.
Ash666 Автор
Добрый день. В том виде, что я его опубликовал, скрипт считает актуальными данными если они не старше 30 дней. Измените значение переменной lifetime на 15 или вообще на 1.