#!/usr/bin/python # Edit a Wikipedia article with your favourite editor. Requires Python 2.3. # See Talk page for usage instructions # # (C) Jpatokal 2005-2006 # Heavily based on editarticle.py by Gerrit Holl 2004 # Distribute under the terms of the PSF license. # # Heavily based on __metaclass__ = type __version__ = "$Id: post.py,v 1.1.1.1 2006/04/25 17:15:44 gnosis Exp $" sig = u"Automated upload" #sig = u"Automated import of CIA World Factbook 2002" import sys import os import httplib import urllib import getpass import difflib import optparse import tempfile import re import codecs import wikipedia import login import config class EditArticle: import string joinchars = string.letters + '[]' + string.digits # join lines if line starts with this ones def __init__(self, args): """Takes one argument, usually this is sys.argv[1:]""" self.all_args = args self.set_options() def initialise_data(self): """Login, set editor, page and pagelink attributes""" self.login()#anonymous=self.options.anonymous) self.editor = self.options.editor or wikipedia.input(u"Editor to use:") def login(self):#, anonymous): """Initialises site and username data"""#, or anonymous""" if False:#anonymous: self.site = wikipedia.getSite(user=None) else: self.username = self.options.username or wikipedia.input(u"Username:") self.site = wikipedia.getSite(user=self.username) #self.site._fill() # load cookies #if not self.site._loggedin: # password = getpass.getpass("Password: ") # cookie = login.login(self.site, self.username, password) # if not cookie: # sys.exit("Login failed") # login.storecookiedata(cookie, self.site, self.username) # wikipedia.output(u"Login succesful") def set_options(self): """Parse commandline and set options attribute""" my_args = [] for arg in self.all_args: arg = wikipedia.argHandler(arg, 'editarticle') if arg: my_args.append(arg) parser = optparse.OptionParser() ## parser.add_option("-a", "--anonymous", action="store_true", default=False, help="Login anonymously") parser.add_option("-r", "--edit_redirect", action="store_true", default=False, help="Ignore/edit redirects") parser.add_option("-u", "--username", help="Username to login with (ignored with -a)") parser.add_option("-p", "--page", help="Page to edit") parser.add_option("-e", "--editor", help="Editor to use") parser.add_option("-j", "--join_lines", action="store_true", default=False, help="Join consecutive lines if possible") parser.add_option("-w", "--watch", action="store_true", default=False, help="Watch article after edit") parser.add_option("-n", "--new_data", default="", help="Data to insert in template") parser.add_option("-t", "--template", default="", help="Template for article creation") self.options = parser.parse_args(args=my_args)[0] def setpage(self): """Sets page and pagelink""" self.pagelink = wikipedia.Page(self.site, self.page) if not self.options.edit_redirect and self.pagelink.isRedirectPage(): self.pagelink = wikipedia.Page(site, self.pagelink.getRedirectTarget()) def repair(self, content): """Removes single newlines and prepare encoding for local wiki""" if self.options.join_lines: lines = content.splitlines() result = [] for i, line in enumerate(lines): try: nextline = lines[i+1] except IndexError: nextline = "last" result.append(line) if line.strip() == "" or line[0] not in self.joinchars or \ nextline.strip() == "" or nextline[0] not in self.joinchars: result.append('\n') else: result.append(" ") s = "".join(result) else: s = content return wikipedia.unicode2html(s, self.site.encoding()) def edit(self): """Edit the page using the editor. It returns two strings: the old version and the new version.""" # Parse data file to figure out article variables and sub them into template newcontent = codecs.open(self.options.template, 'r', 'utf8').read() for line in codecs.open(self.options.new_data, 'r', 'utf8').readlines(): data = line.strip().split('=') newcontent = re.sub('\$' + data[0], data[1], newcontent) if(data[0] == 'NAME'): self.page = data[1] # Change any remaining unresolved variables into question marks for x in ['CAPITAL', 'LANGUAGE', 'CURRENCY', 'TEL', 'DOMAIN', 'AREA', 'POPULATION']: newcontent = re.sub('\$' + x, '?', newcontent) # Read existing article for comparison self.setpage() try: oldcontent = self.pagelink.get() except wikipedia.NoPage: oldcontent = "" except wikipedia.IsRedirectPage: if self.options.redirect: oldcontent = self.pagelink.get(force=True, get_redirect=redirect) else: raise return oldcontent, newcontent def getcomment(self): comment = sig # wikipedia.input(u"What did you change? ") + sig comment = wikipedia.unicode2html(comment, self.site.encoding()) return wikipedia.unicode2html(comment, self.site.encoding()) def handle_edit_conflict(self): fn = os.path.join(tempfile.gettempdir(), self.page) fp = open(fn, 'w') fp.write(new) fp.close() wikipedia.output(u"An edit conflict has arisen. Your edit has been saved to %s. Please try again." % fn) def showdiff(self,old, new): diff = difflib.context_diff(old.splitlines(), new.splitlines()) wikipedia.output(u"\n".join(diff)) def run(self): self.initialise_data() # check if blocked allowed = self.site.allowed() if False: sys.exit("Bot blocked!"); try: old, new = self.edit() except wikipedia.LockedPage: sys.exit("You do not have permission to edit %s" % self.pagelink.sectionFreeTitle()) if old != new: new = self.repair(new) self.showdiff(old, new) comment = self.getcomment() try: self.pagelink.put(new, comment=comment, minorEdit=False, watchArticle=self.options.watch)#, anon=self.options.anonymous) except wikipedia.EditConflict: self.handle_edit_conflict() else: wikipedia.output(u"Nothing changed") def main(): app = EditArticle(sys.argv[1:]) app.run() if __name__ == "__main__": try: main() except: wikipedia.stopme() raise wikipedia.stopme()