User:WdefconBot

{{bot|Misza13|status=unapproved}}

{{emergency-bot-shutoff}}

This bot's IRC companion sits in the [irc://freenode/cvn-wp-en cvn-wp-en] channel and uses this account to edit {{tl|Wdefcon}} on request made in the channel.

Detailed instructions: tools:~misza13/cgi-bin/wdefconbot.py

Archived approval of the bot is available at Wikipedia:Bots/Requests for approvals/Archive4#User:WdefconBot

= 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.

  1. !/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=|noinclude2=}}')

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=')

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()