import socket import MySQLdb import sys import re import string import time import threading import os class database: def __init__(self, dbuser, dbpw, database, dbhost='localhost'): self.db = MySQLdb.connect(host=dbhost, user=dbuser, passwd=dbpw, db=database) self.cursor = self.db.cursor() self.host = dbhost self.user = dbuser self.pw = dbpw self.db = database def query(self, query): try: return self.cursor.execute(query) except: self = database(self.user, self.pw, self.db, self.host) return self.cursor.execute(query) def getone(self): return self.cursor.fetchone() def getall(self): return self.cursor.fetchall() class irc: def __init__(self): self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.nick = "pyirclib" self.host = None self.hmsg = None self.name_regex = re.compile(':.*?!') self.end = 0 self.logging = 0 def send(self, data): self.socket.send("%s\r\n" % data) def join(self, channel, sender='sys', rec='sysproc'): self.send("JOIN %s" % channel) self.log(sender, rec, 'Joining %s' % channel) def connect(self, server, port=6667): self.log('sys', 'sysproc', 'Connecting to %s' % server) self.socket.connect(("%s" % server, port)) self.send("NICK " + self.nick) self.send("USER %s %s None :%s" % ("tasanya", "irc.freenode.net", "pythonirc")) self.log('sys', 'sysproc', 'Socket connection initialised') self.join("#python3d") buffer = "" while(1): if self.end: break buffer += self.socket.recv(1024) data = buffer.split("\n") buffer = data.pop() self.decode(data) def get_name(self, name): match = self.name_regex.search(name) if not match: return name return match.group()[1:-1] def decode(self, data): for element in data: words = element.split(" ") if words[0] == 'NOTICE': self.handle_NOTICE(element, words) return #print element if words[0] == 'PING': self.send("PONG " + words[1]) return info = {'sender':words[0], 'command':words[1], 'recipient':words[2], 'extra':string.join(words[3:])[1:].strip()} if hasattr(self, "handle_%s" % words[1]): getattr(self, "handle_%s" % words[1])(element, info) def handle_NOTICE(self, raw, data): print raw def log(self, user, channel, event): t = time.time() if self.logging: self.db.query("INSERT INTO log VALUES (NULL, '%s', '%s', '%s', '%s')" % (user, channel, t, event)) print "%s: %s@%s - %s" % (time.strftime('%a, %d %b %Y %H:%M:%S', time.localtime()), user, channel, event) def quit(self, msg): self.send("QUIT :%s" % msg) self.end = 1 #self.socket.close() class bot(irc): def __init__(self, nick): irc.__init__(self) self.nick = nick self.logging = 0 self.db = database('timmeh', 'dinosaur', 'ircstats') self.globs = {} self.locs = {} self.timer = 0 self.length = 0 self.interval = 0 self.ticks = 0 self.timerinit = 0 self.started = 0 self.timerchannel = None self.names = {} def privilege(self, user, channel): print user, channel rows = int(self.db.query("SELECT * FROM admin WHERE user='%s' AND channel='%s'" % (user, channel))) if rows: return 1 self.sendalert(channel, '%s you have insufficient privileges to use that command' % user) self.log(user, channel, 'Unprivileged access') return 0 def handle_ERROR(self, raw, data): print "Error" print raw sys.exit(0) def sendmsg(self, rec, msg): print rec, self.sender if rec == self.nick: rec = self.sender print rec self.send('PRIVMSG %s :%s' % (rec, msg)) def sendalert(self, rec, msg): self.sendmsg(rec, '*** ' + msg + ' ***') def intervalup(self): self.ticks += 1 remaining = self.length - self.ticks * self.interval if self.started: self.sendmsg(self.timerchannel, 'Time remaining - Mins: %s, Secs: %s' % (int(remaining / 60), remaining)) self.tick = threading.Timer(self.interval, self.intervalup) def timeup(self): self.started = 0 self.sendalert(self.timerchannel, 'Time is up!!') def handle_PRIVMSG(self, raw, data): #print "Sender: %s" % data['sender'] #print "Sent: %s" %data['extra'] sender = self.get_name(data['sender']) self.sender = sender rec = data['recipient'] param = data['extra'] #quit command quit = r'~quit(?P.*)' match = re.compile(quit).search(param) if match: msg = match.group('msg') self.log(sender, rec, 'Quit issued') if self.privilege(sender, rec): self.send('ACTION %s :is going to sleep' % rec) self.quit(msg) return #add admin user command add = r'~promote (?P.*)' match = re.compile(add).search(param) if match: user = match.group('user') if self.privilege(sender, rec): self.db.query("INSERT INTO admin VALUES(NULL, '%s', '%s')" % (user, rec)) self.log(sender, rec, user + " promoted") self.sendalert(rec, "%s has been promoted" % user) return #log command log = r'~log (?Pon|off|\?)' match = re.compile(log).search(param) if match: if self.privilege(sender, rec): if match.group('switch') == 'on': self.logging = 1 self.log(sender, rec, 'Logging activated') self.sendalert(rec, 'Logging activated') if match.group('switch') == 'off': self.log(sender, rec, 'Logging deactivated') self.logging = 0 self.sendalert(rec, 'Logging deactivated') if match.group('switch') == '?': self.log(sender, rec, 'Logging enquiry') if self.logging: self.sendmsg(rec, '%s, logging is currently on' % sender) else: self.sendmsg(rec, '%s, logging is currently off' % sender) return #re command exp = r'~re ~(?P.*?)~ (?P.*?) (?P\<.*?\>)?' match = re.compile(exp).search(param) if match: exp = match.group('expr') grpdict = match.groupdict() self.log(sender, rec, 'Regular Expression Parser utilised') try: userexp = re.compile(exp) except: self.sendmsg(rec, '%s, invalid pattern' % sender) else: test = match.group('test') usermatch = userexp.search(test) if usermatch: if grpdict.has_key('group'): userdict = usermatch.groupdict() if userdict.has_key(grpdict['group'][1:-1]): self.sendmsg(rec, '%s, match for group: %s - %s' % (sender, grpdict['group'][1:-1], userdict[grpdict['group'][1:-1]])) else: self.sendmsg(rec, '%s, no group named %s exists in supplied pattern' % (sender, grpdict['group'][1:-1])) else: self.sendmsg(rec, '%s, matches: %s' % (sender, usermatch.group())) else: self.sendmsg(rec, '%s, test string does not match supplied pattern' % sender) return #math command exp = r'~math (?P.*)' match = re.compile(exp).search(param) if match: exp = match.group('expr') self.log(sender, rec, 'Math Expression Parser utilised') try: result = eval(exp, self.globs, self.locs) except: self.sendmsg(rec, '%s, invalid expression' % sender) else: self.sendmsg(rec, '%s, %s' % (sender, result)) return #assign variable pattern = r'~var (?P[a-zA-Z0-0_]+)[ ]*=[ ]*(?P.*)' match = re.compile(pattern).search(param) if match: varname = match.group('var') exp = match.group('expr') self.log(sender, rec, 'Math Expression Parser(variable assignment) utilised') try: result = eval(exp, self.globs, self.locs) except: self.sendmsg(rec, '%s, invalid right side of assignment' % sender) else: self.sendmsg(rec, '%s, %s=%s' % (sender, varname, result)) self.globs[varname] = result return #print variable value pattern = r'~var (?P[a-zA-Z0-0_]+)[ ]*\?' match = re.compile(pattern).search(param) if match: self.log(sender, rec, 'Variable value enquiry') varname = match.group('var') if self.globs.has_key(varname): self.sendmsg(rec, "%s, %s=%s" % (sender, varname, self.globs[varname])) else: self.sendmsg(rec, "%s, variable not defined" % sender) return #join channel pattern = r'~join (?P#.*)' match = re.compile(pattern).search(param) if match: channel = match.group('channel') self.join(channel, sender, rec) return #timer pattern = r'~timer (?P[0-9]*) (?P[0-9]*)' match = re.compile(pattern).search(param) if match: if not self.started: self.log(sender, rec, 'Timer initialisation') self.sendmsg(rec, 'Timer initialised, ~start to begin') self.length = int(match.group('length')) self.interval = int(match.group('interval')) self.timer = threading.Timer(self.length, self.timeup) self.tick = threading.Timer(self.interval, self.intervalup) self.timerchannel = rec self.timerinit = 1 else: self.sendmsg(rec, "%s, timer is already in use, please wait" % sender) return if param == '~start': self.started = 1 self.timer.start() self.tick.start() self.sendalert(rec, 'Timer started!!') self.log(sender, rec, 'Timer started') return if param == '~stop': self.started = 0 self.timer.cancel() self.tick.cancel() self.sendalert(rec, 'Timer stopped!!') self.log(sender, rec, 'Timer stopped') return if param == '~restart': self.log(sender, rec, 'Restart issued') self.sendmsg(rec, 'brb...restarting') self.quit('Restarting') os.execvp('python', ('python', 'irc2.py')) return self.db.query("INSERT INTO irclog VALUES (NULL, '%s', '%s', '%s')" % (sender, rec, param)) def handle_353(self, raw, data): pattern = r'=[ ]*#[a-zA-Z_]+[ ]*:(?P.*)' match = re.compile(pattern).search(data['extra']) if match: namestr = match.group('names') self.names[data[rec]] = namestr.split(' ') self.log(sender, rec, 'Received names from %s' % rec) self.log(sender, rec, 'Currently connected to %s: %s' % (rec, namestr)) client = bot('tasanaya') client.connect("irc.freenode.net", 6667)