Hack 43 A Continuity Bot


joined the middle of their conversation?
Joining an IRC channel in the middle of a
conversation can be a frustrating experience for all concerned, so
wouldn't it be nice if there were someone there to
tell you what people were talking about? Wouldn't
you like to know if the awkward silence following your appearance was
because everyone was busy insulting you before you joined? Now, with
the miracle of the Continuity Bot Hack, you can ease seamlessly into
the conversation and find out what your friends really think of you
in the bargain.This hack takes the form of cont, a simple bot
based on the PircBot framework. When someone joins the channel it
sits on, the bot sends her the last 10 events that occurred there via
private message. Many people set up their clients to join multiple
channels on startup. As the history is sent via private message, you
may want to modify the message format to include the channel name in
this case.
|
said in a channel. This requires only normal messages and actions to
be monitored.
6.5.1 The Code
The file Cont.java
will contain the code that is used
to keep an eye on what people are saying in the channel. The
Cont class inherits from the PircBot class to make
this rather straightforward.Save the following as Cont.java:
import org.jibble.pircbot.*;As you may have noticed, the Cont class makes use
import java.util.*;
public class Cont extends PircBot {
// Remember up to 10 things that happened in the channel.
private ContextList contextList = new ContextList(10);
private CurrentTime now = new CurrentTime( );
// Constructor used to set the name of the bot.
public Cont( ) {
this.setName("cont");
this.setLogin("cont");
}
// Handle on-channel messages.
public void onMessage(String channel, String sender,
String login, String hostname, String message) {
contextList.add(now + " <" + sender + "> " + message);
}
// Handle actions.
public void onAction(String sender, String login,
String hostname, String target, String action) {
contextList.add(now + " * " + sender + " " + action);
}
// Handle people joining the channel.
public void onJoin(String channel, String sender,
String login, String hostname) {
if (!sender.equals(getName( ))) {
// Send out the history of messages to the new channel user.
Iterator messageIt = contextList.iterator( );
while (messageIt.hasNext( )) {
sendMessage(sender, messageIt.next( ).toString( ));
}
}
}
}
of two classes that haven't been made yet! The first
of these is
ContextList
, which has the responsibility of
remembering the last 10 events seen by the bot. The second is
CurrentTime, which performs the trivial task of
creating a simple timestamp, similar to that used by most IRC
clients.ContextList is what you might call a
ring buffer. It is an ordered list, but its size is
limited to 10 items in this case. If the list is full and a new item
is added, the oldest item in the list is simply removed. The bot uses
this class to store the last 10 (or fewer) events that occurred
on-channel, ready to be sent to each user who joins the channel.Now create the file ContextList.java:
import java.util.*;To give the user a greater feel of temporal location, it is useful to
public class ContextList extends Vector {
private int maxListSize;
public ContextList(int maxListSize) {
this.maxListSize = maxListSize;
}
public boolean add(Object o) {
if (this.size( ) >= maxListSize) {
// Remove the first item if the list is full.
this.remove(0);
}
// Add the new item to the end of the list.
return super.add(o);
}
}
apply timestamps to the
messages. It often helps if you can tell if a message was sent 30
seconds ago or 30 minutes ago. The quickest way of getting the
current time is to call the
toString() method on a new instance of the
java.util.Date class. This method may return
slightly different things depending on your locale, but it will look
something like this:
Sat Feb 14 14:45:13 GMT 2004This is rather long for messages that appear in an IRC window, and
most of it is unnecessary. Not many channels are idle for more than a
year, and if they are, it's unlikely that
you'll want to keep your bot running in there. The
CurrentTime
class will generate a timestamp like
14:45.Save this as CurrentTime.java:
import java.io.*;All you need to do now is create a main method to run the bot from,
import java.util.*;
import java.text.*;
public class CurrentTime {
private SimpleDateFormat shortDateFormat = new SimpleDateFormat("H:mm");
private FieldPosition fp = new FieldPosition(0);
public String toString( ) {
Date now = new Date( );
StringBuffer output = new StringBuffer( );
try {
shortDateFormat.format(now, output, fp);
}
catch (NullPointerException e) {
// Date cannot be null. Ignore this.
}
return output.toString( );
}
}
and you're done. Save the following as
ContMain.java
:
public class ContMain {
public static void main(String[] args) throws Exception {
Cont bot = new Cont( );
// Connect to a server and join a channel.
bot.connect("irc.freenode.net");
bot.joinChannel("#irchacks");
}
}
6.5.2 Running the Hack
Compile the classes with
the javac command:
C:\java\ContBot> javac -classpath .;pircbot.jar *.javaStart the continuity bot by running the main method in the
ContMain class:
C:\java\ContBot> java -classpath .;pircbot.jar ContMainIf all goes well, the bot should spring into life.When a user joins the channel, the bot will send private messages
containing the last 10 lines of text sent to the channel, as shown in
Figure 6-3.
Figure 6-3. Receiving private messages from the bot

when he enters the middle of a conversation.Steve Jolly