Архив рубрики: Публикации

FreePBX, Elastix. Уведомление о пропущенных вызовах

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

Уведомления при потерянных вызовах на IVR

Если вызовы поступают на IVR, и звонящий не дождавшись ответа положил трубку, то для отчетов правим файл /etc/asterisk/extensions_override_freepbx.conf

# nano /etc/asterisk/extensions_override_freepbx.conf

 

[ivr-1] ;Номер ivr

exten => h,1,System(python /usr/local/bin/sendmail.py "Пропущенный вызов в ${STRFTIME(${EPOCH},,%Y-%m-%d %H:%M:%S)}с номера ${CALLERID(name)}")


Сохраняем и делаем reload астериска. Тепер. если позвонивший положит трубку слушая голосовое меню, то на почту прийдет уведомление. Сам  sendmail.py находится в конце статьи.

Уведомление в группах вызова

Если необходимо уведомлять о потерянных вызовах в группах вызова, то также правим файл /etc/asterisk/extensions_override_freepbx.conf

# nano /etc/asterisk/extensions_override_freepbx.conf

 

[ext-group]

exten => h,1,System(python /usr/local/bin/sendmail.py "Пропущенный вызов в ${STRFTIME(${EPOCH},,%Y-%m-%d %H:%M:%S)}с номера ${CALLERID(name)}")

exten => h,2,Macro(hangupcall,)

 Уведомление в очередях

Если же вызов поступает в очередь, то в /etc/asterisk/extensions_override_freepbx.conf  прописываем

[ext-queues]

exten => h,1,ExecIf($["${CDR(dstchannel)}"=""]?System(python /usr/local/bin/sendmail.py "Пропущенный вызов в ${STRFTIME(${EPOCH},,%Y-%m-%d %H:%M:%S)} с номера ${CALLERID(name)}"))

exten => h,2,Macro(hangupcall,)

Сам файл sendmail.py

#!/usr/bin/python

# -*- coding: utf-8 -*-

from email.MIMEText import MIMEText

import smtplib

import sys

sender = 'noanswer@yourdomain.ru' # От кого

recivers = 'youremail' # Ваш e-mail

host = "localhost"

text = sys.argv[1]

msg = MIMEText(text, "", "utf-8")

msg["Subject"] = "Уведомление о пропущенном вызове"

smtpObj = smtplib.SMTP('localhost')

smtpObj.sendmail(sender, recivers, msg.as_string())

smtpObj.close()


Не забудте дать права на запуск

chmod 755 /usr/local/bin/sendmail.py



2018-09-29T23:30:16
Asterisk

Asetrisk, распознавание и генерации речи с помощью yandex speechkit

В этой статье я расскажу как с помощью asterisk и  yandex speechkit, можно организовать интерактивный диалог с помощью голоса. В качестве примера создадим систему для голосового сбора показаний счетчиков горячей и холодной воды, сразу скажу, что это просто пример, а не рабочая версия, просто здесь показана сама идея организации диалога.

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

На Астериске организован цикл while

1234567 => {

Answer;

Set(audio=/var/lib/asterisk/sounds/custom/enteraccount);

flag=1;

label=1;

while (${flag} = 1){

Background(${audio});

Record(/tmp/${UNIQUEID}label${label}.wav,3,20);

Agi(yandex.agi,/tmp/${UNIQUEID}, ${label});

label=${label}+1;



                  };



    };

В начале позвонившему проигрывается фудио файл «enteraccount» с просьбой назвать лицевой счет

На каждом шаге цикла, позвонившему человеку проигрывается аудио файл «audio», путь к которому получен из agi скрипта, далее записывается ответ, и путь к полученному записанному файлу отправляется agi скрипту, также в скрипт отправляется текущий шаг «label», после чего шаг увеличивается на 1, и цикл повторяется. Из agi скрипта астерис получает 2 параметра, это обязательный параметр «audio», путь к аудиофайлу который нужно проиграть, и не обязательный «label», метка с помощью которой происходит синхронизация астериска и agi. Выход из цикла происходит если человек положил трубку, а также если из agi прийдет параметр «flag» не равный 1.

Еще неплохо бы после завершения вызова удалить все временные файлы, для этого в макросе который срабатывает после завершения вызова пропишем

[macro-hangupcall]

