From f43a7e349a07ba29333490dbbac7dfb3d3f8ba5a Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Sat, 10 May 2008 18:42:29 +0100 Subject: [PATCH] [Contribs] Add simple IRC bot for looking up error codes. --- contrib/errcode/README | 3 + contrib/errcode/errcode.py | 4 +- contrib/errcode/gpxebot.py | 121 +++++++++++++++++++++++++++++++++++++ 3 files changed, 126 insertions(+), 2 deletions(-) create mode 100755 contrib/errcode/gpxebot.py diff --git a/contrib/errcode/README b/contrib/errcode/README index f620ea07..b2963c06 100644 --- a/contrib/errcode/README +++ b/contrib/errcode/README @@ -20,6 +20,9 @@ A PHP script is provided as a web interface. First edit errcode.php to point $ERRCODE_PATH to the errcode.py script. Then move errcode.php to a location visible from your web server. +[OPTIONAL] +A simple IRC bot is provided. Edit gpxebot.py to fill in the IRC details. + Usage ----- Looking up error codes on the command-line: diff --git a/contrib/errcode/errcode.py b/contrib/errcode/errcode.py index 8a8ce808..7bc8d9e1 100755 --- a/contrib/errcode/errcode.py +++ b/contrib/errcode/errcode.py @@ -40,7 +40,7 @@ def lookup_errno_component(defines, component): else: return '0x%x' % component -class Errno(object): +class Errcode(object): def __init__(self, errno): self.pxenv_status = to_pxenv_status(errno) self.uniq = to_uniq(errno) @@ -74,5 +74,5 @@ if __name__ == '__main__': except ValueError: usage() - print Errno(errno) + print Errcode(errno) sys.exit(0) diff --git a/contrib/errcode/gpxebot.py b/contrib/errcode/gpxebot.py new file mode 100755 index 00000000..4fb2ce1e --- /dev/null +++ b/contrib/errcode/gpxebot.py @@ -0,0 +1,121 @@ +#!/usr/bin/env python +# Copyright (C) 2008 Stefan Hajnoczi . +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of the +# License, or any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +import re +import socket +import errcode + +HOST = 'irc.freenode.net' +PORT = 6667 +NICK = 'gpxebot' +CHAN = '#etherboot' +NICKSERV_PASSWORD = None +IDENT = 'gpxebot' +REALNAME = 'gPXE bot' + +ERRCODE_RE = re.compile(r'(errcode|Error)\s+((0x)?[0-9a-fA-F]{8})') + +NO_ARGS = -1 + +handlers = {} + +def nick_from_mask(mask): + return (mask.find('!') > -1 and mask.split('!', 1)[0]) or mask + +def autojoin(): + del handlers['376'] + if NICKSERV_PASSWORD: + pmsg('nickserv', 'identify %s' % NICKSERV_PASSWORD) + if CHAN: + cmd('JOIN %s' % CHAN) + +def ping(_, arg): + cmd('PONG %s' % arg) + +def privmsg(_, target, msg): + if target == CHAN: + replyto = target + if msg.find(NICK) == -1: + return + elif target == NICK: + replyto = nick_from_mask(who) + m = ERRCODE_RE.search(msg) + if m: + try: + pmsg(replyto, str(errcode.Errcode(int(m.groups()[1], 16)))) + except ValueError: + pass + if msg.find('help') > -1: + pmsg(replyto, 'I look up gPXE error codes. Message me like this:') + pmsg(replyto, 'errcode 0x12345678 OR Error 0x12345678') + +def add_handler(command, handler, nargs): + handlers[command] = (handler, nargs) + +def cmd(msg): + sock.sendall('%s\r\n' % msg) + +def pmsg(target, msg): + cmd('PRIVMSG %s :%s' % (target, msg)) + +def dispatch(args): + command = args[0] + if command in handlers: + h = handlers[command] + if h[1] == NO_ARGS: + h[0]() + elif len(args) == h[1]: + h[0](*args) + +def parse(line): + if line[0] == ':': + who, line = line.split(None, 1) + who = who[1:] + else: + who = None + args = [] + while line and line[0] != ':' and line.find(' ') != -1: + arg, line = line.split(None, 1) + args.append(arg) + if line: + if line[0] == ':': + args.append(line[1:]) + else: + args.append(line) + return who, args + +add_handler('376', autojoin, NO_ARGS) +add_handler('PING', ping, 2) +add_handler('PRIVMSG', privmsg, 3) + +sock = socket.socket() +sock.connect((HOST, PORT)) +cmd('NICK %s' % NICK) +cmd('USER %s none none :%s' % (IDENT, REALNAME)) + +rbuf = '' +while True: + r = sock.recv(4096) + if not r: + break + rbuf += r + + while rbuf.find('\r\n') != -1: + line, rbuf = rbuf.split('\r\n', 1) + if not line: + continue + who, args = parse(line) + dispatch(args)