diff --git a/bot.py b/bot.py index a6c05d4..dc7f993 100755 --- a/bot.py +++ b/bot.py @@ -1,8 +1,8 @@ #!/usr/bin/python -network = "localhost" -nickname = "skybot" -channel = "#skybot" +network = "irc.synirc.net" +nick = "skybot" +channel = "#cobol" import sys import os @@ -24,12 +24,13 @@ class Bot(object): self.filters = [] #fn, name, func bot = Bot() -bot.nickname = nickname +bot.nick = nick bot.channel = channel bot.network = network print 'Loading plugins' -magic_re = re.compile(r'^\s*#(command|filter)(?:: +(\S+) *(\S.*)?)?\s*$') +typs = '|'.join('command filter event'.split()) +magic_re = re.compile(r'^\s*#(%s)(?:: +(\S+) *(\S.*)?)?\s*$' % typs) def reload_plugins(mtime=[0]): new_mtime = os.stat('plugins') @@ -65,8 +66,12 @@ def reload_plugins(mtime=[0]): if typ == 'command': args = {'name': nam, 'hook': nam + rest} bot.commands.append((filename, nam, func, args)) - if typ == 'filter': + elif typ == 'filter': bot.filters.append((filename, nam, func)) + elif typ == 'event': + args = {'name': nam, 'prefix':False, + 'events': [nam] + rest.split()} + bot.commands.append((filename, nam, func, args)) except Exception, e: print e @@ -75,9 +80,9 @@ def reload_plugins(mtime=[0]): reload_plugins() print 'Connecting to IRC' -bot.irc = irc.irc(network, nickname) +bot.irc = irc.irc(network, nick) bot.irc.join(channel) -bot.commandprefix = '^(?:\.|'+nickname+'[:,]*\s*)' +bot.commandprefix = '^(?:\.|'+nick+'[:,]*\s*)' print 'Running main loop' @@ -93,7 +98,6 @@ class Input(object): self.host = host self.paraml = paraml self.msg = msg - self.doreply = True class FakeBot(object): def __init__(self, bot, input, fn, func): @@ -101,11 +105,13 @@ class FakeBot(object): self.input = input self.msg = bot.irc.msg self.cmd = bot.irc.cmd + self.join = bot.irc.join self.fn = func self.func = func + self.doreply = True if input.command == "PRIVMSG": self.chan = input.paraml[0] - + def say(self, msg): self.bot.irc.msg(self.input.paraml[0], msg) @@ -135,6 +141,7 @@ while True: break if input == None: continue + print '<<<', input.raw thread.start_new_thread(FakeBot(bot, input, fn, func).run, ()) except Queue.Empty: pass diff --git a/irc.py b/irc.py index aad2ddb..0a35bc0 100644 --- a/irc.py +++ b/irc.py @@ -26,6 +26,7 @@ class crlf_tcp(asynchat.async_chat): self.oqueue = queue() #where we stick things that need to be sent self.iqueue = queue() #where we stick things that were received self.create_socket(socket.AF_INET, socket.SOCK_STREAM) + self.socket.setsockopt(socket.SOL_TCP, socket.TCP_NODELAY, 0) self.host = host self.port = port @@ -72,7 +73,6 @@ class irc(object): def parse_loop(self): while True: msg = self.conn.iqueue.get() - print '>>>', msg if msg.startswith(":"): #has a prefix prefix, command, params = irc_prefix_re.match(msg).groups() else: diff --git a/plugins/bf.py b/plugins/bf.py new file mode 100644 index 0000000..b83ab68 --- /dev/null +++ b/plugins/bf.py @@ -0,0 +1,113 @@ +'''brainfuck interpreter adapted from (public domain) code at +http://brainfuck.sourceforge.net/brain.py''' + +import re +import random + +BUFFER_SIZE = 5000 + +#command +def bf(bot, inp, input=None, max_steps=1000000, no_input=0): + """Runs a Brainfuck program given as a string. + + The string must contain nothing but "<>[]+-.,", i.e. + be already filtered. + + If 'input' is None, stdin is used. 'input' can be + a string or a tuple; tuples are only used if + extended_interpretation is non-zero, and should + be more or less obvious in that case. + + if max_steps is < 0, there is no restriction.""" + program = re.sub('[^][<>+-.,]', '', inp.inp) + + # create a dict of brackets pairs, for speed later on + parens={} + open_parens=[] + for pos in range(len(program)): + if program[pos] == '[': + open_parens.append(pos) + elif program[pos] == ']': + if len(open_parens) > 0: + parens[pos] = open_parens[-1] + parens[open_parens[-1]] = pos + open_parens.pop() + else: + return 'unbalanced brackets' +# if len(open_parens) != 0: +# return 'unbalanced brackets' + # now we can start interpreting + pc = 0 # program counter + mp = 0 # memory pointer + steps = 0 + memory = [0] * BUFFER_SIZE #initial memory area + rightmost = 0 + if input != None: + if type(input) == type(()): + # we'll only be using input[0] right now + inputs, input = input, input[0] + input_pointer = 0 + + output = "" #we'll save the output here + + if no_input: + eof_reached = 1 + else: + eof_reached = 0 + + # the main program loop: + while pc < len(program): + c = program[pc] + if c == '+': + memory[mp] = memory[mp] + 1 % 256 + elif c == '-': + memory[mp] = memory[mp] - 1 % 256 + elif c == '>': + mp = mp + 1 + if mp > rightmost: + rightmost = mp + if mp >= len(memory): + memory = memory + [0]*BUFFER_SIZE # no restriction on memory growth! + elif c == '<': + mp = mp - 1 % len(memory) + elif c == '.': + output += chr(memory[mp]) + if len(output) > 500: + break + + elif program[pc] == ',': + if eof_reached: + raise Exception, "Program tries reading past EOF" + if input == None: + #char = sys.stdin.read(1) + char = chr(random.randint(1,255)) + if char == '': # EOF + memory[mp] = 0 + eof_reached = 1 + else: + memory[mp] = ord(char) + else: + if input_pointer == len(input): # EOF + memory[mp] = 0 + eof_reached = 1 + else: + memory[mp] = ord(input[input_pointer]) + input_pointer = input_pointer + 1 + + elif program[pc] == '[': + if memory[mp] == 0: + pc = parens[pc] + + elif program[pc] == ']': + if memory[mp] != 0: + pc = parens[pc] + + pc += 1 + steps += 1 + if max_steps >= 0 and steps > max_steps: + output += "Maximum number of steps exceeded" + break + + # end of while loop + + return unicode(re.sub('[\r\n\x00]', '/', output), 'iso-8859-1')[:400] diff --git a/plugins/bf.pyc b/plugins/bf.pyc new file mode 100644 index 0000000..0a07a43 Binary files /dev/null and b/plugins/bf.pyc differ diff --git a/plugins/hash.py b/plugins/hash.py new file mode 100644 index 0000000..9b69126 --- /dev/null +++ b/plugins/hash.py @@ -0,0 +1,14 @@ +import hashlib + +#command +def md5(bot, input): + return hashlib.md5(input.inp).hexdigest() + +#command +def sha1(bot, input): + return hashlib.sha1(input.inp).hexdigest() + +#command +def hash(bot, input): + return ', '.join(x + ": " + getattr(hashlib, x)(input.inp).hexdigest() + for x in 'md5 sha1 sha256'.split()) diff --git a/plugins/hash.pyc b/plugins/hash.pyc new file mode 100644 index 0000000..3a5685e Binary files /dev/null and b/plugins/hash.pyc differ diff --git a/plugins/misc.py b/plugins/misc.py new file mode 100644 index 0000000..6b18de3 --- /dev/null +++ b/plugins/misc.py @@ -0,0 +1,8 @@ +#event: KICK INVITE +def rejoin(bot, input): + if input.command == 'KICK': + if input.paraml[1] == bot.bot.nick: + bot.join(input.paraml[0]) + + if input.command == 'INVITE': + bot.join(input.inp) diff --git a/plugins/misc.pyc b/plugins/misc.pyc new file mode 100644 index 0000000..9e5b463 Binary files /dev/null and b/plugins/misc.pyc differ diff --git a/plugins/pyexec.py b/plugins/pyexec.py new file mode 100644 index 0000000..f8e10d9 --- /dev/null +++ b/plugins/pyexec.py @@ -0,0 +1,16 @@ +import urllib +import re + +re_lineends = re.compile(r'[\r\n]*') + +#command +def py(bot, input): + res = urllib.urlopen("http://eval.appspot.com/eval?statement=%s" % + urllib.quote(input.inp.strip(),safe='')).readlines() + if len(res) == 0: + return + res[0] = re_lineends.split(res[0])[0] + if not res[0] == 'Traceback (most recent call last):': + return res[0] + else: + return res[-1] diff --git a/plugins/pyexec.pyc b/plugins/pyexec.pyc new file mode 100644 index 0000000..56e8a46 Binary files /dev/null and b/plugins/pyexec.pyc differ diff --git a/plugins/twitter.py b/plugins/twitter.py index 2b83896..63d8732 100644 --- a/plugins/twitter.py +++ b/plugins/twitter.py @@ -20,4 +20,4 @@ def twitter(bot, input): return "can't find that username" tweet = tweet.find('status') - bot.say(': '.join(tweet.find(x).text for x in 'user/name created_at text'.split())) + bot.say(': '.join(tweet.find(x).text for x in 'created_at user/name text'.split())) diff --git a/plugins/twitter.pyc b/plugins/twitter.pyc index 3960936..56b1b59 100644 Binary files a/plugins/twitter.pyc and b/plugins/twitter.pyc differ