I saw an article on twitter about writing an IRC bot in ruby. It piqued my interest because of nostalgia and because I’m a slack curmudgeon. I believe that IRC has value. I never actually got around to trying the cinch gem that the article recommends, although if I ever need to do anything serious in this realm it wil be the first tool I turn to.
Instead I found an article about writing a really simple ruby class for a bot. It never really occurred to me how simple the actual connection part of IRC is, so after playing around with this code for an hour or two I decided to port it to Go.
What I came up with is an extremely simple
connection struct
that wraps a tcp socket with some metadata, and allows for injection of a message handler, while maintaining
the PING
/ PONG
keep-alives on its own.
I spent at least twenty minutes trying to figure out why this wasn’t working before
realizing fmt.Println
puts in a line break, while fmt.Fprintf
does not. Don’t trust
your debugging output too much.
func (c *IrcConnection) Say(msg string) {
fmt.Println(msg)
fmt.Fprintf(c.conn, fmt.Sprintf("%s\n", msg))
}
For an afternoon project, I like how neat and compartmentalized it is, excusing the natural verbosity of Go. If I ever put more time into this, I’d like to:
- Add tests. I wavered on this because at the end of the day it has to connect to a
real IRC server so I did all my development against that. Sorry freenode. But it
would be pretty easy to make an IrcConnection interface, craft a dummy version with
a buffer I can control, and use that to test that things like
PONG
work correctly. - Factor code more. For example, I could definitely use a separate method for all the handshake messages done during connection.
- Change
Run
to work in a goroutine, and make a separate message handler that allows user input. That would turn this into a single channel IRC client application, which would not be the least cool thing in the world.
That’s it. Just another fun little side project I thought I would share.