[Contribs] Add simple IRC bot for looking up error codes.
authorStefan Hajnoczi <stefanha@gmail.com>
Sat, 10 May 2008 17:42:29 +0000 (18:42 +0100)
committerMichael Brown <mcb30@etherboot.org>
Tue, 20 May 2008 19:28:57 +0000 (20:28 +0100)
contrib/errcode/README
contrib/errcode/errcode.py
contrib/errcode/gpxebot.py [new file with mode: 0755]

index f620ea0..b2963c0 100644 (file)
@@ -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:
index 8a8ce80..7bc8d9e 100755 (executable)
@@ -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 (executable)
index 0000000..4fb2ce1
--- /dev/null
@@ -0,0 +1,121 @@
+#!/usr/bin/env python
+# Copyright (C) 2008 Stefan Hajnoczi <stefanha@gmail.com>.
+#
+# 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)