Building An IM Bot – Part II

As should be clear by Part I of this post, creating a Google Talk IM bot requires the following three items:

  • An installed ColdFusion gateway type that is compatible with the Google Talk network. As Google Talk is built on top of Jabber which is XMPP based, the XMPP gateway that comes with ColdFusion fits the bill.
  • A configuration file specifying the Google Talk account name and password to be used by the bot.
  • A CFC file to actually process and respond to inbound IM messages.

Obviously, any IM bot needs an IM user account, so the first thing you’ll need to do is obtain a Google Talk account. Google Talk uses GMail addresses and passwords, so obtain a new GMail account if needed, or use any unused account (don’t use an account that you yourself will be using with Google Talk, the same account cannot be logged in twice of course, so the bot needs its own account).
Next you’ll need to save that account information into a configuration file. Gateway config files are typically stored in /gateway/config under the ColdFusion root (c:cfusionmx7gatewayconfig on a Windows standalone installation, c:jrun4serverscfusioncfusion-earcfusion-warweb-infcfusiongatewayconfig on the default ColdFusion instance on a Windows multi-server installation), although they could be stored elsewhere too. That folder may contain a sample XMPP configuration file named xmpp.cfg which you may copy and modify. Your configuration file should contain (at a minimum) the following entries (obviously setting userid and password to your GMail account information):
resourceName=ColdFusion MX 7

Next you need the CFC that will respond to inbound requests. At a minimum you need two methods in your CFC, onIncomingMessage and onAddBuddyRequest.
All instant messages sent to your bot are routed to a method named onIncomingMessage. This method is the one that actually receives all inbound messages, and this is where you’d process user requests, generating responses if needed.
Here is a simple example:

All methods invoked by gateways receive a single argument, a CFEvent structure (the contents of which vary based on the gateway type). In this example, two local variables are created containing values extracted from the CFEvent structure, message is the actual text sent by the user, and originatorID is the sender name.
Typically your bot would do some processing based on the contents of message, but this simple example just echoes the content back to the sender. A return structure is created, and two values are set, BuddyID is set to originatorID (so that the message is sent back to the sender), and Message contains a string echoing the received message.
And that is all that is needed. The return structure is returned by the tag, and the echo will be sent back to the sender.
That’s onIncomingMessage. Next comes onAddBuddyRequest. When you add a user to your own IM buddy list, the network sends a message to that user asking them to accept or deny the request. If accepted you’ll be able to see when that user is online and will be able to send him or her messages, and if denied then you’ll not be able to see online status, and you may not even be able to send messages. When a user adds your bot as a buddy, the server will ask it to accept or decline the request. Obviously, these requests must be handled programmatically (as there is no actual user), and so these are routed to a CFC method named onAddBuddyRequest. This method can always return an accept response, or can conditionally accept or decline based on some code (maybe a database lookup, or some password or code provided, and so on).
Here is an example:

Once again, onAddBuddyRequest receives a CFEvent structure. This method must respond to the network either accepting or denying the request. Here a return structure is created. Command is set to accept, accepting the request (set it to decline to deny the request). BuddyID is the name of the user being accepted, and Reason is a welcome message that may be sent to the user (depending on the network and IM client being used). And like before, the return structure is then returned using the tag.
Other methods are supported too. And best practices dictate that every method be present in your CFC, even if they are not all used. So every IM bot CFC you create should probably contain the following (even if the methods are all empty):

The CFC can be saved anywhere on your server. The default path for gateway CFC files is /gateway/cfc under the ColdFusion root (c:cfusionmx7gatewaycfc on a Windows standalone installation, c:jrun4serverscfusioncfusion-earcfusion-warweb-infcfusiongatewaycfc on the default ColdFusion instance on a Windows multi-server installation).
With the config file and CFC saved, you can now register the new gateway instance. Here are the steps needed:

  1. Open the ColdFusion Administrator.
  2. Go to the Event Gateways, Settings screen, and make sure that Enable ColdFusion Event Gateway Services checkbox is checked.
  3. Next, go to the Event Gateways, Gateway Instances screen.
  4. Use the form at the top of the screen to add your new gateway instance. Start by specifying a unique Gateway ID.
  5. In the Gateway Type field select XMPP – XMPP Gateway.
  6. In the CFC Path field specify the path to your gateway CFC file.
  7. In the Configuration File field specify the path to your gateway configuration file.
  8. To have your gateway start automatically upon ColdFusion server start, set Startup Mode to Automatic, otherwise set this field to Manual.
  9. And finally, click the Add Gateway Instance button to save your new gateway instance.