exten => s,1,System(find /tmp/ -name "${UNIQUEID}*" | xargs rm);

На этом настройка астериска завершена.

Далее сам скрипт yandex.agi, написанный на python, для работы необходимо установить pyst

# wget http://heanet.dl.sourceforge.net/project/pyst/pyst/0.6.50/pyst-0.6.50.zip

# unzip pyst-0.6.50.zip

# cd pyst-0.6.50

# python setup.py install

Сам agi:

#!/usr/bin/python

# -*- coding: utf-8 -*-

import urllib2

import urllib

import sys

import random

from xml.dom.minidom import *

import os

import asterisk.agi



agi=asterisk.agi.AGI()

uuid=''

key='28b22b47-a7b0-40d2-892d-ad79bbdbc304'

def yadexASR(uuid, key, topic, callid):

# Функция для преобразования аудио файла в текст

# Генерим уникальный код id для запроса

    while (len(uuid)<32):

        uuid=uuid+random.choice('1234567890abcdef')

    #Ссылка для пост запроса 

    url = 'https://asr.yandex.net/asr_xml?uuid=%s&key=%s&topic=%s&lang=ru-RU' % (uuid, key, topic)

    filename = callid+'.wav'

    #Считываем файл в двоичном режиме

    audio = open(filename,'rb').read()

    #Указываем тип аудиофайла для заголовка в POST запрос

    headers={'Content-Type': 'audio/x-pcm;bit=16;rate=8000'}

    #Отправляем запрос

    request = urllib2.Request(url, data=audio, headers=headers)

    response = urllib2.urlopen(request)

    #Считываем ответ

    answer=response.read()

    # Создаем xml файл для полученного ответа

    f_answer=('%s.xml' % callid)

    f=open(f_answer, 'w')

    # записываем в файл ответ полученный на POST запрос (ответ получен в xml формате)

    f.write(answer)

    f.close()

    # Парсим xml файл

    xml = parse(f_answer)

    # Выбираем из файла значение между тегами variant

    var = xml.getElementsByTagName('variant')

    # Выбираем первое значение из xml файла, оно же наиболее точное в распознании

    result=var[0].childNodes[0].nodeValue

    return result



def generate(key,text, file):

# Функция для преобразования текста в аудио формат

    #Форматируем текс для GET запрса (нужен для корректной обработки кирилици)

    text_f=urllib.quote_plus(text.encode('utf-8'))

    #отправляем запрос на яндекс

    url='http://tts.voicetech.yandex.net/generate?text=%s&format=mp3&lang=ru-RU&speaker=jane&key=%s' % (text_f, key)

    # Сохраняем айдио файл в file

    urllib.urlretrieve(url, file)



if sys.argv[2].replace(' ','')=="1":

    agi.verbose('label='+sys.argv[2].replace(' ',''))

    try:

        # Распознаем полученный файл

        result=yadexASR(uuid, key, 'notes', sys.argv[1]+'label'+sys.argv[2].replace(' ',''))

        # Формируем ответ

        file=sys.argv[1]+'outlabel'+sys.argv[2].replace(' ','')

        generate(key, u'Вы сказали '+result+u'Скажите да или Нет', file+'.mp3')

        agi.set_variable('audio', file)

    except:

        agi.set_variable('audio', '/var/lib/asterisk/sounds/custom/enteraccount')

        agi.set_variable('label', '0')

        agi.verbose('label=0')



elif sys.argv[2].replace(' ','')=="2":

    agi.verbose('label='+sys.argv[2].replace(' ',''))

    try:

        result=yadexASR(uuid, key, 'notes', sys.argv[1]+'label'+sys.argv[2].replace(' ',''))

    except:

        agi.set_variable('label', '1')

    if 'Да' in str(result.encode('utf-8')):

        agi.verbose('Yes')

        #///////////////////////////////

        # Здест должна быть проверка на существование абонента в базе данных

        #/////////////////////////////

    

        file=sys.argv[1]+'outlabel'+sys.argv[2].replace(' ','')

        generate(key, u'Показания какого счетчика вы хотите сообщить горячего или холодного?', file+'.mp3')

        agi.set_variable('audio', file)

    elif 'Нет' in str(result.encode('utf-8')):

        agi.verbose('No')

        # Ставим метку в 0 что бы вернуться к шагй 1 и проигрываем файл

        agi.set_variable('label', '0')

        agi.set_variable('audio', '/var/lib/asterisk/sounds/custom/enteraccount')

    else:

        agi.verbose('Error')

        # Если ответ не да и ни нет, говорим об ошибки и ставим метку на 1 что бы вернуться к шагу 2

        agi.set_variable('label', '1')

