1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
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.
Main.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
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" ); } } }
Bot.Java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
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
Request.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
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.