Building an IRC bot in python

From XPUB & Lens-Based wiki
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

Somewhat redundant to example given on the IRC page.

The irc module provides a number of useful hooks/classes for writing python IRC bots.

sudo pip install irc

Hello

Here's a simple "hello" bot which responds to all chat messages by replying "HELLO".

import irc.bot

class HelloBot(irc.bot.SingleServerIRCBot):
    def __init__(self, channel, nickname, server, port=6667):
        irc.bot.SingleServerIRCBot.__init__(self, [(server, port)], nickname, nickname)
        self.channel = channel

    def on_welcome(self, c, e):
        c.join(self.channel)

    def on_privmsg(self, c, e):
        pass

    def on_pubmsg(self, c, e):
        # e.target, e.source, e.arguments, e.type
        print (e.arguments)
        c.privmsg(self.channel, "HELLO")


if __name__ == "__main__":
    import argparse
    import sys

    ap = argparse.ArgumentParser("IRC Bot")
    ap.add_argument("--server", default="irc.freenode.net")
    ap.add_argument("--port", type=int, default=6667)
    ap.add_argument("--channel", default="#pzi")
    ap.add_argument("--nickname", default="hellobot")
    args=ap.parse_args()

    bot = HelloBot(args.channel, args.nickname, args.server, args.port)
    bot.start()

Reverse Bot

import irc.bot

class FileBot(irc.bot.SingleServerIRCBot):
    def __init__(self, channel, nickname, server, port=6667):
        irc.bot.SingleServerIRCBot.__init__(self, [(server, port)], nickname, nickname)
        self.channel = channel

    def on_welcome(self, c, e):
        c.join(self.channel)

    def on_privmsg(self, c, e):
        pass

    def on_pubmsg(self, c, e):
        # e.target, e.source, e.arguments, e.type
        print e.arguments
        msg = e.arguments[0]
        words = msg.split()
        words.reverse()
        msg = " ".join(words)
        c.privmsg(self.channel, msg)


if __name__ == "__main__":
    import sys
    if len(sys.argv) != 4:
        print "Usage: reversebot.py <server[:port]> <channel> <nickname>"
        sys.exit(1)
    s = sys.argv[1].split(":", 1)
    server = s[0]
    if len(s) == 2:
        try:
            port = int(s[1])
        except ValueError:
            print "Error: Erroneous port."
            sys.exit(1)
    else:
        port = 6667
    channel = sys.argv[2]
    nickname = sys.argv[3]
    bot = FileBot(channel, nickname, server, port)
    bot.start()

PIPEBOT

from __future__ import print_function
import irc.bot
import sys, time
from thread import start_new_thread


def chunks(l, n):
    """ Yield successive n-sized chunks from l.
    """
    for i in xrange(0, len(l), n):
        yield l[i:i+n]

class Bot (irc.bot.SingleServerIRCBot):
    def __init__(self, channel, nickname, server, input, port=6667, idle=False):
        irc.bot.SingleServerIRCBot.__init__(self, [(server, port)], nickname, nickname)
        self.input = input
        self.channel = channel
        if idle:
            start_new_thread(self.idle, ())

    def on_welcome(self, c, e):
        c.join(self.channel)
        print ("join", file=sys.stderr)
        start_new_thread(self.receive, (c,))

    def idle(self):
        while True:
            tstr = time.strftime("%H:%M:%S", time.localtime())
            out = u"({0}) {1}: {2}".format(tstr, "_system", "idle")
            sys.stdout.write(out.encode("utf-8")+"\n")
            sys.stdout.flush()
            time.sleep(1)

    def receive (self, c): 
        if self.input == sys.stdin:
            # print ("reading from stdin", file=sys.stderr)
            _in = sys.stdin
        else:
            # print ("reading from {0}".format(self.input), file=sys.stderr)
            _in = open(self.input)

        while True:
            line = _in.readline()
            if line == '':
                break
            line = line.rstrip().decode("utf-8")
            if line:
                # print ("read line: {0}".format(line), file=sys.stderr)
                # CHUNK IT
                for chunk in chunks(line, 400):
                    c.privmsg(self.channel, chunk)
        
    def on_pubmsg(self, c, e):
        # e.target, e.source, e.arguments, e.type
        msg = e.arguments[0]
        tstr = time.strftime("%H:%M:%S", time.localtime())
        nick = e.source.split("!", 1)[0]
        out = u"({0}) {1}: {2}".format(tstr, nick, msg)
        sys.stdout.write(out.encode("utf-8")+"\n")
        sys.stdout.flush()
        # print ("pubmsg: {0}".format(msg), file=sys.stderr)
        
if __name__ == "__main__":
    from argparse import ArgumentParser
    parser = ArgumentParser()
    parser.add_argument('--server', default='irc.freenode.net', help='server hostname (default: localhost)')
    parser.add_argument('--port', default=6667, type=int, help='server port (default: 6667)')
    parser.add_argument('--channel', default='#botopera', help='channel to join (default: #botopera)')
    parser.add_argument('--nickname', default='pipebot', help='bot nickname (default: pipebot)')
    parser.add_argument('--input', default=sys.stdin, help='input')
    parser.add_argument('--idle', default=False, action="store_true", help='output idle messages')
    args = parser.parse_args()

    bot = Bot(args.channel, args.nickname, args.server, args.input, port=args.port, idle=args.idle)
    bot.start()