Creating an AIM Lite Plugin
by Doug Schwartz
March 21, 2007
Introduction
In my last article, "Creating an AIM Plugin in C# with the .NET Framework," I discussed how you can create a simple plugin in C# using the Microsoft .NET framework. That plugin let the user translate their message using a scheme where letters are shifted 13 places--"a" becomes "n" and so on. What that plugin really demonstrated is how to intercept the instant message (IM) before it is sent by the user, and do whatever you want with the text.
But what if you don't know C# or the Microsoft Common Object Model (COM) and want to create a plugin? AOL has a new IM client, AIM Lite, that supports OpenAIM plugins that are written in Boxely markup and JavaScript. This article discusses how to create the same plugin as in the previous article using this technology.
Plugins are typically created from a couple of XML files and a JavaScript file. Deployment is slightly different compared to C# or COM plugins. You deploy an AIM Lite plugin as an AWI file, which is a ZIP file with an .awi extension. AWI files typically contain at least three files:
- A plugin.xml metadata file.
- A content directory with a main.box XML file.
- A JavaScript file with a .js extension that is referenced in main.box.
The simplest structure is something like that in Figure 1:

Figure 1. A typical plugin structure
AWI files are extremely easy to install. Once someone has AIM Lite and the AWI file, they double-click the AWI file, and voila! The plugin is installed.
What Do I Need to Develop a Plugin?
This section has one additional step compared to my last article--step one, download and install AIM Lite. After that step, if you already understand how to get a developer key and the SDK, you can skip to the next section, Creating the Plugin.
Download and install AIM Lite.
Get an account on the AIM Developer website.
Next, get a developer key for your plugin. There are different keys for different stages of development. For now, you need only a developer key. Later on, if you decide to make your plugin available to others, you will need a deployment key. To get a key, go to the AIM Plugin Registration web page and follow the instructions. You will need the key value to run your plugin.
Once you have registered, you can download the SDK. This article leads you through creating a JavaScript plugin,
Scramble. For the complete source for this article, see Resources.
Note: I know I am probably preaching to the choir, but I strongly recommend that you use tools that understand XML and JavaScript. Stubborn me, I was using my old favorite, Xemacs, as just a vanilla text editor and burned hours trying to figure out why my plugin did not work. Of course it was a silly syntax error that I found in minutes when I fired up an editor that understands JavaScript.
Downloading and Installing AIM Lite
- Go to the AIM Lite web page.
- Click the Download Now button.
- Read the license agreement. (Does anyone really read these things?)
- Click Accept.
- Save the
aim-et-setup.exeapplication installer file to your machine.
It should be about 1.6MB. - Navigate to the folder where you saved the application installer file.
- Double-click the application installer file.
Creating the Plugin
We are going to create the plugin in the following order:
- Create the plugin.xml file.
- Create the main.box file.
- Create the main.js file.
For this plugin, let's create the folder C:\Plugins\Scramble.
Creating the plugin.xml File
The plugin.xml file contains a single widget element. This element can contain a number of subelements, but the only required subelement is the uuid, which is a developer or deployment key. Replace YOUR_DEVELOPER_KEY with your developer key in the following code, and save it as C:\Plugins\Scramble\plugin.xml. Feel free to keep, delete, or modify any of the other subelements.
<?xml version="1.0" encoding="utf-8" ?>
<widget
uuid = "{YOUR_DEVELOPER_KEY}"
version = "1.0"
name = "Scramble"
description = "This plugin scrambles text"
vendor = "Me, Myself, and I Inc."
/>
Creating the main.box File
The main.box file contains a single window element.
This element defines the user interface (UI) for the plugin.
A plugin can be visible, invisible (no UI),
or only visible in response to an event.
Our plugin is invisible, and main.box contains the following text:
<?xml version="1.0" encoding="utf-8" ?>
<window
xmlns="http://www.aol.com/boxely/box.xsd"
xmlns:s="http://www.aol.com/boxely/style.xsd"
xmlns:on="http://www.aol.com/boxely/reaction.xsd"
on:constructed="onConstructed();"
on:destroyed="onDestroyed();"
s:height="0"
s:width="0"
hidden="true"
collapsed="true"
floating="true"
>
<code id="main" language="jscript" src="main.js"/>
</window>
You can easily tell our plugin is invisible by the hidden="true" element.
Let's deconstruct this XML line by line.
- Defines the text encoding.
- Creates the opening
windowelement tag. - Creates the default namespace for this
windowelement. Namespaces are a handy way to save a boatload of typing in an XML file. - Creates the
snamespace for thiswindowelement. - Creates the
onnamespace for thiswindowelement. - Identifies
onConstructedas the function to which theconstructedevent notification is sent. This event is fired whenever the plugin is created.onConstructedshould create any resources that are needed for the plugin. - Identifies
onDestroyedas the function to which thedestroyedevent notification is sent. This event is fired whenever the plugin is destroyed.onDestroyedshould release any resources that were created in theonConstructedfunction. - Defines the height of our UI window.
- Defines the width of our UI window.
- Defines whether the window is visible.
- Defines whether the window is collapsed.
- Defines whether the window can be moved.
- Closes the
windowelement attributes. - Defines the JavaScript file where our code resides.
- Closes the
windowelement.
Creating the main.js File
The main.js file contains the following sections:
- Two global variables.
- The
onConstructedfunction that is called when the plugin is created. - The
onDestroyedfunction that is called when the plugin is finished. - The
BeforeImSendevent handler that is called before the message is sent. - The function that scrambles the IM text.
- The function that handles the plugin command.
The first two lines of main.js contain two global variables:
kCommandId, which defines the integer value of our plugin command, and xlate, which defines whether the user wants us to scramble the IM text. This code is as follows:
var kCommandId = 0; var xlate = false;
One of the challenges of developing a plugin in JavaScript is that the existing plugin documentation is written for COM. Let's spend a couple of minutes examining the association between AIM Lite JavaScript objects and the related COM interfaces, so we can use the SDK documentation.
All AIM functionality, including user preferences, is accessed through a session object. This object is an implementation of the IAccSession interface, and is accessed through the scene.paramsDictionary property's valueForKey function using the session key.
Information about a plugin is accessed through a pluginInfo object. This object is an implementation of the IAccPluginInfo interface, and is accessed through the scene.paramsDictionary property's valueForKey function using the pluginInfo key.
Once we have the pluginInfo object, we can create the plugin command using the pluginInfo object's addCommand function, and assign the text we present to the user with the text property of the command.
Event handling begins with a call to the scene.connectObject function. The first parameter is our IAccSession object, and the second parameter is a prefix to be used when defining event callbacks. Our plugin uses the session_ prefix; therefore, the handler for the DAccEvents::BeforeImSend event is session_BeforeImSend.
Adding commands is done as with COM plugins, using the IAccPluginInfo::AddCommand function. To receive commands from the application, the plugin must create a JavaScript object that implements the QueryStatus and Exec methods, and set this object to the commandTarget key of the supplied paramsDictionary.
Here is our onConstructed function:
function onConstructed() {
var dict = scene.paramsDictionary;
var session = dict.valueForKey("session");
var pInfo = dict.valueForKey("pluginInfo");
var cmd = pInfo.addCommand(kCommandId);
cmd.text = "(un)scramble";
scene.connectObject(session, "session_");
dict.setValueForKey(new commandListener(),
"commandTarget");
}
The onDestroyed function is simple; it deletes the association to the session.
function onDestroyed() {
scene.disconnectObject("session_");
}
Our onConstructed function created an association between the session object and session_. Now we use that association to trap the IM message before it is sent in the BeforeImSend event handler. This function checks whether the user has requested to scramble the IM text, and if so, converts the IM to plain text and replaces it with the results of the scramble function.
function session_BeforeImSend(session, imSession, recipient, im) {
if(xlate) {
// Convert IM to plain text, in place
im.ConvertToMimeType("text/plain");
im.Text = scramble(im.Text);
}
}
The gist of our plugin is the function that scrambles the IM text. It changes "a" to "n" and so on.
function scramble(s) {
var output = "";
for(var i = 0; i < s.length; i++) {
var c = s.charAt(i);
switch(c) {
case "a":
output += "n";
break;
// ...
default:
output += c;
break;
}
}
return output;
}
Figure 2 shows an example of the scrambled text.
Can you guess what is says? (Hint: the answer is below, in white text on this white background. Just highlight the bracketed word on the following line and you can see the answer.)
[Dude]

