Lua

Как бы я этого не хотел, но с факсами сталкиваемся. В этой заметке хочу описать как можно организовать принятие факсов в Webitel с дальнейшей отправкой на Email.

Нам понадобится утилита convert.exe из пакета ImageMagick. Утилиту забрасываем в папку CallManager\ (с ее помощью будим конвертировать TIF в PDF для отправки на Email). Так же, создадим папку CallManager\htdocs\storage\FAX — тут будут хранится оригиналы полученных факсов в TIF формате. Не забываем про настройки SMTP клиента, иначе ничего никуда не отправится!

Собственно Lua-скрипт довольно простой:

t38 = "false";
CallerID = session:getVariable("caller_id_number");
FaxDir = session:getVariable("storage_dir").."/FAX/";
FaxFile = FaxDir..os.date("%Y").."_"..os.date("%m").."_"..os.date("%d").."_"..os.date("%H").."-"..os.date("%M").."_"..CallerID..".tif";

session:answer();
session:sleep(1000);
session:execute("playback", "users/auto_fax.wav");
session:execute("playback", "users/press_start_to_receive_a_fax.wav");
session:execute("set", "fax_enable_t38_request="..t38);
session:execute("set", "fax_enable_t38="..t38);
session:execute("playback", "silence_stream://2000");
session:execute("rxfax", FaxFile);

freeswitch.email("to@webitel.ua",
	"from@webitel.ua",
	"subject: FAX from "..CallerID.."\n",
	"Приветствую!\n\nВам отправили FAX, который я прикрепил во вложение.\n\n--\nВаш, Webitel",
	FaxFile,
	"convert.exe",
	"pdf");

session:hangup();

Осталось назначить внутренний номер для этого скрипта и все факсы будут сохранятся на сервере:

Принятые Факсы
Принятые Факсы

А так же, приходят на Email:

Факс на Email
Факс на Email

Используя телефоны Yealink, никогда особо не обращал внимание на такую полезную функцию как Мелодии:

Мелодии
Мелодии

Прелесть этого функционала заключается в том, что Вы можете создать группы (до 10) с индивидуальными звуковыми файлами. Все, что нужно, так это на стороне CallManager отправить в SIP пакете заголовок «Alert-info» с указанием нужной группы. И телефон зазвонит!

На Webitel мы можем строить любые сценарии поведения звонка с помощью LUA-скриптов. Если я хочу, чтобы при определенном входящем вызове зазвучала мелодия из группы test4, я вызываю всего 1 строчку в скрипте:

session:execute("export", "alert_info=< http://localhost/>;info=test4")

Теперь, для разных групп абонентов из Terrasoft CRM, я могу установить разные мелодии. Правда, удобно? 😉

FreeSWITCHДумаю, что многие используют переадресацию звонков на мобильный, когда вне офиса. Да, это очень удобная функция современной АТС: уходишь, включил переадресацию на мобильный (или по расписанию) и принимаешь важные звонки… Но, одним из неудобных моментов такой переадресации — отсутствие понимания с какого номера пришел звонок (у нас то всегда отображается офисный номер!). Для себя я решил этот вопрос следующим образом: приходит переадресованный звонок, разговариваю, надо узнать номер звонящего — нажимаю *9 и получаю SMS. Как это работает? В предыдущем посте я описал как отправить SMS о пропущенном звонке, так что останавливаться на самом SMS не буду. Все, что нужно, это добавить в dialplan, когда срабатывает переадресация, вызов вот такого action:

&lt;action application=&quot;bind_meta_app&quot; data=&quot;9 b s lua::smsinfo.lua ${cell}&quot;/&gt;

Я использую application bind_meta_app, который позволяет привязывать в уже отвеченном разговоре на заданную комбинацию DTMF запуск разных сценариев. Вот я и запускаю на *9 Lua скрипт с отправкой SMS:

local CallerName = session:getVariable("caller_id_name")
local CallerNumber = session:getVariable("caller_id_number")

function urlencode (s)
 return (string.gsub (s, "%W",
        function (str)
                return string.format ("%%%02X", string.byte (str) )
        end ))
end

local SMS = '<?xml version="1.0" encoding="UTF-8" ?> \
<request method="send-sms" login="login" passw="password"> \
<msg id="1" phone="' ..cell.. '" sn="IT-SFERA" encoding="cyr">Абонент: ' ..CallerName.. ' \
Номер: ' .. CallerNumber.. '&lt;/msg>&lt;/request>'

