Creating your First IM Application


Now that you have your gateway set up, it would be great to test it and make sure that it works. To do so we will use a simple "Hello World" application.

NOTE

Throughout this chapter we will be building an IM and SMS client for a helpdesk application. This application is already created and can be downloaded. For this application we will need a few additional bits and pieces. In the code for this chapter (found on the accompanying Web site) you will find a Microsoft Access database and the MySQL scripts needed to generate this database. You will need to setup this database inside ColdFusion. We used the data source name 'helpdesk' in our code


Quickly modify the onIncomingMessage function in your im.cfc to look like Listing 32.2.

Listing 32.2. im.cfcModify the onIncomingMessage Function
 <cffunction name="onIncomingMessage">         <cfargument name="CFEvent" type="struct" required="YES">         <!--- Generate and return the message.--->         <cfscript>         msg = structNew();          msg.command = "submit";          msg.buddyID = arguments.CFEvent.data.SENDER;          msg.message = Trim(arguments.CFEvent.data.MESSAGE);                   return msg;          </cfscript>  </cffunction> 

This is a little more advanced than your average "Hello World" application. It will echo any message it receives back to the person who sent it. Now we know that the system works and we can have a conversation with ourselves!

It does however begin to show us why IM and SMS applications are quite hard to write. In essence, the IM client is like a very simple Web page. We have presented our user with the ability to type in anything and press send, like a form with only one text field and a submit button. We have not given them any other guidelines on what the gateway does nor how to use it. We are going to have to accept anything they send to us and make sense of it and to respond intelligently. Taking a text string and turning it into a list of instructions for the server is not as easy as it looks.

Generating IM Messages

Now that we have a conduit for our IM messages, it is time to start adding this new functionality into our application. To get ColdFusion to send an IM message to a user from our existing application, it is almost as easy as coding a <cfmail> tag. By now you should be familiar with the SendGatewayMessage() function:

 <cfscript>  msg = StructNew();  msg.command = "Submit"; msg.message = "Hi there from the all new ColdFusion 7!";  msg.buddyID = "LucasSherwood@jabber.com";  SendGatewayMessage("helpdesk", msg);  </cfscript> 

In this code, there is one new argument being passed to our gateway, the BuddyID and our message is sent.

Now we can send and receive messages, we can move on to more complicated issues and get our ColdFusion application to mimic a real world user on an IM network.

There are two key things that we need to do to get our application IM ready. We need to make sure people can add our Virtual helpdesk to their buddy list and so make sure that we can track the status of all of our helpdesk agents and assign them to tasks when we know that they are free.

Making New Friends

As our users begin to use our application, we would like them to be able to add the Virtual Helpdesk to their list of users. As we are building an internal application we are going to be very open and allow anyone to add the helpdesk to their buddy list. If you wanted to restrict this, you should place some logic in here to either ignore the request and queue it for manual approval or to decline it.

As before, you will need to modify your onAddBuddyRequest function in your im.cfc file, as seen in Listing 32.3.

Listing 32.3. Adding an onBuddyRequest Method
 <cffunction name="onAddBuddyRequest" hint="Requests from others to add the             gateway ID to their buddy list.">         <cfargument name="CFEvent" type="struct" required="YES">         <!--- Return the action decision. --->         <cfset retValue = structNew()>         <cfset retValue.command = "accept">         <cfset retValue.BuddyID = CFEvent.DATA.SENDER>         <cfset retValue.Reason = "Because we are nice!">         <cfreturn retValue>  </cffunction> 

User Status Management

Inside our gateway CFC you may have noticed a method called onBuddyStatus(). This is called when one of the members of our buddy list change their status. We will cache this information in the application scope, so that we can use this in the rest of our application. If we add the following code into our onBuddyStatus function we will have the status of all of our buddies available to the rest of the application:

 <cffunction name="onBuddyStatus" hint="Presence status messages from other users.">   <cfargument name="CFEvent" type="struct" required="YES">   <cflock scope="APPLICATION" timeout="10" type="EXCLUSIVE">     <cfscript>     // Create the status structures if they don't exist.     if (NOT StructKeyExists(APPLICATION, "buddyStatus")) {     APPLICATION.buddyStatus=StructNew();     }     if (NOT StructKeyExists(APPLICATION.buddyStatus, CFEvent.Data.BUDDYNAME)) {                         APPLICATION.buddyStatus[#CFEvent.Data.BUDDYNAME#]=StructNew();   }   // Save the buddy status and timestamp.   APPLICATION.buddyStatus[#CFEvent.Data.BUDDYNAME#].status = CFEvent.Data.BUDDYTATUS;     APPLICATION.buddyStatus[#CFEvent.Data.BUDDYNAME#].timeStamp = CFEvent.Data.TIMESTAMP;    </cfscript>   </cflock> </cffunction> 

