Skip to content

Instantly share code, notes, and snippets.

@notklaatu
Forked from kaecy/IRCMessageLoop.java
Created May 2, 2018 18:58
Show Gist options
  • Save notklaatu/c66c88c87814d491eef6c6aae84d4cc2 to your computer and use it in GitHub Desktop.
Save notklaatu/c66c88c87814d491eef6c6aae84d4cc2 to your computer and use it in GitHub Desktop.
Simple IRC Bot
import java.io.*;
import java.net.*;
import java.util.*;
public abstract class IRCMessageLoop implements Runnable {
Socket server;
OutputStream out;
String theChannel;
IRCMessageLoop(String serverName, int port) {
try
{
server = new Socket(serverName, port);
out = server.getOutputStream();
}
catch (IOException info)
{}
}
void send(String text) {
byte[] bytes = (text + "\r\n").getBytes();
try {
out.write(bytes);
}
catch (IOException info)
{}
}
void nick(String nickname) {
String msg = "NICK " + nickname;
send(msg);
}
void user(String username, String hostname, String servername, String realname) {
String msg = "USER " + username + " " + hostname + " " + servername + " :" + realname;
send(msg);
}
abstract void ignite();
void joinOnStart(String channel) {
theChannel = channel;
}
void join(String channel) {
String msg = "JOIN " + channel;
send(msg);
}
void part(String channel) {
String msg = "PART " + channel;
send(msg);
}
void privmsg(String to, String text) {
String msg = "PRIVMSG " + to + " :" + text;
send(msg);
}
void pong(String server) {
String msg = "PONG " + server;
send(msg);
}
void quit(String reason) {
String msg = "QUIT :Quit: " + reason;
send(msg);
}
void processMessage(String ircMessage) {
Message msg = Parse.message(ircMessage);
if (msg.command.equals("privmsg")) {
String target, content;
if (msg.content.equals("\001VERSION\001")) {
privmsg(msg.nickname, "Prototype IRC Client (Built to learn)");
return;
}
System.out.println(msg.nickname + ": " + msg.content);
}
else if (msg.command.equals("001")) {
ignite();
return;
}
else if (msg.command.equals("ping")) {
pong(msg.content);
}
}
public void run() {
InputStream stream = null;
try
{
stream = server.getInputStream();
MessageBuffer messageBuffer = new MessageBuffer();
byte[] buffer = new byte[512];
int count;
while (true) {
count = stream.read(buffer);
if (count == -1)
break;
messageBuffer.append(Arrays.copyOfRange(buffer, 0, count));
while (messageBuffer.hasCompleteMessage()) {
String ircMessage = messageBuffer.getNextMessage();
System.out.println("\"" + ircMessage + "\"");
processMessage(ircMessage);
}
}
}
catch (IOException info)
{
quit("error in messageLoop");
info.printStackTrace();
}
}
}
class Message {
public String origin;
public String nickname;
public String command;
public String target;
public String content;
}
class MessageBuffer {
String buffer;
public MessageBuffer() {
buffer = "";
}
public void append(byte[] bytes) {
buffer += new String(bytes);
}
public boolean hasCompleteMessage() {
if (buffer.contains("\r\n"))
return true;
else
return false;
}
public String getNextMessage() {
int index = buffer.indexOf("\r\n");
String message = "";
if (index > -1) {
message = buffer.substring(0, index);
buffer = buffer.substring(index + 2);
}
return message;
}
public static void main(String[] args) {
MessageBuffer buf = new MessageBuffer();
buf.append("blah\r\nblah blah\r\nblah blah oh uh".getBytes());
while (buf.hasCompleteMessage()) {
System.out.println("\"" + buf.getNextMessage() + "\"");
}
buf.append(" blah\r\n".getBytes());
while (buf.hasCompleteMessage()) {
System.out.println("\"" + buf.getNextMessage() + "\"");
}
}
}
// this class only parses messages it understands. if a message is not understood
// the origin and command are extracted and parsing halts.
class Parse {
static Message message(String ircMessage) {
Message message = new Message();
int spIndex;
if (ircMessage.startsWith(":")) {
spIndex = ircMessage.indexOf(' ');
if (spIndex > -1) {
message.origin = ircMessage.substring(1, spIndex);
ircMessage = ircMessage.substring(spIndex + 1);
int uIndex = message.origin.indexOf('!');
if (uIndex > -1) {
message.nickname = message.origin.substring(0, uIndex);
}
}
}
spIndex = ircMessage.indexOf(' ');
if (spIndex == -1) {
message.command = "null";
return message;
}
message.command = ircMessage.substring(0, spIndex).toLowerCase();
ircMessage = ircMessage.substring(spIndex + 1);
// parse privmsg params
if (message.command.equals("privmsg")) {
spIndex = ircMessage.indexOf(' ');
message.target = ircMessage.substring(0, spIndex);
ircMessage = ircMessage.substring(spIndex + 1);
if (ircMessage.startsWith(":")) {
message.content = ircMessage.substring(1);
}
else {
message.content = ircMessage;
}
}
// parse quit/join
if (message.command.equals("quit") || message.command.equals("join")) {
if (ircMessage.startsWith(":")) {
message.content = ircMessage.substring(1);
}
else {
message.content = ircMessage;
}
}
// parse ping params
if (message.command.equals("ping")) {
spIndex = ircMessage.indexOf(' ');
if (spIndex > -1) {
message.content = ircMessage.substring(0, spIndex);
}
else {
message.content = ircMessage;
}
}
return message;
}
}
public class SimpleIrcClient extends IRCMessageLoop {
SimpleIrcClient(String server, int port) {
super(server, port);
}
@Override
public void ignite() {
join(theChannel);
privmsg("#test", "Hello and bye bye.");
quit("bye bye");
}
public static void main(String[] args) {
SimpleIrcClient client = new SimpleIrcClient("server", 6667);
client.nick("nick");
client.user("catherine", "null", "null", "real name");
client.joinOnStart("#test");
client.run();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment