Queues with hotdesk agents login voicemail AEL 1.4

This currently has support for
Hot Desking
Agent Voicemail
Dynamic Agent Voicemail Mapping to Phone for MWI support
Agents stay logged in through asterisk reload or restart

Here is what I've come up with and is working for me. I'm sure there are improvements that can/will be made and I hope to update this as I make them.
I plan to add realtime and make this post more pretty. But for now, its here for what it is worth.
I got started with comments in the script but it was taking too long. Maybe later.

I've attached this whole post as a file because of ael formatting. So open the attached file for easier reading.
Image


I started from the example given in the doc dir of the source code and worked from there. It didn't support hot desking.
I used parts fro the other agents with out channels wiki pages.
A problem I found is that regular expression extraction using Set(from_channel=$[ "${CHANNEL}" : "+(.+)\[-\]\[+-\]+$" ]) is broken if done in AEL.
So I used the parser to generate the flat extensions.conf.aeldump file using aelparse -w -d -q.
Note that I put the extensions.ael in /etc/asterisk/ael/ so I can cd to that dir, and run aelparse -w -d -q after each change to the ael file.
I then #included the dump file in extensions.conf

Important parts from extension.conf
[globals]
COMPANY_CONTEXT=mycompany         ; !!! This value needs to be manually changed/set in sip.conf for mailboxes, voicemail.conf the context for mailboxes, and switch => Realtime statements in this file. Grep in other configs for the old value!
queue_by_exten_6010=Queue_ONE
queue_by_exten_6020=Queue_TWO
Queue_ONE_exten=6010
Queue_TWO_exten=6020

DOLLAR=$

#include ael/extensions.conf.aeldump

[internal_devices] ; non agent phones enter here
include => internal
include => queue_dial_plan ; _60XX & _!Queue extensions for queues, _6XXX for agents
include => match_outbound

[macro-edit_audio_file]
exten => s,1,Set(File_Record=$ARG1)
exten => s,n,Background(vm-intro)
exten => s,n,Record(${File_Record}_tmp.ulaw)
exten => s,n,Background(recorded)
exten => s,n,Background(${File_Record}_tmp)
exten => s,n,Background(save-announce-press)
exten => s,n,Background(digits/1)
exten => s,n,Background(to-rerecord-announce)
exten => s,n,Background(digits/2)
exten => s,n,Background(press-3)
exten => s,n,Background(to-cancel-this-msg)
exten => s,n,WaitExten(10,m)
exten => s,n,Goto(3,1)

exten => 1,1,System(/bin/rm /var/lib/asterisk/sounds/${File_Record}.*)
exten => 1,n,System(/bin/mv /var/lib/asterisk/sounds/${File_Record}_tmp.ulaw /var/lib/asterisk/sounds/${File_Record}.ulaw)
exten => 1,n,Return()
exten => 2,1,Goto(s,1)
exten => 3,1,System(/bin/rm /var/lib/asterisk/sounds/${File_Record}_tmp.ulaw)
exten => 3,n,Return()
exten => h,1,System(/bin/rm /var/lib/asterisk/sounds/${File_Record}_tmp.ulaw)


sip.conf example entries
[AP_1001]
type=friend
host=dynamic
secret=1234
context=agent_devices
mailbox=1001@mycompany_agent_phones
callerid=Agent Phone <1001>

[dsk_5555]
type=friend
host=dynamic
secret=1234
context=internal_devices
mailbox=5555@mycompany
callerid=My Desk <5555>



voicemail.conf example parts
[mycompany] ; this should match the global var COMPANY_CONTEXT is set to in extensions
; put all users voicemail defs in this context.
5555 => 1234,My Name,myemail@example.com,,

[mycompany_agents]
6101 => 1234,Agent Name,agentemail@example.com,,

[mycompany_agent_phones]
; these are just placeholders for mapping  agent voicemails to phones. /var/spool/asterisk/voicemail/mycompany_agent_phones must be created manually
1001 => 892143432423


ael/extensions.ael
//============= The Contexts referenced from the queues.conf file

