...making Linux just a little more fun!

Fun with Instant Messaging and Ruby

By Unnikrishnan KP

Introduction

As we all know, HTTP is the protocol used for communication between Web servers and Web clients (browsers). Similarly, XMPP [1] is a protocol for communication between Instant Messaging (IM) servers and clients. Most of the popular programming languages like C, Java, Python, etc., have XMPP libraries. Ruby is my language of choice, because of the ease with which ideas can be transformed into code.

Ruby also has an XMPP library known as xmpp4r. There is also a more abstract xmpp4r-simple library, which was built on top of xmpp4r. Let's use xmpp4r-simple, as our goals are relatively simple.

xmpp4r-simple can be easily installed using Rubygems, Ruby's packaging system:

sudo gem install xmpp4r-simple

Connecting to GoogleTalk and sending messages

Lets write a program that:

  1. connects to the Gtalk server
  2. authenticates with proper username and password.
  3. sends an instant message "hello" to a predefined user (a user who is already in the friends list).

Take a look at Program1. Replace the 'gmailusername', 'gmailpassword', and 'destination_gmailusername' in the code with with actual ones. Log in to destination_username via an Instant Messenger client, then run the program as:

 $ ruby chat0.rb 

'Destination user' should now get a "hello" message.

Receiving Messages - Echo Chat

Now, let's look at receiving the messages sent to us by our IM friends; here is a program that will receive an IM message and simply bounce it back to the sender. Log in with your username, and keep this program running for a while. This will baffle your IM friends for sure. :)

Echo Chat Program

Auto Reply

Most e-mail providers provide a service called "Auto reply" or "Holiday mail"; the idea is to send a predefined automated reply to all incoming mails. Here is a program that implements the same functionality for Instant Messenger. The program sends a predefined message in reply to every message it receives from any user. Maybe when you are busy, instead of setting status as "busy", you can simply run this program, so that it sends some appropriate reply automatically.

Auto Reply Program

Two-way chat program

Now, let's try a real chat program that can be used to talk to your friends.

Chat Program 1

In this program, user1 sends a message, user2 responds, then it's user1's turn again, and so on. However, if user1 wants to send a message before user2 responds, it's not possible - this is a single-threaded program which will block while waiting for user2's response.

Using 2 separate threads for listening and sending solves this issue.

Chat Program 2

A Remote Shell with Instant Messenger

The next test is to run commands on a remote machine and get the results through Instant Messenger.

Remote Shell Program

Run the program as "ruby remote_shell.rb" with user1 on a local machine. Log in as another user into an IM client from a remote machine, and send "ls" to user1 from that machine. Now, the "ls" command executes on the user1's remote machine, and the result is sent back. Commands are executed using the 'system' method, which internally uses an 'exec' system call to execute the command.

How useful would it be if you could just say "geyser ON" in your IM on your way home, which turns on the geyser at your home, so that you have warm water ready by the time you reach home? Theoretically, we can do it like this:

[ I love editing LG. Since the only 'geysers' I knew of until this point were volcanic in origin, I had to research the Indian meaning of the term; along the way, I found out that it is pronounced 'gee-zer' (as opposed to the American 'guy-ser' or 'guy-zer'), which leads to much wordplay when the two cultures collide (what DO you do when a geezer has a geyser?) In any case - in common Indian parlance, a 'geyser' is a hot-water heater, usually turned off when one leaves home (solar ones excluded, presumably.) Waiting for the water to warm up after you've returned could be annoying - but using the author's ideas as noted in this article could certainly alleviate the annoyance. On the other hand, if your friends knew, they could create an even greater annoyance for you by having a 'cron' job fire it up as soon as you left home - leading to a surprise gas bill at the end of the month. Which leads us back to ancient computer history: "Hax0rin a boilah" :) -- Ben ]

  1. Connect the geyser to your parallel port (not directly, of course - there should be some relay/switching device in between), so that a TTL 'high' on one of the parallel port pins turns on the geyser.
  2. Write a simple C program named "geyser" (or maybe in Ruby itself - I am not sure if we can do it in Ruby directly) that talks to the parallel port. On running this program with argument 'ON', it should produce a 'high' on one of the parallel port pins, while 'OFF' should make that pin produce a 'low'.
  3. Now, we can run this "geyser" program through our "IM remote shell".

IM-based Dictionary Service

You want to know the French equivalent for the word 'yesterday' - so you send an IM to your friend 'french-bot', and he immediately sends you back the French word for "yesterday". Wouldn't that be cool?

Here is your French-Bot :)

Artificial Intelligence and Instant Messaging - Eliza

Have you talked to Eliza? If not, try it now. She is an AI chat bot. Won't it be fun if we could make Eliza talk to your IM friends, on behalf of ourselves? :)

Since we already have Ruby programs that can talk to IM servers, an interface to Eliza is the only thing we still need. Eliza's web page, shows a plain HTML form, with a text field and a submit button. The page source shows that the name of the text field is "Entry1". That's all we need! Here's the Ruby interface for Eliza:

def eliza(str)
	response =  Net::HTTP.post_form(URI.parse("https://www-ai.ijs.si/eliza-cgi-bin/eliza_script"),{'Entry1'=>str})
	return response.body.split("</strong>\n").last.split("\n").first
end

Hats off to Ruby!!

Now, whenever a chat message arrives, we simply call this 'eliza' method, get a response string from Eliza, and send it as a reply. Here's the full Ruby code for the Eliza chat program.

Voice Chat

'Voice chat' is a little bit of an exaggeration - we are only going to hear the received chat messages, not talk to the program. The idea is to make our IM programs read the received messages aloud, rather than us having to read it.

We will use a speech synthesis system to convert the received IM text messages to speech. Festival is an excellent Open Source speech synthesizer that has had some previous exposure here in the Linux Gazette.

Voice Chat Program

Conclusion

These are just a few simple ideas that came to my mind as soon as I could control my Instant Messenger with my Ruby code. There can be tonnes of such interesting ideas, which may not be very useful - but fun is guaranteed. Start hacking!!!


[1] Rick Moen comments: It should be noted that XMPP, the eXtensible Messaging and Presence Protocol, is the underlying messaging/presence transport protocol of "Jabber" IM clients, and that GoogleTalk (mentioned later in this article) is an extension of XMPP that adds in VoIP functions.

(The term "Jabber" is now officially deprecated in favour of XMPP, but persists in common usage anyway.)

Other IM protocols, many of them much more common than XMPP, include Gadu-Gadu, IRC, MSN Protocol, AOL Instant Messager / ICQ's "OSCAR" protocol, AOL Instant Messager's TOC and TOC2 protocols, and Yahoo Messenger's YMSG protocol. (There are others.) XMPP is distinctive in being openly documented, stable, and modern -- along with often serving as the "glue" among otherwise incompatible services. A variety of Linux client implementations exist for sundry combinations of those IM protocols, along with a couple of good XMPP/Jabber servers and IM-gateway packages.

Talkback: Discuss this article with The Answer Gang


[BIO]

I completed my Bachelors Degree in Computer Science from Govt. Engineering College, Thrissur (Kerala, India) and am presently working at Viamentis Technologies Chennai, India, as a Software Engineer.

I presently work on Ruby on Rails. I am also interested in Ruby, Python, Hardware Interfacing Projects and Embedded systems.


Copyright © 2008, Unnikrishnan KP. Released under the Open Publication License unless otherwise noted in the body of the article. Linux Gazette is not produced, sponsored, or endorsed by its prior host, SSC, Inc.

Published in Issue 149 of Linux Gazette, April 2008

Tux