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.*;
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( ));
}
}
}
}
As you may have noticed, the Cont class makes use
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.*;
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);
}
}
To give the user a greater feel of temporal location, it is useful to
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 2004
This 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.*;
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( );
}
}
All you need to do now is create a main method to run the bot from,
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");
}
}