The Jokosher IRC bot

Someone said: it would be handy if we had a bot on the jokosher irc channel which told us about commits. I thought: I bet that’s not too hard, and it’ll give me an excuse to learn Twisted.

\<jokbot> New commit (r574) by laszlop: A better fix for ticket #150. This code is more maintainable and replaces the other fix committed in r566.
\<aquarius> jokbot: help
\<jokbot> For help on Jokosher, see You can also ask questions here; please be patient for an answer! Commands I understand: ticket - shows a bug in the bugtracker … download count - shows count of downloads of Jokosher … help - This message … revision - shows a revision from SVN
\<aquarius> jokbot: download count
\<jokbot> src:87 deb:281 rpm:74 srcrpm:7
\<aquarius> jokbot: ticket 7
\<jokbot> Recording quality settings -

The bot’s based on the Twisted example ircLogBot, and the basic code is really, really simple. You can make a noddy bot that responds to everything directed at it on the #jokbottest channel with the following 47 lines of Python:

from twisted.protocols import irc
from twisted.internet import reactor, protocol
import time, sys, os

class JokBot(irc.IRCClient):
  '''The Jokosher IRC bot.'''
  nickname = 'jokbot'
  channel = 'jokbottest'

  def connectionMade(self): irc.IRCClient.connectionMade(self)

  def connectionLost(self, reason):
    irc.IRCClient.connectionLost(self, reason)

  def signedOn(self): self.join(

  def privmsg(self, user, channel, msg):
    '''This will get called when the bot receives a message.'''
    user = user.split('!', 1)[0]

    # Check to see if they're sending me a private message
    if channel == self.nickname:
      msg = 'I don't take commands by message.'
      self.msg(user, msg)

    # Otherwise check to see if it is a message directed at me
    if msg.startswith(self.nickname + ':'):
      self.msg(channel, '%s said %s' % (user,
                        msg[len(self.nickname + ':'):]))

class JokBotFactory(protocol.ClientFactory):
  protocol = JokBot
  def __init__(self): pass

  def clientConnectionLost(self, connector, reason): connector.connect()

  def clientConnectionFailed(self, connector, reason): reactor.stop()

if __name__ == '__main__':
  f = JokBotFactory()
  reactor.connectTCP('', 6667, f)

That’s all you need for a very simple IRC bot. The jokbot code does a couple of other neat-ish things; it has a plugin structure, so the bot itself stays very simple and you implement all the commands via plugins. README.plugins in the jokbot distribution has all the details, but writing a plugin is really easy. It’s also reloadable: you can send it SIGHUP to make it reload plugins without quitting and restarting it, using the Python signal module. Grab the latest release of jokbot, or you can browse the Subversion repository for the very very latest code.

I'm currently available for hire, to help you plan, architect, and build new systems, and for technical writing and articles. You can take a look at some projects I've worked on and some of my writing. If you'd like to talk about your upcoming project, do get in touch.

More in the discussion (powered by webmentions)

  • (no mentions, yet.)