// context name same as queue name defined in queues.conf
context Queue_one {

    // while in the queue, a customer can press 9 to leave a VM for the Queue mailbo
    9 => Voicemail(${EVAL(${DOLLAR}{${CONTEXT}_exten})}@${COMPANY_CONTEXT}_agents,b) ;
    99999 => {
        //(re)record queue greeting
        &edit_audio_file(custom/${CONTEXT}_greeting) ;
        goto s,1 ;
    }

    s => {
        Background(custom/${CONTEXT}_greeting);
        WaitExten(2);
        // check if a queue name has already been prefixed on the caller id name, 
        // assumes there is never a : in original CID name
        Set(orig_cid_name=${CUT(CALLERID(name),:,2)}) ;
        if ( "x${orig_cid_name}" = "x" )
        {
            // use ${CALLERID(name) since ${orig_cid_name} is empty
            Set(CALLERID(name)=${CONTEXT:7}:${CALLERID(name):5});
        } else {
            // use ${orig_cid_name} since it already has the orig CID name.
            Set(CALLERID(name)=${CONTEXT:7}:${orig_cid_name});
        }

        // if you want to do Queue escalation, set QUEUE_MAX_PENALTY
        // Set(QUEUE_MAX_PENALTY=10)

        // enter queue allowing the destination agent to transfer the call. 
        //NOTE: I don't think the "t" this has any effect since the agent is 
        //      dialed through Local then Dial command witch will determine transfer capabilities.
        //      not to mention the phones built in capabilities to transfer.
        Queue(${CONTEXT}|t);

        // Queue escalation example continued
        // Set(QUEUE_MAX_PENALTY=20)
        // Queue(${CONTEXT}|t);
        // Set so all agents are tried
        // Set(QUEUE_MAX_PENALTY=0)
        // Queue(${CONTEXT}|t);
        // not sure what effect this has since the call is about to be hung up, 
        // other than to see it in the logs. maybe the cdr?..
        Set(CALLERID(name)=Empty_${CONTEXT});
    }
}

context Queue_two {

    9 => Voicemail(${EVAL(${DOLLAR}{${CONTEXT}_exten})}@${COMPANY_CONTEXT}_agents,b) ;
    99999 => {
        &edit_audio_file(custom/${CONTEXT}_greeting) ;
        goto s,1 ;
    }

    s => {
        Background(custom/Queue_two_greeting);
        WaitExten(2);
        Set(orig_cid_name=${CUT(CALLERID(name),:,2)}) ;
        if ( "x${orig_cid_name}" = "x" )
        {
            Set(CALLERID(name)=:${CALLERID(name):5});
        } else {
            Set(CALLERID(name)=two:${orig_cid_name});
        }

        Queue(${CONTEXT}|t);
        Set(CALLERID(name)=Empty_${CONTEXT});
    }
}


//================= Agents Making calls

context agent_devices
{
    _!. =>    {
        Set(from_channel=$[ "${CHANNEL}" : "+(.+)\[-\]\[+-\]+$" ]);
        if( ${DB_EXISTS(AGENT/channelHasAgent/${from_channel})} )
            Set(from_agent=${DB(AGENT/channelHasAgent/${from_channel})});
        else
            goto queues-loginout,${EXTEN},1 ;
        Set(GROUP(agents)=${from_agent});
        NoOp(mygroupcount: ${GROUP_COUNT(${from_agent}@agents)}) ;
        Set(CALLERID(num)=${from_agent});
        Set(CALLERID(name)=${DB(AGENT/${MACRO_EXTEN}/name)});
        if ( ${LEN(${CALLERID(name)})} = 0 )
            Set(CALLERID(name)=Call Center Agent) ;
        goto agent_call_plan,${EXTEN},1 ;
    }
}

context agent_call_plan
{
    includes {
        queues-loginout;
        queue_dial_plan;
        internal;
    }

}

//================= Agents Log In and Out 


context queues-loginout
{
    *98 => {
        Answer();
        Set(TIMEOUT(response)=3);
        if ( "x${from_agent}" != "x" )
        {
            //Playback(ask_logout_agent) ;
            SayDigits(${from_agent}) ;
            //Read(logout) ;
            Set(queue-announce-success=1);
            goto queues-manip,O${from_agent},1 ;
        } else {
            Read(from_agent,jedi-extension-trick);
            VMAuthenticate(${from_agent}@${COMPANY_CONTEXT}_agents,s);
            Set(queue-announce-success=1);
            goto queues-manip,I${from_agent},1;
        }
    }
    *95 => { // Pause
        if ( "x${from_agent}" = "x" )
            goto *98,1 ;
        Answer();
        Wait(1);
        &queue-addremove(P,${from_agent},"","");
    }
    *96 => { // UnPause
        if ( "x${from_agent}" = "x" )
            goto *98,1 ;
        Answer();
        Wait(1);
        &queue-addremove(U,${from_agent},,);
    }
    *97 => { // check voicemail
        if ( "x${from_agent}" = "x" )
            goto *98,1 ;
        Answer();
        Wait(1);
        VoicemailMain(${from_agent}@${COMPANY_CONTEXT}_agents,s);
    }

    i => {
        if ( "x${from_agent}" = "x" )
            goto *98,1 ;
        else
            Playback(pbx-invalid) ;
    }
}

context queues-manip {

    // My Name
    _[IO]6101 => &queue-addremove(${EXTEN:0:1},${EXTEN:1},My Caller ID name,Queue_one+10:Queue_two+10);

}

macro queue-success(IO_action)
{
    if( ${queue-announce-success} > 0 )
    {
        switch(${IO_action})
        {
        case I:
            Playback(agent-loginok);
            Hangup();
                        break;
        case O:
            Playback(agent-loggedoff);
            Hangup();
                        break;
        }
    }
}


//The queue-addremove macro is defined in this manner:

macro queue-addremove(action,agent,agent_name,queues)
{
    switch(${action})
    {
     pattern [IO]:  // Login
        
        if ( "${action}" = "I" )
        {
            Set(DB(AGENT/channelHasAgent/${from_channel})=${agent}) ;
            Set(DB(AGENT/${agent}/onChannel)=${from_channel}) ;
            Set(DB(AGENT/${agent}/name)=${agent_name}) ;
            Set(dev_mailbox=${SIPPEER($[ "${CHANNEL}" : "\[+/\]+/(.+)\[-\]\[+-\]+" ]:mailbox)}) ;
            System(/bin/ln -s /var/spool/asterisk/voicemail/${COMPANY_CONTEXT}_agents/${agent} /var/spool/asterisk/voicemail/${CUT(dev_mailbox,@,2)}/${CUT(dev_mailbox,@,1)}) ;
        } else {
            Set(agentchan=${DB(AGENT/${agent}/onChannel)});
            Set(oldval=${DB_DELETE(AGENT/channelHasAgent/${agentchan})});
            DBdeltree(AGENT/${from_agent});
            Set(dev_mailbox=${SIPPEER($[ "${agentchan}" : "\[+/\]+/(.+)" ]:mailbox)}) ;
            System(/bin/rm /var/spool/asterisk/voicemail/${CUT(dev_mailbox,@,2)}/${CUT(dev_mailbox,@,1)}) ;
        }
        Set(i=1) ;
        while ( 1 ) {
            Set(queue=${CUT(queues,:,${i})}) ;
            Set(queuename=${CUT(queue,+,1)}) ;
            Set(penalty=${CUT(queue,+,2)}) ;
            Set(penalty=$[ ${LEN(${penalty})} = 0 ]:0:${penalty}) ;
            if ( ${LEN(${queuename})} = 0 )
                break;
            if ( "${action}" = "I" )
                AddQueueMember(${queuename},Local/${agent}@queue_calling_agents,${penalty});
            else
                RemoveQueueMember(${queuename},Local/${agent}@queue_calling_agents);
            Set(i=$[ ${i} + 1 ]);
        }
        &queue-success(${action});
        break;
    case P:  // Pause
        PauseQueueMember(${queuename},Local/${agent}@queue_calling_agents);
                break;
    case U:  // Unpause
        UnpauseQueueMember(${queuename},Local/${agent}@queue_calling_agents);
                break;
    default: // Invalid
        Playback(invalid);
                break;
    }
}


//=======================================================
//|    Controlling The Way Queues Call the Agents       |
//=======================================================

context queue_calling_agents
{
    _! => &callagent(no_vm);
}

context queue_dial_plan
{
    // Goto queue by extension number
    _60XX => Goto(${EVAL(${DOLLAR}{queue_by_exten_${EXTEN}})},s,1) ;
    6010 => goto Queue_one,1 ;
    _Queue_. => goto ${EXTEN},s,1 ;
    _6XXX => &callagent(w_vm);
}

macro callagent(use_vm)
{
    Set(device=${DB(AGENT/${MACRO_EXTEN}/onChannel)}) ;
    if ( "${use_vm}" = "no_vm")
    {
        NoOp(GC agnt:${GROUP_COUNT(${MACRO_EXTEN}@agents)} - ${GROUP_COUNT(${MACRO_EXTEN}@agents_vmail)}) ;
        if ( ${GROUP_COUNT(${MACRO_EXTEN}@agents)} - ${GROUP_COUNT(${MACRO_EXTEN}@agents_vmail)} = 0 )
        {
            Set(GROUP(agents)=${MACRO_EXTEN});
            Dial(${device}|300|t);
            switch(${DIALSTATUS})
            {
            case BUSY:
                Busy();
                break;
            case NOANSWER:
                Set(queue-announce-success=0);
                goto queues-manip|O${MACRO_EXTEN}|1;
            default:
                Hangup();
                break;
            }
        }
        else
        {
            Busy();
        }
    } else {
        NoOp(${GROUP_COUNT(${MACRO_EXTEN}@agents)} - ${GROUP_COUNT(${MACRO_EXTEN}@agents_vmail)}) ;
        if ( ${GROUP_COUNT(${MACRO_EXTEN}@agents)} - ${GROUP_COUNT(${MACRO_EXTEN}@agents_vmail)} = 0 )
        {
            NoOp(device (${device}) has / ?: $[ "x${device}" != "x" ]) ;
            if ( "x${device}" != "x" )
            {
                Set(GROUP(agents)=${MACRO_EXTEN});
                Dial(${device}|20|t);
                NoOp(Dialstatus:${DIALSTATUS}) ;
                Set(GROUP(agents_vmail)=${MACRO_EXTEN}) ;
                if ( "${DIALSTATUS}" == "BUSY" )
                {
                    Voicemail(${MACRO_EXTEN}@${COMPANY_CONTEXT}_agents,b);
                } else {
                    Voicemail(${MACRO_EXTEN}@${COMPANY_CONTEXT}_agents,u);
                }
            } else {
                Voicemail(${MACRO_EXTEN}@${COMPANY_CONTEXT}_agents,u);
            }
        } else {
            Voicemail(${MACRO_EXTEN}@${COMPANY_CONTEXT}_agents,b);
        }
    }
}


This currently has support for
Hot Desking
Agent Voicemail
Dynamic Agent Voicemail Mapping to Phone for MWI support
Agents stay logged in through asterisk reload or restart

Here is what I've come up with and is working for me. I'm sure there are improvements that can/will be made and I hope to update this as I make them.
I plan to add realtime and make this post more pretty. But for now, its here for what it is worth.
I got started with comments in the script but it was taking too long. Maybe later.

I've attached this whole post as a file because of ael formatting. So open the attached file for easier reading.
Image


I started from the example given in the doc dir of the source code and worked from there. It didn't support hot desking.
I used parts fro the other agents with out channels wiki pages.
A problem I found is that regular expression extraction using Set(from_channel=$[ "${CHANNEL}" : "+(.+)\[-\]\[+-\]+$" ]) is broken if done in AEL.
So I used the parser to generate the flat extensions.conf.aeldump file using aelparse -w -d -q.
Note that I put the extensions.ael in /etc/asterisk/ael/ so I can cd to that dir, and run aelparse -w -d -q after each change to the ael file.
I then #included the dump file in extensions.conf

Important parts from extension.conf
[globals]
COMPANY_CONTEXT=mycompany         ; !!! This value needs to be manually changed/set in sip.conf for mailboxes, voicemail.conf the context for mailboxes, and switch => Realtime statements in this file. Grep in other configs for the old value!
queue_by_exten_6010=Queue_ONE
queue_by_exten_6020=Queue_TWO
Queue_ONE_exten=6010
Queue_TWO_exten=6020

DOLLAR=$

#include ael/extensions.conf.aeldump

[internal_devices] ; non agent phones enter here
include => internal
include => queue_dial_plan ; _60XX & _!Queue extensions for queues, _6XXX for agents
include => match_outbound

[macro-edit_audio_file]
exten => s,1,Set(File_Record=$ARG1)
exten => s,n,Background(vm-intro)
exten => s,n,Record(${File_Record}_tmp.ulaw)
exten => s,n,Background(recorded)
exten => s,n,Background(${File_Record}_tmp)
exten => s,n,Background(save-announce-press)
exten => s,n,Background(digits/1)
exten => s,n,Background(to-rerecord-announce)
exten => s,n,Background(digits/2)
exten => s,n,Background(press-3)
exten => s,n,Background(to-cancel-this-msg)
exten => s,n,WaitExten(10,m)
exten => s,n,Goto(3,1)