You will notice that we have put a <cflock> around this code. This is just in case multiple users change their status at exactly the same time. We don't want to overwrite one change with the other.

The IM Gateway Helper

As with all gateways, there is a helper class that carries out additional tasks that are specific to that gateway type. In the case of IM gateways there are four main areas of responsibility that our helper takes care of.

Buddy List Management

One of the first things we want our application to do when it starts up is to check the status of our helpdesk staff. Typically all of our helpdesk staff will already be buddies in our application but it never hurts to check.

Now our application is starting to grow, it is time to build an Application.cfc file into our application. If you haven't already got one, create an Application.cfc file in your test directory. In our Application.cfc we will add some code that checks our list of users against the buddy list of the IM Gateway and requests authorization to add those users who are not buddies to the list when our application starts using the onApplicationStart() function. To do this we need the addBuddy() helper function.

NOTE

Your application will not automatically see changes in the status of any user on the IM network unless you add them to your buddy list.


Listing 32.4. Application.cfc
 <cffunction name="onApplicationStart" returnType="boolean"> <!--- go and get the list of buddies from the Gateway ---> <cfscript>         helper = getGatewayHelper("Helpdesk");         aBuddyList = helper.getBuddyList(); </cfscript> <!--- go and get the list of all users who can access this system from the DB ---> <cfquery datasource="helpdesk" name="qGetUsers"> SELECT userid,imid,name FROM helpdeskstaff <cfif ArrayLen(aBuddyList) gt 0>         WHERE IMID not in(#ListQualify(ArraytoList(aBuddyList),"'")#) </cfif> </cfquery> <!--- loop over this query and generate buddy list requests ---> <cfloop query="qGetUsers">         <cfset rc =helper.addBuddy(qGetUsers.IMID,qGetUsers.Name,"Helpdesk Staff")> </cfloop> <cfreturn true /> </cffunction> 

The next step is to check the online status of all of our helpdesk staff. To do this we will need to poll their status one by one using the getBuddyInfo() helper function. This will also need to go into our onApplicationStart function in our Application.cfc file:

 <cfscript> // go and get the buddy list again as it now may have new users in it aBuddyList = helper.getBuddyList(); for(i=1;i lte arrayLen(aBuddyList);i=i+1) {   // store this status in an applicaiton var so the rest of the applicaiton has access to it   // Create the status structures if they don't exist.   if (NOT StructKeyExists(APPLICATION, "buddyStatus")) {   APPLICATION.buddyStatus=StructNew();   }   if (NOT StructKeyExists(APPLICATION.buddyStatus, aBuddyList[i])) {     APPLICATION.buddyStatus[#aBuddyList[i]#]=StructNew();   }   //get the status for this buddy   status = helper.getBuddyInfo(aBuddyList[i]);   //find the node in the array that contains the data that we need   for(j=1;j lte arrayLen(status);j=j+1) {     if(status[j].BuddyListType eq "BUDDY_LIST")     {       // save the status data       APPLICATION.buddyStatus[#aBuddyList[i]#].status = status[j].BUDDYSTATUS;       APPLICATION.buddyStatus[#aBuddyList[i]#].timeStamp = status[j].BUDDYSTATUSTIME;     }   } } </cfscript> 

In our application we abstracted this functionality into its own function in the Application.cfc file so that we can reuse it elsewhere if needed. We now know enough information that we can go and build an application that takes helpdesk requests and IMs them to an available support staff member. This is done in index.cfm.

Gateway Status Management

It would be nice to add some more functionality to our application so that the users in our organization could see at a glance if their helpdesk staff where busy or not, but to protect our helpdesk staff, we are not going to publish their IM details directly. Instead, we are going to integrate their status into that of our gateway. The Virtual Helpdesk should reflect whether the agents are busy or free.

The gateway helper has a method, setStatus() that we will be using to very simply show our busy/free status.

We will loop over the application scope cache of our agents' status and use this to set the gateway's presence status to reflect our helpdesk team.

In your im.cfc modify the onBuddyStatus() function to include the following code:

 <cfloop collection="#Application.BuddyStatus#" item="key">         <cfif NOT StructKeyExists(stStatus, APPLICATION.buddyStatus[key].Status)>                 <cfset stStatus[APPLICATION.buddyStatus[key].Status] = structNew()>         </cfif>         <cfset stStatus[APPLICATION.buddyStatus[key].Status][key] = true> </cfloop> <!--- now work out what status to put us in ---> <cfif structKeyExists(stStatus,"ONLINE")>         <cfset newstatus = "ONLINE"> <cfelseif structKeyExists(stStatus,"AWAY")>         <cfset newstatus = "AWAY"> <cfelse>         <cfset newstatus = "NA"> </cfif> <cfset helper = getGatewayHelper("Helpdesk")> <cfset ret=helper.setStatus(newstatus, "")> 

As the status of our gateway should be updated whenever one of our helpdesk team changes their status, it will go into the onBuddyStatus() event of our gateway. An advancement of this would be to make it an application level function so that it also could be called when the application starts to set our initial status.

NOTE

Depending on your IM gateway type you will have different options for the status of your gateway. Be sure to check the docs to make sure that the status you select is supported.


TIP

You can always use the setStatus() helper method to add a custom away message to your status to help convey additional information to the users of our application.


Another nice thing we could do for our normal Web based users would be to tell them the status of the helpdesk when they submit their issue. In our application our users log issues via a plain old Flash Form on your regular intranet (this is in index.cfm) and to keep things simple, we will leave it that way. However, it would be great to advertise the status of our helpdesk staff on this page so that users who do not have an IM client are in the loop.

This could not be easier; our Gateway helper can do this for us. You may want to use a <cfswitch> statement to present this information to the user a little better.

On our issue logging page, index.cfm we have the following code to show our users the status of our helpdesk when they log issues:

 <cfset helper = getGatewayHelper("Helpdesk")> <cfset helpDeskStatus=helper. getStatusAsString ()> <cfoutput>the helpdesk is currently #helpDeskStatus#.</cfoutput> 

There are several other Gateway Status helpers, such as isOnline() that you many want to look at using elsewhere in your application. Have a look at the ColdFusion Docs for more details.

Permission Management

Once your application is up and running you may want to start controlling who can see the status of our Virtual Helpdesk and who can not. The IM server itself maintains two lists of users, the permit list and the deny list. These two lists on their own do not control how the IM server will respond, they are just lists. In addition to filling either of these lists, we must tell the IM server to change its default behavior.

By default, the server is set to permit all users to view our status and to disregard the permit and deny list. We can change this using the setPermitMode() helper. There are three modes we can set the gateway to: PERMIT_ALL, PERMIT_SOME and DENY_SOME. The combinations here are straightforward. If permit_some is used, the Permit list is used to specify which users can see the status of the gateway and if the deny_some condition is set then all users on the deny list will be unable to see the status of our gateway.

In the case of our application we will not be using these. For more details of the specifics of these methods, please refer to the ColdFusion Docs.

Gateway Configuration

Beyond the normal helper methods, there are a few that provide statistics on the gateway itself:

  • GetName() This returns the username of the IM user.

  • GetProtocolName() This returns the IM protocol (JABBER for XMPP, or SAMETIME).

  • GetNickName() This returns the Display Name of the gateway (the nickname).

  • setNickName() This sets the nickname of the gateway.

  • numberOfMessagesSent() This returns the number of messages received by the gateway since it was started.

  • numberOfMessagesReceived() This returns the number of messages received by the gateway since it was started.

While the last two don't explicitly have a use in our application, you may want to build a nice little stats logger to show you just how much usage your IM helpdesk is getting.



Advanced Macromedia ColdFusion MX 7 Application Development
Advanced Macromedia ColdFusion MX 7 Application Development
ISBN: 0321292693
EAN: 2147483647
Year: 2006
Pages: 240
Authors: Ben Forta, et al

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net