package ircbot;
/**
* JavaBot (version 1.2)
*
* MIT License, dydx (Josh Sandlin) <dydx@thenullbyte.org>
*
*/
import java.io.*;
import java.net.*;
import java.util.regex.*;
import java.util.Date;
public class Main
{
public static void main( String[] args ) throws IOException
{
//connection variables
String server = "irc.snappeh.com";
String nick = "JavaBot";
String login = "JavaBot";
String channel = "#bots";
int port = 6667;
//for security
String owner = "dydx";
try {
//our socket we're connected with
Socket irc = new Socket( server, port );
//out output stream
BufferedWriter bw = new BufferedWriter( new OutputStreamWriter( irc.getOutputStream() ) );
//our input stream
BufferedReader br = new BufferedReader( new InputStreamReader( irc.getInputStream() ) );
//authenticate with the server
bw.write( "NICK " + nick + "\n" );
bw.write( "USER " + login + " thenullbyte.org JB: Java Bot\n" );
bw.flush();
//join a channel
bw.write( "JOIN " + channel + "\n" );
bw.write( "PRIVMSG " + channel + " :Whats up everybody?\n" );
bw.flush();
System.out.println( "Successfully connected to IRC" );
String currLine = null;
while( ( currLine = br.readLine() ) != null )
{
//checks for PING, if one is found; return a PONG
Pattern pingRegex = Pattern.compile( "^PING", Pattern.CASE_INSENSITIVE );
Matcher ping = pingRegex.matcher( currLine );
if( ping.find() )
{
bw.write( "PONG " + channel + "\n" );
bw.flush();
}
//check for ownership
Pattern checkOwner = Pattern.compile( "^:"+owner, Pattern.CASE_INSENSITIVE );
Matcher ownership = checkOwner.matcher( currLine );
//!exit - quit current irc room
Pattern exitRegex = Pattern.compile( "!exit", Pattern.CASE_INSENSITIVE );
Matcher exit = exitRegex.matcher( currLine );
if( exit.find() && ownership.find() )
{
bw.write( "PRIVMSG " + channel + " :Bye Bye\n" );
bw.write( "PART " + channel + "\n" );
bw.flush();
irc.close();
}
//!time - return current time
Pattern timeRegex = Pattern.compile( "!time", Pattern.CASE_INSENSITIVE );
Matcher time = timeRegex.matcher( currLine );
if( time.find() && ownership.find() )
{
Date d = new Date();
bw.write( "PRIVMSG " + channel + " :" + d +"\n" );
bw.flush();
}
//!sayhi - shows a little message saying hello
Pattern helloRegex = Pattern.compile( "!sayhi", Pattern.CASE_INSENSITIVE );
Matcher hello = helloRegex.matcher( currLine );
if( hello.find() && ownership.find() )
{
bw.write( "PRIVMSG " + channel + " :Hello, I'm a JavaBot. I was coded by dydx in Java!\n");
bw.flush();
}
//!join <room> - changes to a new room and sets the variables accordingly
Pattern joinRegex = Pattern.compile( "!join", Pattern.CASE_INSENSITIVE );
Matcher join = joinRegex.matcher( currLine );
if( join.find() && ownership.find() )
{
String[] token = currLine.split( " " );
bw.write( "PRIVMSG " + channel + " :Im going over to " + token[4] + "\n" );
bw.write( "PART " + channel + "\n" );
channel = token[4];
bw.write( "JOIN " + channel + "\n" );
bw.flush();
}
}
} catch ( UnknownHostException e ) {
System.err.println( "No such host" );
} catch ( IOException e ) {
System.err.println( "There was an error connecting to the host" );
}
}
}
Refactorings
No refactoring yet !
Fivesheep
September 13, 2008, September 13, 2008 14:10, permalink
you can try http://www.jibble.org/pircbot.php, if you just want to write a bot in java.
Ishkur
September 14, 2008, September 14, 2008 00:19, permalink
I decided to refactor it myself and ended up recoding it. I took a slightly different approach this second time. I created a class for the Bot and its functions, and then implemented it in the Main class and controlled the Bot functionality with Regex.
package ircbot;
/**
* JavaBot (version 1.2)
*
* MIT License, dydx (Josh Sandlin) <dydx@thenullbyte.org>
*
*/
import java.io.*;
import java.net.*;
import java.util.regex.*;
import java.util.Date;
import java.util.Random;
public class Main
{
public static void main( String[] args ) throws IOException
{
//connection variables
String server = args[0]; //irc.snappeh.com
String nick = args[1]; //JavaBot
String address = "thenullbyte.org";
String channel = "#"+args[2]; //#enigmagroup
int port = 6667;
//for security
String owner = "dydx";
try {
//our socket we're connected with
Socket irc = new Socket( server, port );
//out output stream
BufferedWriter bw = new BufferedWriter( new OutputStreamWriter( irc.getOutputStream() ) );
//our input stream
BufferedReader br = new BufferedReader( new InputStreamReader( irc.getInputStream() ) );
//create a new instance of the JavaBot
Bot JavaBot = new Bot( bw, channel);
//authenticate the JavaBot with the server
JavaBot.login( nick, address );
String currLine = null;
while( ( currLine = br.readLine() ) != null )
{
//compile a regex to check and see if the person calling commands is the owner
Pattern checkOwner = Pattern.compile( "^:"+owner, Pattern.CASE_INSENSITIVE );
Matcher ownership = checkOwner.matcher( currLine );
//constantly check for PING's, if the bot sees one, it replies with a PONG
Pattern pingRegex = Pattern.compile( "^PING", Pattern.CASE_INSENSITIVE );
Matcher ping = pingRegex.matcher( currLine );
if( ping.find() )
{
JavaBot.pong();
}
//check to see if the owner has given the !exit command
Pattern exitRegex = Pattern.compile( "!exit", Pattern.CASE_INSENSITIVE );
Matcher exit = exitRegex.matcher( currLine );
if( exit.find() && ownership.find() )
{
JavaBot.say( "I'm tired, bye yall" );
JavaBot.quit();
}
//parts one room and joins another, gives a nice little going away speech as well
Pattern joinRegex = Pattern.compile( "!join", Pattern.CASE_INSENSITIVE );
Matcher join = joinRegex.matcher( currLine );
if( join.find() && ownership.find() )
{
String[] token = currLine.split( " " );
JavaBot.say( "I'm going to go over to " + token[4] + " and see what they're up to over there. Cya." );
JavaBot.part();
channel = token[4];
JavaBot.join( channel );
JavaBot.say( "Hey guys!" );
}
//we should be polite every now and then, this introduces the bot
Pattern sayhiRegex = Pattern.compile( "!sayhi", Pattern.CASE_INSENSITIVE );
Matcher sayhi = sayhiRegex.matcher( currLine );
if( sayhi.find() && ownership.find() )
{
JavaBot.say( "Hi, I'm a JavaBot. I was written by dydx in Java!" );
}
//more or less a PoC, just returns the current date/time to the IRC channel
Pattern timeRegex = Pattern.compile( "!time", Pattern.CASE_INSENSITIVE );
Matcher time = timeRegex.matcher( currLine );
if( time.find() )
{
Date d = new Date();
String message = "The date is " + d ;
JavaBot.say( message );
}
}
} catch ( UnknownHostException e ) {
System.err.println( "No such host" );
} catch ( IOException e ) {
System.err.println( "There was an error connecting to the host" );
}
}
}
package ircbot;
import java.io.*;
/**
* The skeleton of the IRC Bot.
*
* @author dydx
*/
public class Bot
{
BufferedWriter bw;
String channel;
/**
* Bot class constructor, set the defaults for the output stream and the channel
* @param writer
* @param chan
* @param own
*/
Bot( BufferedWriter writer, String chan )
{
bw = writer;
channel = chan;
}
/**
* This is the main part of the bot, it replies to PING's
* @throws java.io.IOException
*/
public void pong() throws IOException
{
bw.write( "PONG " + channel + "\n" );
bw.flush();
}
/**
* General purpose method for inputting into the channel at hand
* @param message
* @throws java.io.IOException
*/
public void say( String message ) throws IOException
{
bw.write( "PRIVMSG " + channel + " :" + message + "\n" );
bw.flush();
}
/**
* Joins a specified IRC channel and sets this.channel accordingly
* @param channel
* @throws java.io.IOException
*/
public void join( String chan ) throws IOException
{
bw.write( "JOIN " + chan + "\n" );
bw.flush();
//we're doing this so that there's no confusion
//as to which channel the bot is in
channel = chan;
}
/**
* Leave the curent channel
* @throws java.io.IOException
*/
public void part() throws IOException
{
bw.write( "PART " + channel + "\n" );
bw.flush();
}
/**
* Quit the current IRC session
* @param reason
* @throws java.io.IOException
*/
public void quit() throws IOException
{
bw.write( "QUIT " + channel + "\n" );
bw.flush();
}
/**
* Class method used to authenticate the Bot with the IRC server
* @param nick
* @param address
* @throws java.io.IOException
*/
public void login( String nick, String address ) throws IOException
{
bw.write( "NICK " + nick + "\n" );
bw.write( "USER " + nick + " " + address + ": Java Bot\n" );
bw.flush();
bw.write( "JOIN " + channel + "\n" );
bw.flush();
}
/**
* General method for yelling at users, might not need to use it after all
* @param message
* @throws java.io.IOException
*/
public void yell( String message ) throws IOException
{
say( message );
}
/**
* Will eventually be used to search for crap on Wikipedia
* @throws java.io.IOException
*/
public void wiki() throws IOException
{
say( "Sorry folks, but that feature isn't working just yet." );
}
}
Simon Hartley
October 25, 2008, October 25, 2008 12:20, permalink
To increase clarity I've separated the logic of parsing the request line and the how to respond to it.
package ircbot;
/**
* JavaBot (version 1.2)
*
* MIT License, dydx (Josh Sandlin) <dydx@thenullbyte.org>
*
*/
import java.io.*;
import java.net.*;
import java.util.Date;
public class Main
{
public static void main( String[] args ) throws IOException
{
//connection variables
String server = args[0]; //irc.snappeh.com
String nick = args[1]; //JavaBot
String address = "thenullbyte.org";
String channel = "#"+args[2]; //#enigmagroup
int port = 6667;
try {
//our socket we're connected with
Socket irc = new Socket( server, port );
//out output stream
BufferedWriter bw = new BufferedWriter( new OutputStreamWriter( irc.getOutputStream() ) );
//our input stream
BufferedReader br = new BufferedReader( new InputStreamReader( irc.getInputStream() ) );
//create a new instance of the JavaBot
Bot JavaBot = new Bot( bw, channel);
//authenticate the JavaBot with the server
JavaBot.login( nick, address );
String currLine = null;
while( ( currLine = br.readLine() ) != null )
{
Request request = new Request(currLine);
if( request.isPing() )
{
JavaBot.pong();
}
if( request.isTime() )
{
Date d = new Date();
String message = "The date is " + d ;
JavaBot.say( message );
}
if( request.hasOwnership() )
{
//check to see if the owner has given the !exit command
if( request.isExit() )
{
JavaBot.say( "I'm tired, bye yall" );
JavaBot.quit();
}
//parts one room and joins another, gives a nice little going away speech as well
if( request.isJoin() )
{
String newChannel = request.getDestinationChannel();
JavaBot.say( "I'm going to go over to " + newChannel + " and see what they're up to over there. Cya." );
JavaBot.part();
channel = newChannel;
JavaBot.join( channel );
JavaBot.say( "Hey guys!" );
}
//we should be polite every now and then, this introduces the bot
if( request.isSayHi() )
{
JavaBot.say( "Hi, I'm a JavaBot. I was written by dydx in Java!" );
}
}
}
} catch ( UnknownHostException e ) {
System.err.println( "No such host" );
} catch ( IOException e ) {
System.err.println( "There was an error connecting to the host" );
}
}
}
package ircbot;
import java.util.regex.*;
public class Request {
//for security
private String MANDATORY_OWNER = "dydx";
private String line;
public Request(String line) {
this.line = line;
}
public boolean hasOwnership()
{
//compile a regex to check and see if the person calling commands is the owner
Pattern checkOwner = Pattern.compile( "^:"+MANDATORY_OWNER, Pattern.CASE_INSENSITIVE );
Matcher ownership = checkOwner.matcher( this.line );
return ownership.find();
}
public boolean isPing()
{
Pattern pingRegex = Pattern.compile( "^PING", Pattern.CASE_INSENSITIVE );
Matcher ping = pingRegex.matcher( this.line );
return ping.find();
}
public boolean isExit()
{
//check to see if the owner has given the !exit command
Pattern exitRegex = Pattern.compile( "!exit", Pattern.CASE_INSENSITIVE );
Matcher exit = exitRegex.matcher( this.line );
return exit.find();
}
public boolean isJoin()
{
Pattern joinRegex = Pattern.compile( "!join", Pattern.CASE_INSENSITIVE );
Matcher join = joinRegex.matcher( this.line );
return join.find();
}
public boolean isSayHi()
{
Pattern sayhiRegex = Pattern.compile( "!sayhi", Pattern.CASE_INSENSITIVE );
Matcher sayhi = sayhiRegex.matcher( this.line );
return sayhi.find();
}
public boolean isTime()
{
Pattern timeRegex = Pattern.compile( "!time", Pattern.CASE_INSENSITIVE );
Matcher time = timeRegex.matcher( this.line );
return time.find();
}
public String getDestinationChannel()
{
String[] token = this.line.split( " " );
return token[4];
}
}
Simo Niemelä
November 4, 2008, November 04, 2008 11:46, permalink
public boolean hasOwnerShip()
{
return this.find("^:"+MANDATORY_OWNER);
}
public boolean isPing()
{
return this.find("^PING");
}
// ...
private boolean find(String command)
{
Pattern regex = Pattern.compile(command, Pattern.CASE_INSENSITIVE);
Matcher match = regex.matcher(this.line);
return match.find();
}
private boolean find(String command, int flags)
{
Pattern regex = Pattern.compile(command, flags);
Matcher match = regex.matcher(this.line);
return match.find();
}
I've been working on this for a few days, and I finally have it to where it actually works like I want it to. I'm new to Java, so I know this isn't the best way I could have coded it, and I'm curious to see how anyone would improve upon it.