exten => 1,1,System(/bin/rm /var/lib/asterisk/sounds/${File_Record}.*)
exten => 1,n,System(/bin/mv /var/lib/asterisk/sounds/${File_Record}_tmp.ulaw /var/lib/asterisk/sounds/${File_Record}.ulaw)
exten => 1,n,Return()
exten => 2,1,Goto(s,1)
exten => 3,1,System(/bin/rm /var/lib/asterisk/sounds/${File_Record}_tmp.ulaw)
exten => 3,n,Return()
exten => h,1,System(/bin/rm /var/lib/asterisk/sounds/${File_Record}_tmp.ulaw)


sip.conf example entries
[AP_1001]
type=friend
host=dynamic
secret=1234
context=agent_devices
mailbox=1001@mycompany_agent_phones
callerid=Agent Phone <1001>

[dsk_5555]
type=friend
host=dynamic
secret=1234
context=internal_devices
mailbox=5555@mycompany
callerid=My Desk <5555>



voicemail.conf example parts
[mycompany] ; this should match the global var COMPANY_CONTEXT is set to in extensions
; put all users voicemail defs in this context.
5555 => 1234,My Name,myemail@example.com,,

[mycompany_agents]
6101 => 1234,Agent Name,agentemail@example.com,,

[mycompany_agent_phones]
; these are just placeholders for mapping  agent voicemails to phones. /var/spool/asterisk/voicemail/mycompany_agent_phones must be created manually
1001 => 892143432423


ael/extensions.ael
//============= The Contexts referenced from the queues.conf file

// context name same as queue name defined in queues.conf
context Queue_one {

    // while in the queue, a customer can press 9 to leave a VM for the Queue mailbo
    9 => Voicemail(${EVAL(${DOLLAR}{${CONTEXT}_exten})}@${COMPANY_CONTEXT}_agents,b) ;
    99999 => {
        //(re)record queue greeting
        &edit_audio_file(custom/${CONTEXT}_greeting) ;
        goto s,1 ;
    }

    s => {
        Background(custom/${CONTEXT}_greeting);
        WaitExten(2);
        // check if a queue name has already been prefixed on the caller id name, 
        // assumes there is never a : in original CID name
        Set(orig_cid_name=${CUT(CALLERID(name),:,2)}) ;
        if ( "x${orig_cid_name}" = "x" )
        {
            // use ${CALLERID(name) since ${orig_cid_name} is empty
            Set(CALLERID(name)=${CONTEXT:7}:${CALLERID(name):5});
        } else {
            // use ${orig_cid_name} since it already has the orig CID name.
            Set(CALLERID(name)=${CONTEXT:7}:${orig_cid_name});
        }

        // if you want to do Queue escalation, set QUEUE_MAX_PENALTY
        // Set(QUEUE_MAX_PENALTY=10)

        // enter queue allowing the destination agent to transfer the call. 
        //NOTE: I don't think the "t" this has any effect since the agent is 
        //      dialed through Local then Dial command witch will determine transfer capabilities.
        //      not to mention the phones built in capabilities to transfer.
        Queue(${CONTEXT}|t);

        // Queue escalation example continued
        // Set(QUEUE_MAX_PENALTY=20)
        // Queue(${CONTEXT}|t);
        // Set so all agents are tried
        // Set(QUEUE_MAX_PENALTY=0)
        // Queue(${CONTEXT}|t);
        // not sure what effect this has since the call is about to be hung up, 
        // other than to see it in the logs. maybe the cdr?..
        Set(CALLERID(name)=Empty_${CONTEXT});
    }
}

context Queue_two {

    9 => Voicemail(${EVAL(${DOLLAR}{${CONTEXT}_exten})}@${COMPANY_CONTEXT}_agents,b) ;
    99999 => {
        &edit_audio_file(custom/${CONTEXT}_greeting) ;
        goto s,1 ;
    }

    s => {
        Background(custom/Queue_two_greeting);
        WaitExten(2);
        Set(orig_cid_name=${CUT(CALLERID(name),:,2)}) ;
        if ( "x${orig_cid_name}" = "x" )
        {
            Set(CALLERID(name)=:${CALLERID(name):5});
        } else {
            Set(CALLERID(name)=two:${orig_cid_name});
        }

        Queue(${CONTEXT}|t);
        Set(CALLERID(name)=Empty_${CONTEXT});
    }
}


