Last active
May 5, 2022 18:54
-
-
Save kaecy/286f8ad334aec3fcb588516feb727772 to your computer and use it in GitHub Desktop.
Simple IRC Bot (Updated)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class SimpleIrcBot extends IRCMessageLoop { | |
SimpleIrcBot(String server, int port) { | |
super(server, port); | |
} | |
// you have full access to PRIVMSG messages that are parsed. | |
void raw(Message msg) { | |
// when someone sends "hello" we'll respond with "Hiya!" | |
if (msg.content.equals("hello")) { | |
// is this a channel the message was sent to? | |
if (msg.target.startsWith("#")) { | |
privmsg(msg.target, "Hiya!"); | |
} else { | |
// no it's a private message. let's send this message back to the nickname. | |
privmsg(msg.nickname, "Hiya"); | |
} | |
// this is weird, yep, but this is how irc is. | |
// the target of a message is the person or group (channel) receiving the message so | |
// if the bot is receiving the message the target would be | |
// the bot's nickname. | |
} | |
if (msg.content.equals("!news")) { | |
privmsg(msg.target, "In keeping with Channel 40's policy of bringing you the latest in " + | |
"blood and guts and in living color, you are going to see another first - an attempted suicide."); | |
} | |
} | |
public static void main(String[] args) { | |
SimpleIrcBot client = new SimpleIrcBot("irc.rizon.net", 6667); | |
client.nick("Christine_Chubbuck"); | |
client.user("6a3k_49GRK", "null", "null", "real name"); | |
client.join("#test"); | |
client.run(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.io.*; | |
import java.net.*; | |
import java.util.*; | |
public abstract class IRCMessageLoop implements Runnable { | |
Socket server; | |
OutputStream out; | |
List<String> channelList; | |
boolean initial_setup_status; | |
IRCMessageLoop(String serverName, int port) { | |
channelList = new ArrayList<String>(); | |
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); | |
} | |
void join(String channel) { | |
if (!initial_setup_status) { | |
channelList.add(channel); | |
return; | |
} | |
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); | |
} | |
abstract void raw(Message msg); | |
void initial_setup() { | |
initial_setup_status = true; | |
// now join the channels. you need to wait for message 001 before you join a channel. | |
for (String channel: channelList) { | |
join(channel); | |
} | |
} | |
void processMessage(String ircMessage) { | |
Message msg = MessageParser.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; | |
} | |
raw(msg); | |
System.out.println("PRIVMSG: " + msg.nickname + ": " + msg.content); | |
} | |
else if (msg.command.equals("001")) { | |
initial_setup(); | |
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(); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Message { | |
public String origin; | |
public String nickname; | |
public String command; | |
public String target; | |
public String content; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// class only parses messages it understands. if a message is not understood | |
// the origin and command are extracted and parsing halts. | |
class MessageParser { | |
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; | |
} | |
} |
Good Code, I am able to connect the channel,
Thanks a Lot
I've updated the code to make it a little easier to make IRC bots.
Thank you.
I'm trying to use this to write an IRC client, but every time I try to use it to connect the socket to irc.libera.chat:6697
, I get the following exception:
java.net.SocketException: Connection reset
at java.net.SocketInputStream.read(SocketInputStream.java:210)
at java.net.SocketInputStream.read(SocketInputStream.java:141)
at java.net.SocketInputStream.read(SocketInputStream.java:127)
at com.AdamT.JarChat.IRCMessageLoop.run(JarChat.java:224)
at com.AdamT.JarChat.JarChat.run(JarChat.java:19)
at com.AdamT.JarChat.JarChat.main(JarChat.java:89)
All source code, with one or two edits, is already in a git repo. Any ideas?
@SimPilotAdamT hi.
Looks like the port is not right, try 6665. Also check out their connecting guide https://libera.chat/guides/connect.
@kaecy yeah for some reason I was using the SSL encrypted port and not the plaintext one.
I made some edits to the IRCMessageLoop constructor which might help with connections to TLS ports...
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thank you, I had problems when connecting to IRC, with this it just works fine