User:WdefconBot
From Wikipedia, the free encyclopedia
Emergency bot shutoff button |
Administrators: Use this button if the bot is malfunctioning.
Non-administrators can report misbehaving bots to Wikipedia:Administrators' noticeboard/Incidents. |
This bot's IRC companion sits in the #vandalism-en-wp channel and uses this account to edit {{Wdefcon}} on request made in the channel.
Archived approval of the bot is available at Wikipedia:Bots/Requests for approvals/Archive4#User:WdefconBot
[edit] Source
This is the bot's source code. It assumes that the file lies in the pywikipedia/ directory (an already logged-in pywikipedia framework is required to work) and is executed from there. To adjust the configuration, modify constants specified at the end of file.
#!/usr/bin/env python import re, socket, time, wikipedia class WdefconBot: def __init__(self): self.LASTLEVEL = '0' self.LASTEDITED = 0 self.LOGfile = open('defbotlog.txt', 'a+') self.site = wikipedia.getSite() self.IRC = socket.socket(socket.AF_INET,socket.SOCK_STREAM) def log(self,nick,text): TIME = time.gmtime() self.LOGfile.write("[%04d-%02d-%02d %02d:%02d.%02d] (%s) :%s\n" % (TIME[0:6] + (nick, text))) self.LOGfile.flush() def irc_conn(self,server,port): self.IRC.connect((server,port)) def login(self,nickname, password, username, realname, hostname='hostname', servername='server'): self.IRC.send("PASS %s\n" % password) self.IRC.send("USER %s %s %s :%s\n" % (username, hostname, servername, realname)) self.IRC.send("NICK %s\n" % nickname) self.nick = nickname def join(self,channel): self.IRC.send("JOIN %s\n" % channel) self.channel = channel def do_say(self,target,text): self.IRC.send("PRIVMSG %s :%s\n" % (target, text)) def do_ctcp(self,target,text): self.IRC.send("PRIVMSG %s :\001%s\001\n" % (target, text)) def user_access(self,hostmask): asteriskRE = re.compile('\*') for mask in ACCESSLIST.keys(): maskRE = re.compile(asteriskRE.sub('.*?',mask)) if maskRE.match(hostmask): return ACCESSLIST[mask] return 0 def get_defcon(self): wdefcon = wikipedia.Page(self.site,"Template:Wdefcon") text = wdefcon.get() p = text.find('\n|level=') if p == -1: return ("-1",""); p1 = text.find('\n|info=') p2 = text.find('\n|align=') if p1 == -1 or p2 == -1: return (text[p+8], "Unknown. Template damaged?") info = text[p1+7:p2] info = re.compile('\n|<!--.*?-->|<.+?>').sub('',info) info = re.compile('\[\[[^\|]*\|(.*)\]\]').sub(r'\1',info) info = re.compile('\[\[([^\|]*?)\]\]').sub(r'\1',info) return (text[p+8],info) def do_defcon_check(self,force): defcon = self.get_defcon() if defcon[0] == self.LASTLEVEL and force == 0: return self.log("WdefconBot","Wdefcon level is %s and the description is: %s" % defcon) self.LASTLEVEL = defcon[0] if defcon[0] == -1: self.do_say(self.channel,"Error while retrieving level! Template vandalised?") else: self.do_say(self.channel,"The current WikiDefcon level is %s and the description is: %s" % defcon) def main_loop(self): try: while True: buffer = self.IRC.recv(1024) if buffer == '': break msg = buffer.split() if msg[0] == "PING": self.IRC.send("PONG %s\n" % msg[1]) if msg[1] == 'PRIVMSG' and msg[2].lower() == NICKNAME.lower() and msg[3].find('VERSION') != -1: nick = msg[0][:msg[0].find("!")].lstrip(':') print "Replying to VERSION by %s..." % nick self.IRC.send('NOTICE %s :\001VERSION Misza\'s WdefconBot 2.0\001\n' % nick) if nick == 'freenode-connect': self.join(CHANNEL) continue if msg[1] == 'PRIVMSG': self.log(msg[0].lstrip(':'),' '.join(msg[3:]).lstrip(':')) command = msg[3].lower().lstrip(':') if command == 'force': if self.user_access(msg[0]) >= 80: self.IRC.send(' '.join(msg[4:])+'\n') continue if command == 'say': if bot.user_access(msg[0]) >= 50: self.do_say(self.channel,' '.join(msg[4:])) continue if command == 'act': if bot.user_access(msg[0]) >= 50: self.do_ctcp(self.channel,'ACTION ' + ' '.join(msg[4:])) continue if command == 'msg': if bot.user_access(msg[0]) >= 60: self.do_say(msg[4],' '.join(msg[5:])) continue if command == 'ctcp': if bot.user_access(msg[0]) >= 60: self.do_ctcp(msg[4],' '.join(msg[5:])) continue if command == 'quit': if self.user_access(msg[0]) >= 0: self.IRC.send("PART %s :Bye!\n" % CHANNEL) self.IRC.send("QUIT\n") continue if msg[1] == 'PRIVMSG' and msg[2] == CHANNEL: nick_name = msg[0][:msg[0].find("!")] nick = nick_name.lstrip(':') command = msg[3].lower().lstrip(':') params = ' '.join(msg[4:]) if command == '!wdefcon' and self.user_access(msg[0]) >= 0: self.log(msg[0].lstrip(':'),'!wdefcon '+params) if params == '': self.do_defcon_check(1) continue edit = re.match('edit level=([0-5]) info=(.*)',params) if edit: TIME = time.time() if TIME - self.LASTEDITED < EDITINTERVAL*60: self.do_say(self.channel,nick + ': I have edited %0.1f minutes ago. I\'m disallowed to edit faster than once every %d minutes.' % ((TIME-self.LASTEDITED)/60, EDITINTERVAL)) continue self.LASTEDITED = TIME wdefcon = wikipedia.Page(self.site,TEMPLATEPAGE) wikipedia.setAction('Changing level to '+ edit.group(1)+' on behalf of IRC user '+nick) wdefcon.put('{{subst:User:MiszaBot/Wdefcon template|level=' + edit.group(1)+'|info='+edit.group(2)+' —IRC user \'\''+nick+ '\'\' ~~~~~|noinclude1=<noinclude>|noinclude2=</noinclude>}}') self.do_ctcp(self.channel, 'ACTION has set the WikiDefcon level to %s and description to "%s"' % edit.groups()) continue self.do_say(self.channel,nick+ ': Syntax for editing is: !wdefcon edit level=[0-5] info=<situation description>') continue if re.match('\[\[User:.*?\]\].*?\[\[Template:Wdefcon\]\].*?".*"',' '.join(msg[3:])): self.do_defcon_check(0) continue finally: self.LOGfile.close() wikipedia.stopme() if __name__ == '__main__': SERVER = 'irc.freenode.net' PORT = 6667 NICKNAME = 'WdefconBot2' #Put your bot's nickname PASSWORD = 'XXXXX' #Put your NickServ password here USERNAME = 'defcon' REALNAME = 'Misza\'s WdefconBot 2.0' CHANNEL = '#vcn-tech' #Channel to work in (needs a pgkbot clone to report changes) TEMPLATEPAGE = 'Template:Wdefcon' ACCESSLIST = { #Add users' hostmasks and their access levels (100 being owner) '*!*@wikimedia/Misza13': 100 } #Set a user's access negative to make the bot ignore him EDITINTERVAL = 5 #Minimal timespan (in minutes) between edits bot = WdefconBot() bot.irc_conn(SERVER,PORT) bot.login(NICKNAME,PASSWORD,USERNAME,REALNAME) bot.join(CHANNEL) bot.main_loop()