//================= Agents Making calls

context agent_devices
{
    _!. =>    {
        Set(from_channel=$[ "${CHANNEL}" : "+(.+)\[-\]\[+-\]+$" ]);
        if( ${DB_EXISTS(AGENT/channelHasAgent/${from_channel})} )
            Set(from_agent=${DB(AGENT/channelHasAgent/${from_channel})});
        else
            goto queues-loginout,${EXTEN},1 ;
        Set(GROUP(agents)=${from_agent});
        NoOp(mygroupcount: ${GROUP_COUNT(${from_agent}@agents)}) ;
        Set(CALLERID(num)=${from_agent});
        Set(CALLERID(name)=${DB(AGENT/${MACRO_EXTEN}/name)});
        if ( ${LEN(${CALLERID(name)})} = 0 )
            Set(CALLERID(name)=Call Center Agent) ;
        goto agent_call_plan,${EXTEN},1 ;
    }
}

context agent_call_plan
{
    includes {
        queues-loginout;
        queue_dial_plan;
        internal;
    }

}

//================= Agents Log In and Out 


context queues-loginout
{
    *98 => {
        Answer();
        Set(TIMEOUT(response)=3);
        if ( "x${from_agent}" != "x" )
        {
            //Playback(ask_logout_agent) ;
            SayDigits(${from_agent}) ;
            //Read(logout) ;
            Set(queue-announce-success=1);
            goto queues-manip,O${from_agent},1 ;
        } else {
            Read(from_agent,jedi-extension-trick);
            VMAuthenticate(${from_agent}@${COMPANY_CONTEXT}_agents,s);
            Set(queue-announce-success=1);
            goto queues-manip,I${from_agent},1;
        }
    }
    *95 => { // Pause
        if ( "x${from_agent}" = "x" )
            goto *98,1 ;
        Answer();
        Wait(1);
        &queue-addremove(P,${from_agent},"","");
    }
    *96 => { // UnPause
        if ( "x${from_agent}" = "x" )
            goto *98,1 ;
        Answer();
        Wait(1);
        &queue-addremove(U,${from_agent},,);
    }
    *97 => { // check voicemail
        if ( "x${from_agent}" = "x" )
            goto *98,1 ;
        Answer();
        Wait(1);
        VoicemailMain(${from_agent}@${COMPANY_CONTEXT}_agents,s);
    }

    i => {
        if ( "x${from_agent}" = "x" )
            goto *98,1 ;
        else
            Playback(pbx-invalid) ;
    }
}

context queues-manip {

    // My Name
    _[IO]6101 => &queue-addremove(${EXTEN:0:1},${EXTEN:1},My Caller ID name,Queue_one+10:Queue_two+10);

}

macro queue-success(IO_action)
{
    if( ${queue-announce-success} > 0 )
    {
        switch(${IO_action})
        {
        case I:
            Playback(agent-loginok);
            Hangup();
                        break;
        case O:
            Playback(agent-loggedoff);
            Hangup();
                        break;
        }
    }
}


//The queue-addremove macro is defined in this manner:

