AppleScript support in Adium 1.2 and Later
Prior to 1.2 accessing certain features of Adium via AppleScript was either cumbersome or non-intuitive - some people would probably use the word "buggy" to describe it. In Adium 1.2 the AppleScript support has been completely reworked. While initially some features have been removed, overall the new applescript support makes more sense than it used to. While there are a few remaining bugs and some new regressions in the new AppleScript support, once they are cleaned up, the AppleScript support in Adium should be very easy for all to use.
Part of the new support is a new hierarchy of objects. As we shall soon see, this hierarchy makes it easy for us to get information about specific objects in Adium. Prior to this new hierarchy it was much more cumbersome to get information on specific objects in Adium. So let's take a look at how Adium AppleScript objects are now arranged.
Sidenote: The examples in this document can be run using the Script Editor which comes with MacOSX. You can find it in /Applications/AppleScript/. Also if you need more information about Adium's AppleScript support you can look at the Adium AppleScript Dictionary by opening Script Editor and selecting File->Open Dictionary from the menu. Then select Adium from the dictionary chooser. The Dictionary is the best place to go for information on a specific property or how a class is defined.
The Hierarchy
The following diagram helps to visualize what sort of data is available from specific AppleScript classes:
application
|
+---> accounts
| +---> contacts
|
+---> contact groups
| +---> contacts
|
+---> contacts
|
+---> services
| +--->accounts
| +--->contacts
|
+---> windows
|
+---> chat windows
| +---> chats
| +---> contacts
|
+---> chats
| +---> contacts
|
+---> statuses
As we can see from this diagram, all objects in Adium's applescript support are contained by the application object. So let's start there in our exploration of Adium's AppleScript support.
Working with the application class
As with all AppleScript scriptable applications, the base class is the application class. This allows you to send messages to Adium using a tell block. For example:
tell application "Adium" to activate
This will cause Adium to come to become the active application. Or you could use:
tell application "Adium" activate end tell
If you are going to send multiple messages to Adium you need to use the second version and include your commands in-between the tell application "Adium" and the end tell lines.
Properties of the application class
Most of the properties in the application class are standard for every scriptable application so they won't be covered here. However, the application class has one interesting none-standard property - active chat.
Example of using a property of the application class
You can use the active chat property to access the last chat to have focus. We'll see what I mean by "access" later when we talk about working with chat objects. However, for now just be aware that you can do the following:
tell application "Adium" to send the active chat message "Hello World!"
Side note: Those of us with devious minds (you know who you are!) may look at the previous example and think, "Hmm... what if I wrapped this in a loop and sent the same thing repeatedly to the active chat? Can you say IM bomb?" If you do it, please do it with some class (maybe use Chuck Norris facts) and apologize afterwards. :-)
Messages the application class responds to
The application class also responds to some messages that you might not expect. Those messages are:
- go online
- go available
- go offline
- go away
- go invisible
All of these messages are an easy way to set your global status or to get all accounts to go online or offline. Here's an example that will cause all accounts to go online:
tell application "Adium" to go online
In addition, all of these commands offer an optional with message parameter that can be used to set a temporary status message:
tell application "Adium" to go away with message "Stepped away for a bit."
If you want more granular settings for things like a specific status for a specific account or which accounts are online you will need to use the account class.
The application class contains elements that make up the rest of Adium's AppleScript support. The currently available elements of Adium's application class are:
- accounts
- contact groups
- contacts
- services
- windows
- chat windows
- chats
- statuses
We'll be going through each one individually and looking at examples of how to utilize them.
Working with the accounts class
An account in Adium is an object that is part of a specific service (for example AIM or Yahoo!) and has a unique id number and a unique name. It is possible to configure more than one account for a given service, and the Applescript support in Adium allows access to every account independently.
If we reduce the hierarchy diagram to just information about accounts we would get the following:
application
|
+---> accounts
+---> contacts
From this we can see that the account class contains contacts so it is possible to get information about contacts of a specific account using something like:
tell application "Adium" to get every contact of the first account
If we know the account name, we could also get every contact of an account using that name:
tell application "Adium" to get every contact of account "somename"
If we know the id number of the account we could get every contact of the account using the following where in this case 1 is the id number:
tell application "Adium" to get every contact of account id 1
Accounts are contained by the application class so you can do:
tell application "Adium" to get every account
One interesting thing about accounts is that they are not only contained by the application but they are also contained by services. So let's assume you have multiple Yahoo! accounts. You can get every contact of every Yahoo! account by using the fact that the accounts are contained by services:
tell application "Adium" to get every contact of every account of service "Yahoo!"
We'll be talking more about services later.
Properties of the account class
The account class contains several properties that can be read. Those include:
- id - integer - The unique ID assocoated with this account
- name - text - The name of this account
- service - service - the service object this account is registered under
- enabled - boolean - Is the account enabled?
- host - text - The host this account is connected to
- port - integer - The port this account is connected to
The account class also contains several properties that can be both read and written to. Those include:
- display name - text - The display name of the account, a.k.a the Alias. When you type something into a chat, this is the name displayed for you.
- status - status - The current status on the account. Note that this isn't a string, it's an actual status object.
- status type - constant - Setting this only creates a temporary status. Possible constants are offline, available, away and invisible.
- status message - rich text - A message associated with the current status, also sets a temporary status.
- image - TIFF picture - The image associated with this account (Requires Adium 1.2.1 or later)
You can get all of these properties using the properties keyword:
tell application "Adium" to get properties of the first account
Example of using a property of the account class
To set a simple status on a specific account you would most likely want to use the "status type" property. For example the following will set the first account's status to away and create a temporary away message of "I'm not here":
tell application "Adium" set the status type of the first account to away set the status message of the first account to "I'm not here" end tell
Remember that accounts can be referenced by their name which allows for the following:
tell application "Adium" to set status type of account "someaccountname" to away
In both of these examples I used the away constant. The status type property, as described above in the list of properties of the account class accepts several constants like away and available.
If you want to do more complicated things with statuses, you need to utilize the status property of the account class. We'll see this again when we talk about statuses, but for now just be aware that you can do something like:
tell application "Adium" to set status of the first account to the status "Away"
This will set the status of the first account to the the status with the name of "Away".
Messages the accounts respond to
Accounts respond to the same messages as the application:
- go online
- go available
- go offline
- go away
- go invisible
So this is how you can change the status of an account:
tell application "Adium" to tell the first account to go away
Or cause a specific account to go offline:
tell application "Adium" to tell the account "accountname" to go offline
Working with the contact group class
This class was added in Adium 1.3. A contact group in Adium is a container of sorts that contacts can be assigned to. In the contact list contacts can then be grouped based on the group that they are in. Contact groups have no dependancy on specific services or accounts, so it is possible to have contacts from different services and accounts in the same contact group. It is possible for contacts to not be assigned to a user defined contact group, instead they automatically get assigned to a global contact group that can not be accessed via AppleScript. There are issues when a contact is assigned to this global contact group, for example if they are deleted via AppleScript they do not get removed from the contact list. For this and other reasons I recommend that all contacts belong to a user defined contact group.
Contact groups contain contacts so it is possible to do:
tell application "Adium" to get every contact of contact group "Family"
Where "Family" is the name I have given to my contact group.
Properties of the contact group class
The contact group class only defines two properties. They are:
- name - text - The name of this contact group.
- visible - boolean - The visibility of this group.
Note that the visible property is read only while the name property is available for reading or writing.
Example of using a property of the contact group class
You can change the name of a contact group with:
tell application "Adium" to set name of contact group "Family" to "New Family"
However, please note that changing the name of a contact group will require you to change the way you reference the contact group going forward. So for example once the previous example is run, I would need to use contact group "New Family" to reference that contact group from that point forward.
To tell if the contact group is visible you can do:
tell application "Adium" get visible of contact group "New Family"
Messages the contact groups respond to
Contact groups respond to no messages.
Working with the contact class
A contact in Adium is one of the most basic objects. If we look at all the places where contacts show up in the hierarchy diagram we can see what other classes contain contacts:
application
|
+---> accounts
| +---> contacts
|
+---> contacts
|
+---> chats
+---> contacts
From this we can see that contacts are contained in three classes, the application, the accounts and the chats. Being contained by all three of these classes allows for the following examples:
tell application "Adium" to get every contact
This gets every contact regardless of account or service.
tell application "Adium" to get every contact of account "someaccountname"
This gets every contact in a specific account.
tell application "Adium" to get every contact of the first chat
Gets every contact in the in a specific chat (remember that you can have conference chats which can have multiple contacts in them).
Properties of the contact class
Contacts have the following read only properties:
- account - account - The account associated with this contact
- group - contact group - The group associated with this contact (requires 1.3 or later)
- name - text - the Name of this contact
- idle time - integer - The duration this contact has been idle
- status type - constant - The current status of the contact, either offline, available, away or invisible
- status message - rich text - the custom status message for this contact.
Contacts also have two properties that can be read or written to:
- display name - text - a.k.a. the alias of the contact
- notes - text - notes you have added for this contact.
- image - TIFF picture - The image associated with this contact (Requires Adium 1.2.1 or later)
Example of using a property of the contact class
You can add a note to a contact using the notes property:
tell application "Adium" to set the notes of contact "contactname" to "This is my new note"
However, this will overwrite whatever note may have already been stored there. So it is probably best to do:
tell application "Adium" set oldNote to the notes of the first contact of the active chat if oldNote is not missing value then set newNote to oldNote & " This is my new note" else set newNote to "This is my new note" end if set the notes of the contact of the active chat to newNote end tell
Another example may be to get the contact group of a contact:
tell application "Adium" to get the group of contact "contactname"
One thing you will notice is that the group property of the contact class is read only. In order to change the group, you would use the move command:
tell application "Adium" to move contact "contactname" to contact group "contactgroupname"
Messages the contacts respond to
Contacts respond to no messages.
Working with services
A Service in Adium is simply the type of chat protocol. So for example AIM is a service, Yahoo! is a service and Jabber is a service. Services are contained by the application class so you could do the following:
tell application "Adium" to get the first service
Services contain the accounts. So you can get the accounts of a specific service:
tell application "Adium" to get the accounts of the service "Yahoo!"
To see what services are available you could ask for the name of every service:
tell application "Adium" to get the first service
Properties of the service class
Services have two properites:
- name - text - The name of this service
- image - TIFF picture - The icon representing this service (Requires Adium 1.2.1 or later)
Example of using a property of the service class
tell application "Adium" to set theImage to the image of the first service
This example is fairly basic. One might be wondering what you would actually do with the image of the service. One example might be that it could be used in a growl notification.
Messages the services respond to
Services respond to no messages.
Working with windows
A window in Adium could be used for many things including the contact list, preferences, chats, etc. A user can rip away a tab from one chat window and create another window dynamically. Windows are contained by the application class and contain no other classes. You can get every window Adium currently has with:
tell application "Adium" to get every window
Properties of the window class
The following properties are read only:
- name - text - The title of this window
- id - integer - The unique identifier of the window.
- closeable - boolean - Whether the window has a close box.
- minimizable - boolean - Whether the window can be minimized.
- resizable - boolean - Whether the window can be resized.
- zoomable - boolean - Whether the window can be zoomed.
The following properties can be read and written to:
- index - integer - The index of the window, ordered front to back.
- bounds - rectangle - The bounding rectangle of the window.
- minimized - boolean - Whether the window is currently minimized.
- visible - boolean - Whether the window is currently visible.
- zoomed - boolean - Whether the window is currently zoomed.
Example of using a property of the window class
tell application "Adium"
tell window "Contacts"
set visible to false
end tell
end tell
This example hides the contact window. This example also shows how you can use a tell block to instruct different objects to do certain things. This type of a tell block can be used for most (if not all) objects in Adium.
tell application "System Events"
if application "Adium" is not running then error number -128
end tell
tell application "Adium"
tell window "Contacts"
set visible to (not visible)
end tell
end tell
This example makes sure Adium is running and if it is, it toggles the visibility of the "Contacts" window. So if the window is currently hidden, it will become visible or if it is currently visible it will become hidden.
Messages the windows respond to
Windows respond to no messages.
Working with Chat Windows
In Adium chat window is a window that contains chat tabs. The chat window class inherits from the window class. So all of the properties that a window has, a chat window has as well. Because chat windows are contained by the application, you can get every chat window very easily:
tell application "Adium" to get every chat window
Chat windows contain one or more chats. So if you wanted to get every chat you could do:
tell application "Adium" to get every chat of every chat window
However this last example is a little silly because as we will soon see, chats are their own class and contained by the application so it's just easier to do:
tell application "Adium" to get every chat
Properties of the chat window class
Chat windows have no additional properties of their own. They inherit all their properties from the window class.
Example of using a property of the chat window class
tell application "Adium" to set visible of the first chat window to false
This example hides the first chat window.
Messages the chat windows respond to
Chat windows respond to the close message. This can be used to close a chat window programatically. For example:
tell application "Adium" to tell the first chat window to close
Working with Chats
A chat in adium is contained by the application so it is possible to get every chat with:
tell application "Adium" to get every chat
Chats are also contained by chat windows, so you can get every chat of a specific chat window with:
tell application "Adium" to get every chat of the first chat window
Chats contain contact objects so you can get every contact of a specific chat with:
tell application "Adium" to get every contact of the first chat
Properties of the chats class
Chat's offer a few properties all of which are read only:
- name - text - The name of the chat
- id - text - The unique ID of the chat
- account - account - The account associated with the chat
- date opened - date, - The date and time at which this chat was opened (Requires Adium 1.2.1 or later)
- index - integer - The index of the tab in the chat window this chat is in.
- window - window - The window this chat is in.
Example of using a property of the chat class
tell application "Adium" to get date opened of every chat
Messages the chats respond to
Chat's respond to two messages, "close" and "send" so you can close a specific chat or send a specific chat a message. For example:
tell application "Adium" to close the second chat of the first chat window
Sending a message is accomplished just like we saw before with the active chat:
tell application "Adium" to send the second chat of the first chat window message "Hello"
Working with Statuses
A status in Adium is an object that contains information on a specific status and can be assigned globally to all online accounts or to individual online accounts. Note that I specifically called out the fact that statuses can only be assigned to accounts which are online. Trying to set a status for an offline account does not make sense and as such it does not have any affect. This can be confusing because you may try to set an account to the "away" status but if that account is not online, it will not go to the away status, it's status will remain "offline".
Statuses are contained by the application. So you can get every status with:
tell application "Adium" to get every status
Statuses do not contain any objects.
Properties of the status class
Every property of a status object is read only and they are:
- title - text - The title of the status
- status type - constant - The type of this status, one of the following: offline/available/away/invisible
- message - rich text - The customer status message
- autoreply - rich text - The message to auto reply
- id - integer - the unique ID of the status
Example of using a property of the status class
tell application "Adium" to get every status whose status type is away
This example gets every away status.
Messages the statuses respond to
Statuses do not respond to any messages.
Other Commands
We have already seen some commands that are specific to certain classes. For example the close command is only used on windows and chats, or the go online command is used on the application or on a specific account. Adium's AppleScript support also contains several commands that are not tied to specific classes. The list of other commands includes:
- count - Return the number of elements of a particular class within an object
- delete - Delete an object
- exists - Verify if an object exists
- make - Make a new object
- move - Move object(s) to a new location
- send - Send text or a file to some contact
We will look at each command individually to see how they can be used.
Using the count command
The count command can be used to count specific objects fore example to count the total number of contacts in Adium you could use:
tell application "Adium" to count contacts
You could narrow this down to a specific account with:
tell application "Adium" to count contacts of the first account
The count command also includes an optional each keyword which can be used to count specific elements in an object. So the last example could be rewritten to:
tell application "Adium" to count the first accounts each contacts
I personally don't care much for this last form because it moves away from AppleScripts common english like structure.
Using the delete command
The delete command is designed to delete objects, but currently it can not delete every object. It does work on statuses as well as images of contacts. To delete a status you could do something like:
tell application "Adium" to delete status id 60
Or you could do:
tell application "Adium" to delete status "status title"
To delete the image of a contact you could do:
tell application "Adium" to delete the image of the contact of the active chat
Starting Adium 1.3 you can now delete contacts using:
tell application "Adium" to delete contact "contactname"
Using the exists command
The exists command can be used to test if an object exists. For example you could test if a contact exists with:
tell application "Adium" to (exists contact "contactname")
If the contact exists, this will return true. Otherwise it will return false.
You can also test if a contact has an image assigned:
tell application "Adium" to (exists image of contact "contactname")
Using the make command
The make command can be used to create a new chat or a new status. Make has several optional (or mandatory depending on the object you are making) subcommands. These include:
- at <location secifier> - The location at which to insert the object
- with data <any> - The initial data for the object
- with properties <record> - The initial value for properties of the object
- with contacts <list of contacts> - The contacts needed for creating a chat or group.
- new chat window <boolean> - If this is true, then a new chat window will be created when creating a chat
The make command returns a specifier to the object that was created.
To make a new chat you would need to tell the account to create the chat using something like:
tell application "Adium" to tell account "accountname" to make new chat with contacts {contact "contactname"} with new chat window
Sidenote: The make new chat example works fine as long as the contact exists. If it does not exist in Adium 1.2.1, an error is thrown but a window is still created and could cause some very weird symptoms to take place after that. A Trac has been filed.
To make a new status you would use:
tell application "Adium"
set myStat to (make new status with properties {status type:away, title:"I'm not here", message:"I'm not here", autoreply:"Your message will be read when I return"})
end tell
Sidenote: The make new status example works fine on Tiger but throws an error on Leopard in Adium 1.2.1. There is a Trac opened for this.
Starting in Adium 1.3 you can now make a new contact using:
tell application "Adium"
tell account "accountname" of service "servicename"
make new contact with properties {display name:"Firstname Lastname", name:"userid", group:contact group "contactgroupname" of application "Adium"}
end tell
end tell
If you neglect to include the group property, the contact will be assigned to a global group that is not accessible via AppleScript. The only way utilize the contacts group after that is to assign one via the GUI or to move the contact to a user defined contact group using the move command. One interesting thing about this previous example is that because the example utilizes the tell account "accountname" of service "servicename" tell block, the make command is being run in the context of the account object which has no knowledge of contact groups. This forces us to fully qualify where the contact group is located with contact group "contactgroupname" of application "Adium". Remember that contact groups are contained by the application.
Using the move command
You can move a contact from one contact group to another. In fact, the group property of a contact is read-only, so the only way to change it is to use the move command. Here is an example that moves a contact:
tell application "Adium" to move contact "contactname" to contact group "contactgroupname"
Using the send command
We've already seen one example of sending a specific message to the active chat. Here's that example again:
tell application "Adium" to send the active chat message "Hello World!"
You can also send files:
tell application "Adium" set theFile to alias ((path to documents folder from user domain as string without folder creation) & "filename.txt") send active chat message "Check this out" with file theFile end tell
Examples
Here is an example of how to script Adium from the outside - SelectiveSignOn