elif sys.argv[2].replace(' ','')=="3":

    agi.verbose('label='+sys.argv[2].replace(' ',''))

    try:

        result=yadexASR(uuid, key, 'notes', sys.argv[1]+'label'+sys.argv[2].replace(' ',''))

    except:

        agi.set_variable('label', '2')

    if 'Горяч' in str(result.encode('utf-8')):

        agi.verbose('Hot')      

        file=sys.argv[1]+'outlabel'+sys.argv[2].replace(' ','')

        generate(key, u'Сообщите показания горячего счетчика', file+'.mp3')

        agi.set_variable('audio', file)

    elif 'Холод' in str(result.encode('utf-8')):

        agi.verbose('Cold')     

        file=sys.argv[1]+'outlabel'+sys.argv[2].replace(' ','')

        generate(key, u'Сообщите показания холодного счетчика', file+'.mp3')

        agi.set_variable('audio', file)

    else:

        agi.verbose('Error')

        agi.set_variable('label', '2')

elif sys.argv[2].replace(' ','')=="4":

    agi.verbose('label='+sys.argv[2].replace(' ',''))

    try:

        result=yadexASR(uuid, key, 'notes', sys.argv[1]+'label'+sys.argv[2].replace(' ',''))      

        file=sys.argv[1]+'outlabel'+sys.argv[2].replace(' ','')

        generate(key, u'Ваши показания '+result+u'Скажите да или Нет', file+'.mp3')

        agi.set_variable('audio', file)

    except:

        agi.set_variable('label', '3')

        agi.verbose('label=3')

elif sys.argv[2].replace(' ','')=="5":

    try:

        result=yadexASR(uuid, key, 'notes', sys.argv[1]+'label'+sys.argv[2].replace(' ',''))

    except:

        agi.set_variable('label', '1')

    if 'Да' in str(result.encode('utf-8')):

        

        #/////////////

        #Обрабатываем результат и заносим в базу

        #/////////////

 

        file=sys.argv[1]+'outlabel'+sys.argv[2].replace(' ','')

        generate(key, u'Хотите сообщить показания другого счетчика да или нет?', file+'.mp3')

        agi.set_variable('audio', file)

    elif 'Нет' in str(result.encode('utf-8')):

        agi.set_variable('label', '2')

        file=sys.argv[1]+'outlabel'+sys.argv[2].replace(' ','')

        generate(key, u'Показания какого счетчика вы хотите сообщить горячего или холодного?', file+'.mp3')

        agi.set_variable('audio', file)

    else:

        agi.verbose('Error')

        agi.set_variable('label', '2')

elif sys.argv[2].replace(' ','')=="6":

    try:

        result=yadexASR(uuid, key, 'notes', sys.argv[1]+'label'+sys.argv[2].replace(' ',''))

    except:

        agi.set_variable('label', '1')

    if 'Да' in str(result.encode('utf-8')):

        file=sys.argv[1]+'outlabel'+sys.argv[2].replace(' ','')

        generate(key, u'Показания какого счетчика вы хотите сообщить горячего или холодного?', file+'.mp3')

        agi.set_variable('audio', file)

        agi.set_variable('label', '2')

    elif 'Нет' in str(result.encode('utf-8')):

        file=sys.argv[1]+'outlabel'+sys.argv[2].replace(' ','')

        generate(key, u'Досвидания', file+'.mp3')

        agi.set_variable('audio', file)

    else:

        agi.verbose('Error')

        file=sys.argv[1]+'outlabel'+sys.argv[2].replace(' ','')

        generate(key, u'Хотите сообщить показания другого счетчика да или нет', file+'.mp3')

        agi.set_variable('label', '5')



2018-09-29T23:27:08
Asterisk

Elastix, права на прослушивание записей и просмотр статистики звонков

По умолчанию прослушивать запись и просматривать статистику всех звонков в Elastix может только пользователь admin, все остальные пользователи могут прослушивать и просматривать статистику только своих звонков. Если же нужно разрешить пользователю из группы Operator доступ ко всем звонкам, но при этом не делать его администратором, то в Elastix, в файле:

var/www/html/libs/paloSantoACL.class.php

В функции:

function isUserAdministratorGroup($username)

после строчки:

 $is = array_search('1', $arrGroup);

Добавить следующий код:

if(isset($arrGroup['Operator']))

$is=true;


После этого все пользователи группы Operator смогут просматривать отчет по всем звонкам, а также прослушивать все разговоры.



2018-09-29T23:25:09
Asterisk

Сброс пароля на админку в django

Что делать если вы забали пароль от админки к django? Есть как минимум 2 решения проблемы.

Первое решение просто поменять пароль на root или другого суперпользователя, которого вы создали при создании базы данных. Для этого входим в manage.py shell

python manager.py shell

и набираем

>>>from django.contrib.auth.models import User

>>>user = User.objects.get( username='root')

>>>user.set_password(«password»)

>>>user.save()

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

python manage.py createsuperuser

 И вводим новые данные.



2018-09-29T23:09:18
Django

Настройка PPTP клиент в MikroTik RouterOS

Для настройки подключения к серверу PPTP на микротике, нужно зайти в меню РРР и добавить новый PPTP Client интерфейс, на вкладке Dial Out прописываем следующие параметры:

ConnectTo — ip адрес PPTP сервера

User — логин для подключения к РРТР серверу

Password — пароль для подключения к РРТР серверу

Add Default Route — указываем если хотим что бы весь наш трафик шел через РРТР тунель.

Dial on Demand — установите этот флажок, если вы хотите, чтобы Mikrotik подключался к провайдеру только если с одного из ваших устройств запрошено подключение к интернет. И держал соединение отключенным, если выход в интернет никому не требуется.

 

Обучающий курс по настройке MikroTik

Нужно разобраться с MikroTik, но не определились с чего начать? В курсе «Настройка оборудования MikroTik» все по порядку. Подойдет и для начала работы с этим оборудованием, и для того, чтобы систематизировать знания. Это видеокурс из 162 уроков и 45 лабораторных работ, построен на официальной программе MTCNA. Проходить можно, когда удобно и пересматривать по необходимости – материалы курса выдаются бессрочно. Также есть 30 дней на личные консультации с автором. На пробу выдают 25 уроков бесплатно, заказать их можно на странице курса.

Если вы нашли ошибку, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter.



2018-09-29T23:03:44
Микротик

Настройка PPTP сервера в MikroTik RouterOS

Часто сотрудники офиса работают удаленно, или находятся в разъездах, при этом им необходимо подключаться к внутренней локальной сети компании, например для доступа к общим папкам принтерам и т.д. Если в качестве маршрутизатора используется MikroTik RouterOS, то его можно настроить как PPTP сервер, и сотрудники смогут подключатся к нему и попадать в локальную сеть.

Настройка микротика

Заходим в меню PPP, на вкладке interface нажимаем кнопку PPTP Server, в открывшемся окне ставим галочку Enable, и указываем нужные нам шифрования при аутентификации, я поставил все.

Теперь идем на вкладку secret нажимаем «+» и прописываем следующие поля:

Name — логин, который пользователь будет указывать при подключении

Password — пароль,  который пользователь будет указывать при подключении

Local Address — локальный адрес маршрутизатора

Remote Address — адрес из локальной сети который будет выдан пользователю

Иногда при подключении к серверу соединение есть, но внутреннюю сеть не видно. В таком случае на интерфейсе локальной сети надо включить proxy-arp. Идем в меню interfaces,  вкладка interface и выбираем нужный интерфейс.

На этом настройка PPTP сервера закончена

Обучающий курс по настройке MikroTik

Нужно разобраться с MikroTik, но не определились с чего начать? В курсе «Настройка оборудования MikroTik» все по порядку. Подойдет и для начала работы с этим оборудованием, и для того, чтобы систематизировать знания. Это видеокурс из 162 уроков и 45 лабораторных работ, построен на официальной программе MTCNA. Проходить можно, когда удобно и пересматривать по необходимости – материалы курса выдаются бессрочно. Также есть 30 дней на личные консультации с автором. На пробу выдают 25 уроков бесплатно, заказать их можно на странице курса.

Если вы нашли ошибку, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter.



2018-09-29T22:58:59
Микротик