macro queue-addremove(action,agent,agent_name,queues)
{
    switch(${action})
    {
     pattern [IO]:  // Login
        
        if ( "${action}" = "I" )
        {
            Set(DB(AGENT/channelHasAgent/${from_channel})=${agent}) ;
            Set(DB(AGENT/${agent}/onChannel)=${from_channel}) ;
            Set(DB(AGENT/${agent}/name)=${agent_name}) ;
            Set(dev_mailbox=${SIPPEER($[ "${CHANNEL}" : "\[+/\]+/(.+)\[-\]\[+-\]+" ]:mailbox)}) ;
            System(/bin/ln -s /var/spool/asterisk/voicemail/${COMPANY_CONTEXT}_agents/${agent} /var/spool/asterisk/voicemail/${CUT(dev_mailbox,@,2)}/${CUT(dev_mailbox,@,1)}) ;
        } else {
            Set(agentchan=${DB(AGENT/${agent}/onChannel)});
            Set(oldval=${DB_DELETE(AGENT/channelHasAgent/${agentchan})});
            DBdeltree(AGENT/${from_agent});
            Set(dev_mailbox=${SIPPEER($[ "${agentchan}" : "\[+/\]+/(.+)" ]:mailbox)}) ;
            System(/bin/rm /var/spool/asterisk/voicemail/${CUT(dev_mailbox,@,2)}/${CUT(dev_mailbox,@,1)}) ;
        }
        Set(i=1) ;
        while ( 1 ) {
            Set(queue=${CUT(queues,:,${i})}) ;
            Set(queuename=${CUT(queue,+,1)}) ;
            Set(penalty=${CUT(queue,+,2)}) ;
            Set(penalty=$[ ${LEN(${penalty})} = 0 ]:0:${penalty}) ;
            if ( ${LEN(${queuename})} = 0 )
                break;
            if ( "${action}" = "I" )
                AddQueueMember(${queuename},Local/${agent}@queue_calling_agents,${penalty});
            else
                RemoveQueueMember(${queuename},Local/${agent}@queue_calling_agents);
            Set(i=$[ ${i} + 1 ]);
        }
        &queue-success(${action});
        break;
    case P:  // Pause
        PauseQueueMember(${queuename},Local/${agent}@queue_calling_agents);
                break;
    case U:  // Unpause
        UnpauseQueueMember(${queuename},Local/${agent}@queue_calling_agents);
                break;
    default: // Invalid
        Playback(invalid);
                break;
    }
}


//=======================================================
//|    Controlling The Way Queues Call the Agents       |
//=======================================================

context queue_calling_agents
{
    _! => &callagent(no_vm);
}

context queue_dial_plan
{
    // Goto queue by extension number
    _60XX => Goto(${EVAL(${DOLLAR}{queue_by_exten_${EXTEN}})},s,1) ;
    6010 => goto Queue_one,1 ;
    _Queue_. => goto ${EXTEN},s,1 ;
    _6XXX => &callagent(w_vm);
}

macro callagent(use_vm)
{
    Set(device=${DB(AGENT/${MACRO_EXTEN}/onChannel)}) ;
    if ( "${use_vm}" = "no_vm")
    {
        NoOp(GC agnt:${GROUP_COUNT(${MACRO_EXTEN}@agents)} - ${GROUP_COUNT(${MACRO_EXTEN}@agents_vmail)}) ;
        if ( ${GROUP_COUNT(${MACRO_EXTEN}@agents)} - ${GROUP_COUNT(${MACRO_EXTEN}@agents_vmail)} = 0 )
        {
            Set(GROUP(agents)=${MACRO_EXTEN});
            Dial(${device}|300|t);
            switch(${DIALSTATUS})
            {
            case BUSY:
                Busy();
                break;
            case NOANSWER:
                Set(queue-announce-success=0);
                goto queues-manip|O${MACRO_EXTEN}|1;
            default:
                Hangup();
                break;
            }
        }
        else
        {
            Busy();
        }
    } else {
        NoOp(${GROUP_COUNT(${MACRO_EXTEN}@agents)} - ${GROUP_COUNT(${MACRO_EXTEN}@agents_vmail)}) ;
        if ( ${GROUP_COUNT(${MACRO_EXTEN}@agents)} - ${GROUP_COUNT(${MACRO_EXTEN}@agents_vmail)} = 0 )
        {
            NoOp(device (${device}) has / ?: $[ "x${device}" != "x" ]) ;
            if ( "x${device}" != "x" )
            {
                Set(GROUP(agents)=${MACRO_EXTEN});
                Dial(${device}|20|t);
                NoOp(Dialstatus:${DIALSTATUS}) ;
                Set(GROUP(agents_vmail)=${MACRO_EXTEN}) ;
                if ( "${DIALSTATUS}" == "BUSY" )
                {
                    Voicemail(${MACRO_EXTEN}@${COMPANY_CONTEXT}_agents,b);
                } else {
                    Voicemail(${MACRO_EXTEN}@${COMPANY_CONTEXT}_agents,u);
                }
            } else {
                Voicemail(${MACRO_EXTEN}@${COMPANY_CONTEXT}_agents,u);
            }
        } else {
            Voicemail(${MACRO_EXTEN}@${COMPANY_CONTEXT}_agents,b);
        }
    }
}


Created by: wideser, Last modification: Tue 12 of Jun, 2012 (04:27 UTC) by admin
Please update this page with new information, just login and click on the "Edit" or "Discussion" tab. Get a free login here: Register Thanks! - Find us on Google+