Figure 2. Our plugin in action
Since our JavaScript object need only implement the QueryStatus and Exec methods, we create a null object inline and add the QueryStatus and Exec methods to this object through the function prototype.
The QueryStatus method checks whether the command is that of our plugin. The Exec function toggles whether IM text is scrambled if our plugin command is issued.
function commandListener() {}
commandListener.prototype.QueryStatus=function(id, users) {
return (id == kCommandId) ? true : false;
}
commandListener.prototype.Exec=function(id, users) {
if (id == kCommandId) {
// We have a command, so toggle translation
xlate = !xlate;
}
}
Figure 3 shows what the user sees in the Plugins menu:

Figure 3. The (un)scramble plugin
Creating the AWI file
Zip up plugin.xml, content/main.box, and content/main.js as a ZIP file, and then change the extension to awi, so you end up with scramble.awi. You can get this file below in the Resources section.
Secrets of the Plugin Ninjas
I have discovered a few things about AIM Lite plugins that might interest some folks. For example, did you know that once you install a plugin, you can edit it in place while AIM Lite is running? Neither did I. Navigate to the "%USERPROFILE%\My Documents\Local Settings\Temp\awcache\{GUID}" folder, where GUID is the developer key for the plugin. You should see plugin.xml and the content folder containing main.box and main.js, if that's the name of your JavaScript file. You can change your plugin, and when you are done, update your AWI file.
You can confirm your plugin is installed by looking in a couple of places. The AWI file should be copied to the "%USERPROFILE%\My Documents\My Aim Plugins" folder. If you look in the registry, there should be the HKLM\SOFTWARE\America Online\AIM\Plugins\{GUID} key, where GUID is your developer key.
That is it. If you have any additional tips or tricks you want other plugin developers to know about or ideas for additional plugins, send me email.
Conclusion
Now you understand how to create a simple plugin in JavaScript; congratulations! Of course there is a lot more to Boxely than just what I've shown. Browse through the sample AIM Lite plugin source to get a feel of the possibilities.
Resources
The file scramble.zip contains the complete source code for this article.
If you want to see the scramble plugin at work:
- Install AIM Lite.
- Unzip scramble.zip to get the source files.
- Open plugin.xml.
- Change YOUR_DEVELOPER_KEY to your developer key.
- Zip the files back up.
- Change the file extension to .awi.
- Double-click the file to install the plugin.
References
Here are a number of web pages where you can get further information about AIM Lite and plugins.
- AIM Lite Plugin contains some basic information on plugins and a number of sample plugins.
- Boxely Developer Forums: Ask and answer questions about Boxely.
- The AIM Developer FAQ contains additional information about Open AIM and AIM plugins.
- AOL Developer Resources contains a wide variety of developer resources.
- Gregs blog is a blog written by one of the AOL developers who wrote many of the AIM plugins.
- AIM Developer Key Management is where you go to get keys for your plugin.
