#!/usr/bin/python # -*- coding: euc-kr -*- # Python Dicebot "Utgard Loki" Ver 0.1 # http://paul.giannaros.org/sandbox_pythonircbotmodule ¿¡ ³ª¿Â IRCBotÀ» ±â¹ÝÀ¸·Î Á¦ÀÛÇß½À´Ï´Ù. # Based on the IRCBot module at http://paul.giannaros.org/sandbox_pythonircbotmodule # Áú¹®À̳ª ÄÚ¸àÆ® µîÀº ·ÎÅ°¿¡°Ô ÇØÁÖ¼¼¿ä. loki@lokasenna.pe.kr # Direct Questions and comments to Loki at loki@lokasenna.pe.kr import signal import socket, os, string, sys, re, signal, random, pickle, datetime #signal.signal(signal.SIGPIPE, signal.SIG_DFL) debug = True def dbg(s): #output for debugging if debug: print s class UtgardLoki: def __init__(self,nick,server,channels=None): """connection information @type nick: string @param nick: Bot nickname @type server: string @param server: IRC server to connect to @type channels: list @param channels: IRC channels to join on connection""" self.firstcon = True self.nick = nick self.server = server self.channels = channels self.port = 6666 self.name = "Utgard-Loki" self.sock = socket.socket( ) #socket.AF_INET, socket.SOCK_STREAM def execute(self): self.startConnect() while 1: #Endless loop reading data try: line = string.strip(self.sock.recv(1024)) lines = line.split("\n") except socket.error, msg: pass # If we received \0 then exit, we're done. if not line: break for line in lines: if line.startswith('PING '): self.send("PONG :" + line[6:]) else: self.readLines(line) #if self.channels and line.find("Welcome")!=-1 and self.firstcon==True: #self.autoJoin(self.channels) #self.firstcon = False def close(self): self.sock.close() def startConnect(self): try: self.sock.connect((self.server, self.port)) except: print "Error!" #sys.stderr.write("Error connecting to " + self.server + " on port " + str(self.port)) self.send("USER " + self.name + " storygames.kr blog.storygames.kr :" + self.name) self.send("NICK " + self.nick) def send(self, text): self.sock.send(text + "\n\r") dbg("bot->" + text) def autoJoin(self, channels): for channel in channels: self.send("JOIN " + channel) def readLines(self, line): print line channel = self.getChannel(line,False) sender = self.getSender(line) msg = line.split(" ",3) try: msgType = msg[1] except IndexError: msgType = '' try: msgSentTo = msg[2] except IndexError: msgSentTo = '' try: msgBody = msg[3] msgBody = msgBody[1:] except IndexError: msgBody ="" #print msgType if msgType.startswith("353"): self.nickList(msgBody) if channel and msgType.startswith("PRIVMSG"): #and not sender #sender = None self.msgFromChannel(channel, sender, msgBody) elif msgType.startswith("JOIN"): self.getNicks(channel) elif msgType.startswith("INVITE"): invitedChan = msgBody if not msgBody.startswith("#"): invitedChan = "#" + msgBody dbg("You have been invited to " + invitedChan) self.invitedToChannel(invitedChan, sender) elif msgType.startswith("NICK"): newNick = msgSentTo[1:] self.changedNick(sender,newNick) self.getNicks(channel) elif msgType.startswith("PART"): self.getNicks(channel) elif msgType.startswith("QUIT"): self.getNicks(channel) elif sender: ok = False if msgType.startswith("NOTICE"): ok = True elif msgType.startswith("PRIVMSG"): ok = True if ok: self.msgFromUser(sender, msgBody) elif not sender and msgType.startswith('319'): #what channel is the user on? chanslist = msgBody.split(' ') chanslist = [channame.replace('@','') for channame in chanslist] #find the log files, if any today = datetime.date.today() year = today.year month = today.month day = today.day for chan in chanslist: pass else: self.msgFromServer(msgBody) def getChannel(self, line, username=True): msg = line.split(" ",3) try: msgType = msg[1] except IndexError: msgType = '' try: msgSentTo = msg[2] except IndexError: msgSentTo = '' #no channel, get sending user name if not msgSentTo.startswith("#") and username: return self.getSender(line) elif msgSentTo.startswith("#"):# and msgSentTo.find('\n')==-1 return msgSentTo else: return None def getSender(self, line): if not line.count("!"): return None else: #from after the beginning : up to ! return line[1:line.index("!")] def sendToChannel(self, channel, msg): self.send("PRIVMSG " + channel + " :" + msg) def sendToUser(self, user, msg): self.send("PRIVMSG " + user + " :" + msg) def noticeToChannel (self, channel, msg): self.send("NOTICE " + channel + " :" + msg) def noticeToUser (self, user, msg): self.send("NOTICE " + user + " :" + msg) def msgFromChannel(self, channel, user, msg): dbg(user + " on " + channel + ": " + msg) def msgFromUser(self, user, msg): dbg(user + ": " + msg) def msgFromServer(self, msg): dbg(msg) def invitedToChannel(self, channel, user): self.send("JOIN " + channel) def changedNick(self, oldNick, newNick): pass #self.send('WHOIS '+newNick) def getNicks(self,channel): """get list of nicks""" self.send("NAMES %s" % (channel,)) def nickList(self,msgBody): """list of nicknames""" rawString = msgBody.split(":",1) channel = rawString[0].strip(" =") self.nicks = rawString[1].strip().split(" ") self.nicks = [nick.strip("@") for nick in self.nicks] #print self.nicks def getNumSize(self,msg,signify): wrds = msg.split(" ",1) wrdOne = wrds[0] if wrdOne.find(signify)==-1: #no 'd' in first word diceNum = "" diceSize = "" else: diceStats = wrdOne.split("d",1) diceNum = diceStats[0] diceSize = diceStats[1] if not diceNum: diceNum = "1" if not diceSize: diceSize = "6" return {"diceNum": diceNum, "diceSize":diceSize} def getDiceModifier(self,msg,total): wrds = msg.split(" ",1) if len(wrds) > 1: wrdsAfterFirst = wrds[1] else: wrdsAfterFirst = "" try: total = eval(str(total) + wrdsAfterFirst) wrdsAfterFirst = wrdsAfterFirst + " " except SyntaxError or ValueError: wrdsAfterFirst = "" return {"mod":wrdsAfterFirst,"total":total} def getDiceResults(self,diceNum,diceSize,symbol): num = 0 diceRes = "" while num < int(diceNum): roll = random.randint(1,int(diceSize)) diceRes = "%s%d%s" % (diceRes,roll,symbol) num = num + 1 #dice results diceRes = diceRes[:-1] #take off the trailing symbol return diceRes def getDiceList(self,diceNum,diceSize): num = 0 diceList = [] while num < int(diceNum): roll = random.randint(1,int(diceSize)) diceList.append(roll) num = num + 1 #return array of integers return diceList def getNumbers(self,msg): pos = 0 nums = [] num = '' while pos < len(msg): if msg[pos].isdigit(): num = num + msg[pos] if pos > 0: #check for minus prevletter= msg[pos-1] if prevletter == '-': num = '-' + num try: #not end of string, #but next letter not digit nextletter = msg[pos+1] if not nextletter.isdigit(): try: numerical = int(num) nums.append(numerical) except ValueError: pass num = '' pos = pos + 1 except IndexError: #end of my string try: numerical = int(num) nums.append(numerical) except ValueError: pass pos = pos +1 return nums def getRollerName(self,user,msg,leftSymbol,rightSymbol): leftIndex = msg.find(leftSymbol) rightIndex = msg.find(rightSymbol) if leftIndex==-1 or rightIndex==-1: #if there is no left or right symbol return 'boo!' + user else: leftIndex = leftIndex +1 return msg[leftIndex:rightIndex] def sortDice(self,results,symbol): diceList = results.split(symbol) diceList.sort(lambda a,b: cmp(int(a), int(b))) diceRes = symbol.join(diceList) return diceRes def rsortDice(self,results,symbol): diceList = results.split(symbol) diceList.sort(lambda a,b: cmp(int(a), int(b)), reverse=True) diceRes = symbol.join(diceList) return diceRes def takeMessage(self,msg,chan): numbers = self.getNumbers(msg) if len(numbers) > 0: howmany = numbers[0] else: howmany = 1 return {'reply':"¸Þ½ÃÁö %d°³¸¦ ¹ÞÀ» Áغñ¸¦ Çß½À´Ï´Ù. ±Ó¼Ó¸»·Î º¸³»ÁÖ¼¼¿ä." % \ howmany, 'howmany': howmany, 'channel': chan, 'messages': [], \ 'users': [], 'confirmed': []} def readFromFile(self,filename): try: #read from file readFile = open(filename,'r') readResults = pickle.load(readFile) readFile.close() except IOError: readResults = [] return readResults def writeToFile(self,data,filename): #write to file writeFile = open(filename,'w') pickle.dump(data,writeFile) writeFile.close() def main(): class basicDice(UtgardLoki): def msgFromChannel(self, channel, user, msg): diceTxt = self.parseForDice(user, msg) if diceTxt: self.noticeToChannel(channel, diceTxt) def msgFromUser(self, user, msg): diceTxt = self.parseForDice(user, msg) if diceTxt: self.noticeToUser(user, diceTxt) def parseForDice(self, user, msg): dice = self.getNumSize(msg,"d") diceNum = dice["diceNum"] diceSize = dice["diceSize"] if diceNum.isdigit() and diceSize.isdigit(): diceRes = self.getDiceResults(diceNum,diceSize,"+") diceTotal = eval(diceRes) diceModified = self.getDiceModifier(msg,diceTotal) diceMod = diceModified["mod"] diceTotal = diceModified["total"] if msg.find("Á¤·Ä")!=-1: if msg.find("¿ª")!=-1 or msg.find("°Å²Ù·Î")!=-1: diceRes = self.rsortDice(diceRes,"+") else: diceRes = self.sortDice(diceRes,"+") #elif diceMod!="": #diceTotal = eval("%d %s" % (diceTotal,diceMod)) #diceMod = diceMod + " " diceTxt = "%s´ÔÀÇ ±¼¸²Àº %sd%s (%s) %s= %d ÀÔ´Ï´Ù." % \ (user,diceNum,diceSize,diceRes,diceMod,diceTotal) return diceTxt else: return None bot = basicDice(raw_input("´Ð: "), raw_input("¼­¹ö: "),['#ÀÌ¿À´Ð½º']) bot.execute() #bot.close() #Run this if no imported module if __name__ == "__main__": main()