if (cell) then
        api = freeswitch.API();
        local response = api:execute("curl", "http://sms.it-sfera.com/websend/ post " ..urlencode(SMS) )
        freeswitch.consoleLog("DEBUG","Here's response:\n" .. response .. "\n")
end

И получаем SMS:

Абонент на линии
Абонент на линии

FreeSWITCHИнтересной функцией для офисной АТС может стать отправка SMS сотруднику о пропущенном звонке. Я опишу, как реализовать этот функционал на FreeSWITCH.

1. Формат SMS
Мой SMS провайдер принимает сообщения через HTTP XML API. Мне необходимо будет сформировать XML файл и передать его методом POST на URL шлюза. Использовать будем модуль mod_curl. Здесь проблем нет. Только нужна будет функция для преобразования XML в urlencode…

2. Когда и куда отправлять
Что бы ответить на вопрос куда отправить, в directory я к регистрации каждого сотрудника добавил переменную cell с мобильным. Теперь из скрипта можно будет получить эту информацию. А когда отправлять? Здесь 2 проверки:
1. причина разрыва коммутации «ORIGINATOR_CANCEL»
2. возможно абонент Вам оставил голосовое сообщение?

3. Как вызвать скрипт?
Из dialplana 🙂 Просто добавьте вот такой action в extension с локальными пользователями:

4. А теперь сам скрипт на Lua

local send = false
local cell = env:getHeader("cell")
local hangup_cause = env:getHeader("hangup_cause")
local bridge_channel = env:getHeader("bridge_channel")
local CallerName = env:getHeader("Caller-Caller-ID-Name")
local CallerNumber = env:getHeader("Caller-Caller-ID-Number")

function urlencode (s)
 return (string.gsub (s, "%W",
        function (str)
                return string.format ("%%%02X", string.byte (str) )
        end ))
end

local SMS = ' \
 \
'

if (hangup_cause == "ORIGINATOR_CANCEL" and cell) then
        SMS = SMS.. "Вам звонили: " ..CallerName.. " " .. CallerNumber
        send = true
end

if (bridge_channel == "loopback/voicemail-a" and cell) then
        SMS = SMS.. "Новое сообщение от " ..CallerName.. " " .. CallerNumber
        send = true
end

if (send) then
        SMS = SMS.. ""
        api = freeswitch.API();
        local response = api:execute("curl", "http://sms.it-sfera.com/websend/ post " ..urlencode(SMS) )
        freeswitch.consoleLog("DEBUG","Here's response:\n" .. response .. "\n")
end

5. О, sms-ка пришла!

У Вас пропущенный звонок!
У Вас пропущенный звонок!

Недавно мне задали вопрос: «Как можно с помощью FreeSWITCH сделать рассылку факсов по списку номеров?» Я набросаю ключевые пункты, как это сделать.

Во-первых, у Вас должна быть какая-то SQL база со списком номеров. К примеру, берем MySQL с одной табличкой fax, где находиться колонка distination.

Во-вторых, файл, который будем отправлять. Что бы привести его в пригодный нам формат, воспользуемся утилитой convert:

convert -density 204x98 -units PixelsPerInch -resize 1728x1186\! -monochrome -compress Fax my-fax-file.pdf /opt/freeswitch/storage/fax_out/01.tif

В-третьих, напишем LUA-скрипт scripts/send_fax.lua, который будет лезть в базу, выбирать номер и отправлять наш файлик:

local fax_file = "/opt/freeswitch/storage/fax_out/01.tif"

local dbh = freeswitch.Dbh("dsn", "user", "password")
if dbh:connected() then
        freeswitch.consoleLog("NOTICE", "database connected\n")
else
        freeswitch.consoleLog("ERR", "database error\n")
    return
end

local my_query = "select distination from fax "

assert(dbh:query(my_query, function(row)
        freeswitch.consoleLog("NOTICE", "\nSending FAX to " ..row.distination.. "\n")
        send_fax = "originate sofia/gateway/farlep/" ..row.distination.. " &txfax(" ..fax_file.. ")"
        api = freeswitch.API()
        reply = api:executeString(send_fax)
        freeswitch.consoleLog("DEBUG", "\nSending " ..reply.. "\n")
end))

Теперь можем просто из консоли FreeSWITCH выполнить скрипт:

luarun send_fax.lua

Дальше, приправляем на свой вкус: записать результат отправки в базу или еще чего….