To start the gateway, click the green Start button in the gateway Action column. The status will change to Starting, and then Running. And once running, your Google Talk IM bot will be ready to receive and respond to requests.
But what if the bot won’t start? The Debugging & Logging, Log Files screen contains a file named eventgateway.log (this file will be created the first time event gateways are used). You can inspect this log file to determine what your gateway is doing and what errors it may have thrown.
And with that, you are all set to create a Google Talk IM bot. In a subsequent post we’ll look at other IM networks, and advanced IM bot functionality.

14 responses to “Building An IM Bot – Part II”

  1. Raymond Camden Avatar
    Raymond Camden

    Why not share the CFC for your googlebot?

  2. Raymond Camden Avatar
    Raymond Camden

    You have a bug in your code. It isn’t:
    <cfset var>
    <cfset var originatorID=CFEvent.originatorID>

  3. Ben Forta Avatar
    Ben Forta

    Thanks Ray, I fixed that.
    And yes, I will post that code, I have quite a bit more I want to post on the subject, starting with other IM networks and IM helper functions. More to follow.

  4. Michael Dawson Avatar
    Michael Dawson

    I am sure that, by now, many people have added the cfdocs "buddy" to their Google Talk buddy list. Is there anyway you can programmatically retrieve a list of those buddies?
    For example, could you write a function that returns a count of buddies if I send "show buddy count" to cfdocs?
    Also, does Google Talk have a "history" of interactions (not necessarily chat logs) between cfdocs and its buddies, or do you need to log the interactions within your gateway?
    In other words, can Google Talk tell you how many times I sent an IM to cfdocs, or when I added cfdocs to my buddy list?

  5. Michael Dawson Avatar
    Michael Dawson

    Never mind. I found part III of the IM bot discussion. It answered all of my questions.

  6. Anthony Avatar

    I keep all my ports locked down on my server, is 5222 the only one i would need to have opened?

  7. David Droddy Avatar
    David Droddy

    I am working on CFMX7 but could not find the Event Gateways page in the Administrator–so, I went into the Administrator directories to see if I could force my browser to open the pages. I found the admin pages and pointed my browser to /administrator/eventgateway/index.cfm. I got the following error:
    Next, I tried /administrator/eventgateway/gateways.cfm
    This page loads, but there are no predefined Gateway Types.
    Can anyone help me figure out what’s going on here?

  8. since1968 Avatar

    All three articles in the series were excellent; thanks for posting.
    One thing I haven’t grasped: how do I "push" data to an event gateway? For example, if I have a component "Orders" with the method "add", I’d like to invoke a method in my gmail CFC every time an order is added. That way I could send an alert to google talk/ichat when someone places an order.
    Is this feasible?

  9. since1968 Avatar

    OK, answering my own question you can use sendGatewayMessage, called from any CFC, to broadcast.

  10. Zimbie Avatar

    Every heard of zimbie…

  11. Niall Avatar

    @David Droddy
    Just thought I’d add a response to your question about the error:
    I know it’s not timely but it happened to me also, and when ‘googled’, the only result was Ben’s

  12. Phillip Gagnon Avatar
    Phillip Gagnon

    I followed your tutorial ver batum several times to no avail. I copied your code, and replaced the nessicary values (username, password, etc) and I cannot get the service to start. I do not get any error message, it just says "starting." It never gets past that.
    Any thoughts?

  13. Phillip Gagnon Avatar
    Phillip Gagnon


  14. Ben Forta Avatar
    Ben Forta

    There is a .jar file in CF7 that was updated at one point, I believe it is smack.jar, and the newer one solved that problem. I am not sure where the updated .jar file is anymore though (you may be able to use the one from CF8, but I am not suggesting you do that without a goo backup and thorough testing).
    — Ben

Leave a Reply