Showing posts with label transfer. Show all posts
Showing posts with label transfer. Show all posts

Wednesday, August 9, 2017

FusionPBX/FreeSWITCH save CLID on transfer

Idea is when call is received, transfer to next destination should come with callerID was received originally, not updated in moment of transfer. Sometimes it's needed for correct CRM integration or peoples just get used to it, cause it's default with blind transfer.

Actually, same ideas that described here, but for use in FusionPBX.

1. Create context save_transfer with order ~85
condition - <empty>
action - export - nolocal:execute_on_answer_1=lua number_save_on_transfer_store.lua
action - export - api_hangup_hook=lua number_save_on_transfer_db_cleanup.lua

2. Create context restore_transfer with order higher, than save_trasfer, ~80
condition - ${db(exists/number_transfer_store/${sip_from_user})} - ^true$
action - set - restored_number_on_transfer=${db(select/number_transfer_store/${sip_from_user})} - inline
action - set - effective_caller_id_number=${restored_number_on_transfer}
action - set - effective_caller_id_name=${restored_number_on_transfer}
action - db - delete/number_transfer_store/${sip_from_user}
condition - ${db(exists/number_transfer_store/${sip_from_user}_name)} - ^true$
action - set - restored_number_on_transfer_name=${db(select/number_transfer_store/${sip_from_user}_name)} - inline
action - set  - effective_caller_id_name=${restored_number_on_transfer_name}
action - db - delete/number_transfer_store/${sip_from_user}_name

Lua files:
/usr/share/freeswitch/scripts/number_save_on_transfer_store.lua

-- Save number_answered / original caller_id to database

--api = freeswitch.API()

if (session:ready()) then
    answered_extension = session:getVariable("dialed_user")

    caller_id = session:getVariable("restored_number_on_transfer")
    caller_name = session:getVariable("restored_number_on_transfer_name")

    if (caller_id == nil) then
        caller_id = session:getVariable("sip_from_user")
    end
    if (caller_name == nil) then
        caller_name = session:getVariable("sip_from_display")
    end
    if (answered_extension ~= nil and caller_id ~= nil) then
        freeswitch.consoleLog("INFO", "[NUMBER_ON_TRANSFER_SAVE] Got answered call from "..caller_id.." to "..answered_extension.."\n")
        session:execute('db', 'insert/number_transfer_store/'..answered_extension..'/'..caller_id)
        if (caller_name ~= nil) then
            session:execute('db', 'insert/number_transfer_store/'..answered_extension..'_name/'..caller_name)
        end
    end
end

/usr/share/freeswitch/scripts/number_save_on_transfer_db_cleanup.lua

-- Cleanup database

api = freeswitch.API()
sip_to_user = env:getHeader("variable_last_sent_callee_id_number")

if (sip_to_user ~= nil) then
--serialized = env:serialize()
--freeswitch.consoleLog("INFO","[hangup]\n" .. serialized .. "\n")

    freeswitch.consoleLog("INFO", "[DB_CLEANUP] Cleaning " .. sip_to_user .. "\n")
    api:executeString('db delete/number_transfer_store/'..sip_to_user)
    api:executeString('db delete/number_transfer_store/'..sip_to_user..'_name')
end



P.S.: At the end, db is can be easily replaced with hash. As we don't need persistence storage here.

Monday, September 17, 2012

Предача Clid при переводе звонка

Так получилось, что необходимость это сделать переросла из "было бы неплохо" до "надо сделать".
Начальные условия: телефоны делают transfer не средствами станции, а своими. Тот, кому звонят должен как-то увидеть, что звонок переводится.
Сделано для варианта вызова простым Dial, но с очередью проблем быть не должно, просто другая переменная.

Смысл такой: при ответе вызывается макрос, которые заносит номера пары звонящий/ответивший в базу. При завершении разговора эта запись стирается. При вызове ответившего по второй линии (что и делается при переводе) его номер заменяется на номер звонящего (можно с модификациями, типа Перевожу ХХХ).

При использовании очередей также можно использовать этот метод, но надо доработать  macro-StoreCLID на предмет анализа не DIALEDPEERNUMBER, а MEMBERINTERFACE, или, в в случае перехвата - BRIDGEPEER. Только предварительно их обработав типа
...
exten => s,n,Set(AnsweredPeer=${CUT(BRIDGEPEER,/,2)})
exten => s,n,Set(AnsweredPeer=${CUT(AnsweredPeer,-,1)})
...
...
exten => s,n,GoToIf($["${DIALEDPEERNUMBER}x" != "x"]?DPNPresent)
exten => s,n,Set(DIALEDPEERNUMBER=${CUT(MEMBERINTERFACE,/,2)})
exten => s,n(DPNPresent),n,NoOp("No DIALEDPEERNUMBER present...")
...
[macro-StoreCLID]

exten => s,1,NoOp(Answered is = ${DIALEDPEERNUMBER})
exten => s,n,Set(DB(CLIDT/${DIALEDPEERNUMBER})=${ExternalCLID})


[IncomingCallContext]
...
exten => s,n,Set(__ExternalCLID=${CALLERID(num)})
exten => s,n,Dial(${ALLOP},20,M(StoreCLID))
...
exten => h,1,NoOp(${DB_DELETE(CLIDT/${DIALEDPEERNUMBER})})

[InternalCallsContext]

exten => _X,1,Set(TransferredCLID=${DB_DELETE(CLIDT/${CALLERID(num)})})
exten => _X,n,GotoIf($[ "x${TransferredCLID}" = "x"]?ClearCall)
exten => _X,n,Set(CALLERID(num)=${TransferredCLID})
exten => _X,n(ClearCall),.....



При использовании очередей также можно использовать этот метод, но надо доработать  macro-StoreCLID на предмет анализа не только DIALEDPEERNUMBER, а MEMBERINTERFACE, или, в в случае перехвата - BRIDGEPEER. Только предварительно их обработав типа

...
exten => s,n,Set(AnsweredPeer=${CUT(BRIDGEPEER,/,2)})
exten => s,n,Set(AnsweredPeer=${CUT(AnsweredPeer,-,1)})

...
...
exten => s,n,GoToIf($["${DIALEDPEERNUMBER}x" != "x"]?DPNPresent)
exten => s,n,Set(DIALEDPEERNUMBER=${CUT(MEMBERINTERFACE,/,2)})

exten => s,n(DPNPresent),n,NoOp("No DIALEDPEERNUMBER present...")
...

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