XMPP Scripting with Sluift

Did you ever want to find out what XMPP clients people in your contact list are using? Do you want to migrate your contact list from one server to another, but don’t want to provide your password to some on-line service to do that? Do you have some XMPP-related task you quickly want to write a script for, but don’t want to deal with complex asynchronous APIs? Well, Sluift may be just the thing you are looking for!

Sluift is a Lua-based script layer on top of the Swiften XMPP library. It provides a simple API to do common XMPP tasks, either interactively (through an XMPP console), or by running a script in batch mode. In this post, we’ll go through some examples of what you can already do with Sluift today.

Let’s start with a very simple task: logging into a server, and sending a message to one of our contacts. We fire up Sluift, and start by typing the commands to log in:

== Sluift XMPP Console (20110304) == 
Press Ctrl-D to exit  
> c = sluift.new_client("alice@wonderland.lit", "MySecret")
> c:connect()
>

Now that we’re connected to the server, let’s send out presence (so people can see we’re online), and send the message to one of our contacts:

> c:send_presence("I'm here")
> c:send_message("sister@realworld.lit", "Hi there!")

Now, let’s wait 3 seconds for her reply, by printing out all the incoming events, and finish off by disconnecting:

> for event in c:events{timeout = 3000} do print(event) end
([type] => presence, [from] => sister@realworld.lit/Home, 
[status] => At home)
([type] => presence, [from] => rabbit@wonderland.lit/Party, 
[status] => Tea party!)
([type] => message, [from] => sister@realworld.lit/Home, 
[body] => Hi Alice!)
> c:disconnect()
>

Now for a slightly more complex example. Suppose that you want to switch XMPP servers, but you want to take all your contacts with you to your new account. To do this, you start by logging into your current account, and fetch your contact list:

> c = sluift.new_client("alice@wonderland.lit", "MySecret")
> c:connect()
> contacts = c:get_contacts()
> print(contacts)
[sister@wonderland.lit] => table
    ( [jid] => sister@wonderland.lit
      [subscription] => both
      [groups] => table ( [1] => Family )
      [name] => Sister )
...

Now that we have our contact list, let’s disconnect, log into our second account, and add all the contacts from the list to the second account:

> c:disconnect()
> c = sluift.new_client("alice@teaparty.lit", "MyOtherSecret")
> c:connect()
> for _, contact in pairs(contacts) do c:add_contact(contact) end

That’s it, all your contacts have now been migrated!

So far, we have used Sluift as an interactive XMPP console. However, Sluift’s synchronous/blocking nature (it only executes the next command when you have the results of the previous) also makes it very suitable for writing small batch scripts. For example, you can write a short script to collect statistics about which sever software is popular amongst your contacts:

c = sluift.new_client("alice@wonderland.lit", "MySecret")
c:connect(function () 
  versions = {}
  for jid in pairs(c:get_contacts()) do
    v = c:get_software_version{to = sluift.jid.domain(jid)} or {name = 'Unknown'}
    versions[v['name']] = (versions[v['name']] or 0) + 1
  end
  for name, count in pairs(versions) do print(name .. ': ' .. count) end
end)

By passing a function to connect, we ensure that the client is automatically disconnected when the function finishes (either through an error, or because it reached the end). Executing the script gives us the following result:

$ ./sluift CollectVersions.lua
jabberd2: 1
Prosody: 25
Isode M-Link: 31
yabberd: 1
SoapBox Server 2007: 1
jabberd: 5
Tigase: 2
ejabberd: 19
Openfire: 4

And finally, we can’t show script examples without including our beloved EchoBot from XMPP: The Definitive Guide:

c = sluift.new_client("echobot@wonderland.lit", "mypass")
c:connect(function () 
  c:send_presence("Send me a message")
  for message in c:messages() do
    c:send_message{to = message["from"], body = message["body"]}
  end
end)

Besides interactive and scripted tasks, another great use for Sluift is for XMPP testing (which is the reason we started Sluift in the first place). However, we will go into details about this use case in a later blog post. For now, if you want to play around with Sluift yourself, you can build a development version from the Swift Git repository (together with some examples).

Finally, note that, although you can already do quite some tasks with Sluift today, the API is still quite limited (and undocumented). We are adding new functionality to Sluift as we need it or as people ask for it, so if you’re interested in Sluift, speak up!

Stay tuned for more on the topic of XMPP scripting!

This page was posted in Programming, Jabber with tags Jabber, XMPP, Swift, Swiften, Lua, Sluift .