Pull to refresh

Asterisk, автоматическое определение сотового оператора по номеру телефона даже перенесенных номеров

Reading time 3 min
Views 18K
У 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».

Всем спасибо)
Tags:
Hubs:
If this publication inspired you and you want to support the author, do not hesitate to click on the button
+8
Comments 19
Comments Comments 19

Articles