Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/python
- # twisted imports
- from twisted.words.protocols import irc
- from twisted.internet import reactor, protocol, ssl, task
- from twisted.python import log
- # system imports
- import time, sys, unicodedata, re
- import zlib, socket, struct, pickle
- NUM_NATIONS = 250
- class Game:
- def __init__(self):
- self.name = ""
- self.tth = 0
- self.server=""
- self.port=0
- self.processedTurn=0
- def tthformat(self):
- days = 86400
- hour = 3600
- minute = 60
- tths = ""
- if((self.tth/1000) > days):
- tths += "%dd " % int((self.tth/1000)/days)
- r = (self.tth/1000) % days
- if(r > hour):
- tths += "%dh " % int(r/hour)
- r = r % hour
- if(r > minute):
- tths += "%dm " % int(r/minute)
- return tths
- def getdom4Status(self):
- s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- s.connect((self.server,self.port))
- s.sendall("\x66\x48\x01\x00\x00\x00\x03")
- compdata = s.recv(1024*1024)
- zdata = compdata[10:]
- data = zlib.decompress(zdata)
- retstr = ""
- ## Actually interesting data starts at byte 7
- idata = data[6:]
- #eextract the name
- name = ""
- idx = 0
- while ord(idata[idx]) > 0:
- name = name + idata[idx]
- idx+=1
- # Burn the next 7 unintersting pieces
- idx += 7
- idata = idata[idx:]
- tthl = struct.unpack('<L',idata[0:4])
- idata = idata[5:]
- nationStatus = idata[0:NUM_NATIONS]
- submitted = idata[NUM_NATIONS:NUM_NATIONS*2]
- connected = idata[NUM_NATIONS*2:NUM_NATIONS*3]
- idata = idata[NUM_NATIONS*3:]
- turnNumber = struct.unpack('<l',idata[0:4])[0]
- numNations = reduce(lambda x,y: x+y,map(lambda x:1 if ord(x)==1 else 0,nationStatus[5:]))
- subNations = reduce(lambda x,y: x+y,map(lambda x:1 if ord(x)>0 else 0,submitted[5:]))
- self.name = name
- self.tth = tthl[0]
- self.currentTurn = turnNumber
- self.nations = numNations
- self.subNations = subNations
- def updateStatus(self, g):
- self.tth = g.tth
- self.currentTurn = g.currentTurn
- self.subNations = g.subNations
- def checkTurn(self):
- if self.currentTurn > self.processedTurn:
- self.processedTurn = self.currentTurn
- return "New turn in %s (%d)" % (self.name, self.currentTurn)
- else:
- return None
- class DiosBot(irc.IRCClient):
- nickname = 'DiosBot' # nickname
- password = '' # server pass
- def save(self):
- try:
- f = open('diosbot.txt','wb')
- pickle.dump(self.games,f)
- f.close()
- except IOError:
- return
- try:
- f = open('diosbotr.txt','wb')
- pickle.dump(self.remember,f)
- f.close()
- except IOError:
- return
- def load(self):
- try:
- f = open('diosbot.txt','rb');
- self.games = pickle.load(f)
- f.close()
- except IOError:
- self.games = {}
- except EOFError as e:
- print e
- self.games = {}
- try:
- f = open('diosbotr.txt','rb');
- self.remember = pickle.load(f)
- f.close()
- except IOError:
- self.remember = {}
- except EOFError as e:
- print e
- self.remember = {}
- def poll(self):
- """ Poll games and shit"""
- for gname, g in self.games.iteritems():
- g.getdom4Status()
- tt = g.checkTurn()
- if tt:
- self.msg(self.channel, tt)
- self.save()
- def connectionMade(self):
- irc.IRCClient.connectionMade(self)
- ## We'll use this to setup the bot.
- self.games = {}
- self.remember = {}
- self.load()
- ## Setup the polling timer Run every 10 minutes
- l = task.LoopingCall(self.poll)
- l.start(60*10)
- def connectionLost(self, reason):
- irc.IRCClient.connectionLost(self, reason)
- self.save()
- # callbacks for events
- def signedOn(self):
- """Called when bot has succesfully signed on to server."""
- self.join(self.factory.channel)
- def joined(self, channel):
- """This will get called when the bot joins the channel."""
- self.channel = channel
- def privmsg(self, user, channel, msg):
- """This will get called when the bot receives a message."""
- user = user.split('!', 1)[0]
- # Check to see if they're sending me a private message
- if channel == self.nickname:
- return
- if channel == self.factory.channel:
- ## Asking for staus by server/port
- mm = re.match(r"!status (\S+)\s+([0-9]+)",msg)
- if mm:
- ## Status Request
- g = Game()
- g.server = mm.group(1)
- g.port = int(mm.group(2))
- g.getdom4Status()
- self.msg(channel, "Game: %s Turn:%d Submitted: %d/%d Time to Host: %s" % (g.name, g.currentTurn, g.subNations, g.nations, g.tthformat()))
- if g.name in self.games.keys() :
- self.games[g.name].updateStatus(g)
- tt = self.games[g.name].checkTurn()
- if tt:
- self.msg(channel, tt)
- else:
- self.games[g.name] = g
- g.processedTurn = g.currentTurn
- self.save()
- ## Save the database to disk
- mm = re.match(r"!save", msg)
- if mm:
- self.save()
- ## Remember
- mm = re.match(r".r (\S+)\s+(.+)", msg)
- if mm:
- found = False
- subj = mm.group(1)
- obj = mm.group(2)
- for rr in self.remember.keys():
- if(rr.lower() == subj.lower()):
- old = self.remember[rr]
- self.msg(channel, "%s: Forgetting %s %s, remembring this instead" % (user, rr, old))
- self.remember[rr] = obj
- found = True
- if not found:
- self.remember[subj] = obj
- self.msg(channel, "%s: Done." % user)
- self.save()
- mm = re.match(r"\?(\S+)", msg)
- if mm:
- subj = mm.group(1)
- for rr in self.remember.keys():
- if(rr.lower() == subj.lower()):
- old = self.remember[rr]
- self.msg(channel, "%s %s" % (rr, old))
- def alterCollidedNick(self, nickname):
- return nickname+'_'
- def action(self, user, channel, msg):
- pass
- def irc_NICK(self, prefix, params):
- """Called when an IRC user changes their nickname."""
- class DiosBotFactory(protocol.ClientFactory):
- """A factory for LogBots.
- A new protocol instance will be created each time we connect to the server.
- """
- protocol = DiosBot
- def __init__(self):
- self.channel = '#dom4goons' #channel
- def clientConnectionLost(self, connector, reason):
- """If we get disconnected, reconnect to server."""
- connector.connect()
- def clientConnectionFailed(self, connector, reason):
- print "connection failed:", reason
- reactor.stop()
- if __name__ == '__main__':
- # create factory protocol and application
- f = DiosBotFactory()
- # connect factory to this host and port
- hostname = 'irc.synirc.net' # irc-server-hostname
- port = 6697 #port
- reactor.connectSSL(hostname, port, f, ssl.ClientContextFactory())
- # run bot
- reactor.run()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement