XMPP connection

Good afternoon.

I am working on translating scripts from python to lua for the moby dick system. I know there is some xmpp feature for mobydick (yes? or am I mistaken?) Is there any help or assistance I can inquire about xmpp connector via mobydick, that I can use in my lua scripts to connect to our xmpp system to alert our support people of the incoming calls?

On that similar vein, one of the scripts that also involves the xmpp, is a pin verification script. What connectors or API things can I use, acceptable for MobyDick, in order to recreate the scripts we are currently using? We do have our own APIs that we use, but I want to ensure that this doesn’t go against any policy or program issues that MobyDick may have with “outside” add-ins to increase functionality.

Any guidance with scripting and connecting the xmpp and APIs for additional features would be greatly appreciated.

Hello,

yes, the mobydick features an XMPP-Based API, which is documented here. It can be used to connect “external” applications for real time communication about events like phone calls, chats or similar things - but I’m not sure if it is the right tool for your specific task.

I have a few questions about the problem you’re trying to solve, maybe I can give you a recommendation on how to proceed.

  • What does your workflow look like?
  • What do your current scripts do?
  • Which APIs do they use?

Best Regards,
Jan

  1. Work flow: as in the phone system? The calls come in via main number. Users are prompted for sales, administration or support. If the caller does support they are prompted for their customer pin number, which will verify and pull their customer information. The information will be sent to support. Sales and Admin calls have the number lookup; if number matches in database, provides the receiver with the customer information (mainly name, number, company, vip status).

  2. Our current main scripts are one called check_support_pin.py and notify_cli.py These are very similar in scripting, except the check support, verifies current customer validation and support status and sends the information to the support group. The notify script is similar, minus the pin validation. Both do customer information lookups, then posts that information in xmpp message to the support or caller stating “Call from %r to %r” (callerid, extension) and if the user is a VIP (vip status is in the customer info pull up). check_support_pin script also records calls, and has a second script that archives the call.

  3. The asterisk scripts are using jasonrpc or xmlrpc to speak to our company APIs.

Hi Inxjenn,

I will try to explain some of the features you can use.

Dial plan sends the event to xmpp plugin script


;read 4 digits customer id, send request and continue execution
exten => s,1,Answer()
same => n,Read(customer_id,,4)
same => n,UserEvent(ScriptUser,script: "custom_support",data: "{\"customer_id\":\"${customer_id}\"}")
same => n,Return()

Dial plan sends the HTTP POST request to xmpp plugin script


;read 4 digits customer id, send request and wait for response
exten => s,1,Answer()
same => n,Read(customer_id,,4)
same => n,GoSub(sub_curl,s,1(curl,post,http://localhost/services/pluginscript/custom_support/action,"{\"customer_id\":\"${customer_id}\"}"))
same => n,GoToIf($ "${HASH(curl,HTTP_CODE)}" != "200" ]?skip)
same => n,GoToIf($ "${AGISTATUS}" = "FAILURE" ]?skip)
same => n,Set(CURL_RESPONSE=${HASH(curl,CONTENT)})
;in my example CURL_RESPONSE will look like 0049112233^PLATINUM
same => n,Set(CUSTOMER_NUMBER=${CUT(CURL_RESPONSE,^,1)})
same => n,Set(CUSTOMER_VIP=${CUT(CURL_RESPONSE,^,2)})
same => n,Return()
same => n(skip),Return()

Server plugin script (Advanced/Scripts) handles dial plan requests and notfies third party API


import groovy.json.JsonSlurper
import groovyx.net.http.HTTPBuilder
import static groovyx.net.http.ContentType.JSON
import static groovyx.net.http.Method.*
import net.pascom.ahab.cmd.script.ScriptEvent

import javax.ws.rs.core.*


/*
 Dialplan invokes custom script and waits for response. Sync method
*/
script.onRestPost = { httpRequest ->
   def jsonBody = new JsonSlurper().parseText(httpRequest.getInputStream().getText())
   def customerId = jsonBody.get('customer_id')
   if (!customerId) return Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON).entity('{"error":"customer_id param is missing"}').build()
   def customer = findCustomer(customerId)
   if (!customer) return Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON).entity('{"error":"invalid customer with id $customerId"}').build()
   def customerNumber = customer'number']
   def customerSLA = customer'sla']
   String customerDetails = "$customerNumber^$customerSLA"
   return Response.ok(customerDetails).build();
}

/*
 ScriptUserEvent received from the dialplan. Dialplan does not block. Async method
*/
script.onManagerEvent_ScriptUserEvent = { event ->
    if(event.script!=getName()) return
    def jsonBody = new JsonSlurper().parseText(event.data)
    def customerId = jsonBody.get('customer_id')
    if (!customerId) return
    def customer = findCustomer(customerId)
    if (!customer) return
    pushCustomerDetails(customer)
}

/*
 User REST to fetch details from third part system
*/
def findCustomer(String customerId) {
    def result
    try {
        def client = new HTTPBuilder("http://apitest.com")
        client.request(POST,JSON) { req->
            uri.path = "/api/test"
            uri.query = "customer":customerId]

            response.success = { resp,json ->
                result = json'customer']
            }

            response.failure= { resp ->
                script.log.error " ${resp.statusLine.statusCode} : ${resp.statusLine.reasonPhrase}"
            }
        }
    } catch (Exception e) {
        log.error e.message
    }
    return result
}

/*
Push the data to all xmpp clients with proper subscription
Xmpp client should add the subscription like specified. User need to have supervisor role
<iq id="7HY4b-73" type="get">
  <cmd xmlns="http://www.pascom.net/mobydick" module="event">
  <AddSubscription>
    <Subscription module="script" type="ScriptEvent" scope="supervisor">
      <AttributeFilter name="script" equals="custom_support"/>
    </Subscription>
  </AddSubscription>
</cmd>
</iq>
*/
void pushCustomerDetails(def customer) {
    ScriptEvent event = new ScriptEvent()
    event.setScript(script.getName())
    event.setBody(customer)
    try {
        script.getBean("eventManager").publishEvent('', event)
    } catch (Exception e) {
        log.error "Can't send script event ${e.getMessage()}"
    }
}

The provided code is not tested. I hope those code snippets basically satisfies your requirements.

I look forward your feedback. If you require any further information, feel free to contact me

Kind regards,
Stefan Tosic

Thank you. I will give it a try, and see about translating it to our API and such.

On a related question: how would I apply our AGI settings to mobydick? We have a separate server for AGIs and the customer database. I understand that you’ll probably answer within the script. But I want to ensure that our AGIs and json settings would work without involving installation of other packages necessary, since mobydick is semi-limited on package installation of non-related programs.

Another question: where in the server directories could I find those scripts that are saved via the web interface? like /home/asterisk/script.py And how does Mobydick pull the scripts into the extensions.conf file?

I have created a different dialplan to call the python scripts. I cannot figure out a better way to run those scripts via lua or other dialplans. I have not tested yet. I will hopefully get some testing done today! I will continue to play with scripting to see if I can get another way to get similar functionality later.