PGhosh

add_text.py full

Jan 27th, 2014
229
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 16.07 KB | None | 0 0
  1. #!/usr/bin/python
  2. # -*- coding: utf-8  -*-
  3. """
  4. This is a Bot written by Filnik to add a text at the end of the page but above
  5. categories, interwiki and template for the stars of the interwiki (default).
  6.  
  7. Alternatively it may also add a text at the top of the page.
  8. These command line parameters can be used to specify which pages to work on:
  9.  
  10. &params;
  11.  
  12. Furthermore, the following command line parameters are supported:
  13.  
  14. -page             Use a page as generator
  15.  
  16. -talkpage         Put the text onto the talk page instead the generated on
  17. -talk
  18.  
  19. -text             Define which text to add. "\n" are interpreted as newlines.
  20.  
  21. -textfile         Define a texfile name which contains the text to add
  22.  
  23. -summary          Define the summary to use
  24.  
  25. -except           Use a regex to check if the text is already in the page
  26.  
  27. -excepturl        Use the html page as text where you want to see if there's
  28.                  the text, not the wiki-page.
  29.  
  30. -newimages        Add text in the new images
  31.  
  32. -untagged         Add text in the images that don't have any license template
  33.  
  34. -always           If used, the bot won't ask if it should add the text
  35.                  specified
  36.  
  37. -up               If used, put the text at the top of the page
  38.  
  39. -noreorder        Avoid to reorder cats and interwiki
  40.  
  41. --- Example ---
  42. 1.
  43. # This is a script to add a template to the top of the pages with
  44. # category:catname
  45. # Warning! Put it in one line, otherwise it won't work correctly.
  46.  
  47. python add_text.py -cat:catname -summary:"Bot: Adding a template"
  48. -text:"{{Something}}" -except:"\{\{([Tt]emplate:|)[Ss]omething" -up
  49.  
  50. 2.
  51. # Command used on it.wikipedia to put the template in the page without any
  52. # category.
  53. # Warning! Put it in one line, otherwise it won't work correctly.
  54.  
  55. python add_text.py -excepturl:"class='catlinks'>" -uncat
  56. -text:"{{Categorizzare}}" -except:"\{\{([Tt]emplate:|)[Cc]ategorizzare"
  57. -summary:"Bot: Aggiungo template Categorizzare"
  58.  
  59. --- Credits and Help ---
  60. This script has been written by Botwiki's staff, if you want to help us
  61. or you need some help regarding this script, you can find us here:
  62.  
  63. * http://botwiki.sno.cc
  64.  
  65. """
  66.  
  67. #
  68. # (C) Filnik, 2007-2010
  69. # (C) Pywikibot team, 2007-2013
  70. #
  71. # Distributed under the terms of the MIT license.
  72. #
  73. __version__ = '$Id: 4daa02a2f68c4c0b828f8ccfe29f85547e02712b $'
  74. #
  75.  
  76. import re
  77. import urllib2
  78. import webbrowser
  79. import codecs
  80. import time
  81.  
  82. import wikipedia as pywikibot
  83. import config
  84. from pywikibot import i18n
  85. import pagegenerators
  86.  
  87. docuReplacements = {
  88.     '&params;': pagegenerators.parameterHelp,
  89. }
  90.  
  91.  
  92. starsList = [
  93.     u'bueno',
  94.     u'bom interwiki',
  95.     u'cyswllt[ _]erthygl[ _]ddethol', u'dolen[ _]ed',
  96.     u'destacado', u'destaca[tu]',
  97.     u'enllaç[ _]ad',
  98.     u'enllaz[ _]ad',
  99.     u'leam[ _]vdc',
  100.     u'legătură[ _]a[bcf]',
  101.     u'liamm[ _]pub',
  102.     u'lien[ _]adq',
  103.     u'lien[ _]ba',
  104.     u'liên[ _]kết[ _]bài[ _]chất[ _]lượng[ _]tốt',
  105.     u'liên[ _]kết[ _]chọn[ _]lọc',
  106.     u'ligam[ _]adq',
  107.     u'ligoelstara',
  108.     u'ligoleginda',
  109.     u'link[ _][afgu]a', u'link[ _]adq', u'link[ _]f[lm]', u'link[ _]km',
  110.     u'link[ _]sm', u'linkfa',
  111.     u'na[ _]lotura',
  112.     u'nasc[ _]ar',
  113.     u'tengill[ _][úg]g',
  114.     u'ua',
  115.     u'yüm yg',
  116.     u'רא',
  117.     u'وصلة مقالة جيدة',
  118.     u'وصلة مقالة مختارة',
  119. ]
  120.  
  121.  
  122. class NoEnoughData(pywikibot.Error):
  123.     """ Error class for when the user doesn't specified all the data needed """
  124.  
  125.  
  126. class NothingFound(pywikibot.Error):
  127.     """
  128.    An exception indicating that a regex has return [] instead of results.
  129.  
  130.    """
  131.  
  132.  
  133. # Useful for the untagged function
  134. def pageText(url):
  135.     """ Function to load HTML text of a URL """
  136.     try:
  137.         request = urllib2.Request(url)
  138.         request.add_header("User-Agent", pywikibot.useragent)
  139.         response = urllib2.urlopen(request)
  140.         text = response.read()
  141.         response.close()
  142.         # When you load to many users, urllib2 can give this error.
  143.     except urllib2.HTTPError:
  144.         pywikibot.output(u"Server error. Pausing for 10 seconds... " +
  145.                          time.strftime("%d %b %Y %H:%M:%S (UTC)",
  146.                                        time.gmtime()))
  147.         response.close()
  148.         time.sleep(10)
  149.         return pageText(url)
  150.     return text
  151.  
  152.  
  153. def untaggedGenerator(untaggedProject, limit=500):
  154.     """ Function to get the pages returned by this tool:
  155.    http://toolserver.org/~daniel/WikiSense/UntaggedImages.php
  156.  
  157.    """
  158.     lang = untaggedProject.split('.', 1)[0]
  159.     project = '.' + untaggedProject.split('.', 1)[1]
  160.     URL = 'http://toolserver.org/~daniel/WikiSense/UntaggedImages.php?'
  161.     if lang == 'commons':
  162.         link = '%swikifam=commons.wikimedia.org&since=-100d&until=&img_user_text=&order=img_timestamp&max=%d&order=img_timestamp&format=html' \
  163.                % (URL, limit)
  164.     else:
  165.         link = '%swikilang=%s&wikifam=%s&order=img_timestamp&max=%d&ofs=0&max=%d' \
  166.                % (URL, lang, project, limit, limit)
  167.     text = pageText(link)
  168.     regexp = r"<td valign='top' title='Name'><a href='http://.*?\.org/w/index\.php\?title=(.*?)'>.*?</a></td>"
  169.     results = re.findall(regexp, text)
  170.     if results == []:
  171.         print link
  172.         raise NothingFound(
  173.             'Nothing found! Try to use the tool by yourself to be sure that it '
  174.             'works!')
  175.     else:
  176.         for result in results:
  177.             yield pywikibot.Page(pywikibot.getSite(), result)
  178.  
  179.  
  180. def add_text(page=None, addText=None, summary=None, regexSkip=None,
  181.              regexSkipUrl=None, always=False, up=False, putText=True,
  182.              oldTextGiven=None, reorderEnabled=True, create=False):
  183.     if not addText:
  184.         raise NoEnoughData('You have to specify what text you want to add!')
  185.     if not summary:
  186.         summary = i18n.twtranslate(pywikibot.getSite(), 'add_text-adding',
  187.                                    {'adding': addText[:200]})
  188.  
  189.     # When a page is tagged as "really well written" it has a star in the
  190.     # interwiki links. This is a list of all the templates used (in regex
  191.     # format) to make the stars appear.
  192.  
  193.     errorCount = 0
  194.     site = pywikibot.getSite()
  195.     pathWiki = site.family.nicepath(site.lang)
  196.  
  197.     if putText:
  198.         pywikibot.output(u'Loading %s...' % page.title())
  199.     if oldTextGiven is None:
  200.         try:
  201.             text = page.get()
  202.         except pywikibot.NoPage:
  203.             if create:
  204.                 pywikibot.output(u"%s doesn't exist, creating it!"
  205.                                  % page.title())
  206.                 text = u''
  207.             else:
  208.                 pywikibot.output(u"%s doesn't exist, skip!" % page.title())
  209.                 return (False, False, always)
  210.         except pywikibot.IsRedirectPage:
  211.             pywikibot.output(u"%s is a redirect, skip!" % page.title())
  212.             return (False, False, always)
  213.     else:
  214.         text = oldTextGiven
  215.     # Understand if the bot has to skip the page or not
  216.     # In this way you can use both -except and -excepturl
  217.     if regexSkipUrl is not None:
  218.         url = '%s%s' % (pathWiki, page.urlname())
  219.         result = re.findall(regexSkipUrl, site.getUrl(url))
  220.         if result != []:
  221.             pywikibot.output(
  222. u'''Exception! regex (or word) used with -exceptUrl is in the page. Skip!
  223. Match was: %s''' % result)
  224.             return (False, False, always)
  225.     if regexSkip is not None:
  226.         result = re.findall(regexSkip, text)
  227.         if result != []:
  228.             pywikibot.output(
  229. u'''Exception! regex (or word) used with -except is in the page. Skip!
  230. Match was: %s''' % result)
  231.             return (False, False, always)
  232.     # If not up, text put below
  233.     if not up:
  234.         newtext = text
  235.         # Translating the \\n into binary \n
  236.         addText = addText.replace('\\n', config.line_separator)
  237.         if (reorderEnabled):
  238.             # Getting the categories
  239.             categoriesInside = pywikibot.getCategoryLinks(newtext, site)
  240.             # Deleting the categories
  241.             newtext = pywikibot.removeCategoryLinks(newtext, site)
  242.             # Getting the interwiki
  243.             interwikiInside = pywikibot.getLanguageLinks(newtext, site)
  244.             # Removing the interwiki
  245.             newtext = pywikibot.removeLanguageLinks(newtext, site)
  246.  
  247.             # Adding the text
  248.             newtext += u"%s%s" % (config.line_separator, addText)
  249.             # Reputting the categories
  250.             newtext = pywikibot.replaceCategoryLinks(newtext,
  251.                                                      categoriesInside, site,
  252.                                                      True)
  253.             # Dealing the stars' issue
  254.             allstars = []
  255.             starstext = pywikibot.removeDisabledParts(text)
  256.             for star in starsList:
  257.                 regex = re.compile('(\{\{(?:template:|)%s\|.*?\}\}[\s]*)'
  258.                                    % star, re.I)
  259.                 found = regex.findall(starstext)
  260.                 if found != []:
  261.                     newtext = regex.sub('', newtext)
  262.                     allstars += found
  263.             if allstars != []:
  264.                 newtext = newtext.strip() + config.line_separator * 2
  265.                 allstars.sort()
  266.                 for element in allstars:
  267.                     newtext += '%s%s' % (element.strip(), config.LS)
  268.             # Adding the interwiki
  269.             newtext = pywikibot.replaceLanguageLinks(newtext, interwikiInside,
  270.                                                      site)
  271.         else:
  272.             newtext += u"%s%s" % (config.line_separator, addText)
  273.     else:
  274.         newtext = addText + config.line_separator + text
  275.     if putText and text != newtext:
  276.         pywikibot.output(u"\n\n>>> \03{lightpurple}%s\03{default} <<<"
  277.                          % page.title())
  278.         pywikibot.showDiff(text, newtext)
  279.     # Let's put the changes.
  280.     while True:
  281.         # If someone load it as module, maybe it's not so useful to put the
  282.         # text in the page
  283.         if putText:
  284.             if not always:
  285.                 choice = pywikibot.inputChoice(
  286.                     u'Do you want to accept these changes?',
  287.                     ['Yes', 'No', 'All', 'open in Browser'],
  288.                     ['y', 'n', 'a', 'b'], 'n')
  289.                 if choice == 'a':
  290.                     always = True
  291.                 elif choice == 'n':
  292.                     return (False, False, always)
  293.                 elif choice == 'b':
  294.                     webbrowser.open("http://%s%s" % (
  295.                         page.site.hostname(),
  296.                         page.site.nice_get_address(page.title())
  297.                     ))
  298.                     pywikibot.input("Press Enter when finished in browser.")
  299.             if always or choice == 'y':
  300.                 try:
  301.                     if always:
  302.                         page.put(newtext, summary,
  303.                                  minorEdit=page.namespace() != 3)
  304.                     else:
  305.                         page.put_async(newtext, summary,
  306.                                        minorEdit=page.namespace() != 3)
  307.                 except pywikibot.EditConflict:
  308.                     pywikibot.output(u'Edit conflict! skip!')
  309.                     return (False, False, always)
  310.                 except pywikibot.ServerError:
  311.                     errorCount += 1
  312.                     if errorCount < config.maxretries:
  313.                         pywikibot.output(u'Server Error! Wait..')
  314.                         time.sleep(5)
  315.                         continue
  316.                     else:
  317.                         raise pywikibot.ServerError(u'Fifth Server Error!')
  318.                 except pywikibot.SpamfilterError as e:
  319.                     pywikibot.output(
  320.                         u'Cannot change %s because of blacklist entry %s'
  321.                         % (page.title(), e.url))
  322.                     return (False, False, always)
  323.                 except pywikibot.PageNotSaved as error:
  324.                     pywikibot.output(u'Error putting page: %s' % error.args)
  325.                     return (False, False, always)
  326.                 except pywikibot.LockedPage:
  327.                     pywikibot.output(u'Skipping %s (locked page)'
  328.                                      % page.title())
  329.                     return (False, False, always)
  330.                 else:
  331.                     # Break only if the errors are one after the other...
  332.                     errorCount = 0
  333.                     return (True, True, always)
  334.         else:
  335.             return (text, newtext, always)
  336.  
  337.  
  338. def main():
  339.     # If none, the var is setted only for check purpose.
  340.     summary = None
  341.     addText = None
  342.     regexSkip = None
  343.     regexSkipUrl = None
  344.     generator = None
  345.     always = False
  346.     textfile = None
  347.     talkPage = False
  348.     reorderEnabled = True
  349.     namespaces = []
  350.     # Load a lot of default generators
  351.     genFactory = pagegenerators.GeneratorFactory()
  352.     # Put the text above or below the text?
  353.     up = False
  354.     # Loading the arguments
  355.     for arg in pywikibot.handleArgs():
  356.         if arg.startswith('-textfile'):
  357.             if len(arg) == 9:
  358.                 textfile = pywikibot.input(
  359.                     u'Which textfile do you want to add?')
  360.             else:
  361.                 textfile = arg[10:]
  362.         elif arg.startswith('-text'):
  363.             if len(arg) == 5:
  364.                 addText = pywikibot.input(u'What text do you want to add?')
  365.             else:
  366.                 addText = arg[6:]
  367.         elif arg.startswith('-summary'):
  368.             if len(arg) == 8:
  369.                 summary = pywikibot.input(u'What summary do you want to use?')
  370.             else:
  371.                 summary = arg[9:]
  372.         elif arg.startswith('-page'):
  373.             if len(arg) == 5:
  374.                 generator = [pywikibot.Page(
  375.                     pywikibot.getSite(),
  376.                     pywikibot.input(u'What page do you want to use?'))]
  377.             else:
  378.                 generator = [pywikibot.Page(pywikibot.getSite(), arg[6:])]
  379.         elif arg.startswith('-excepturl'):
  380.             if len(arg) == 10:
  381.                 regexSkipUrl = pywikibot.input(u'What text should I skip?')
  382.             else:
  383.                 regexSkipUrl = arg[11:]
  384.         elif arg.startswith('-except'):
  385.             if len(arg) == 7:
  386.                 regexSkip = pywikibot.input(u'What text should I skip?')
  387.             else:
  388.                 regexSkip = arg[8:]
  389.         elif arg.startswith('-untagged'):
  390.             if len(arg) == 9:
  391.                 untaggedProject = pywikibot.input(
  392.                     u'What project do you want to use?')
  393.             else:
  394.                 untaggedProject = arg[10:]
  395.             generator = untaggedGenerator(untaggedProject)
  396.         elif arg == '-up':
  397.             up = True
  398.         elif arg == '-noreorder':
  399.             reorderEnabled = False
  400.         elif arg == '-always':
  401.             always = True
  402.         elif arg == '-talk' or arg == '-talkpage':
  403.             talkPage = True
  404.         else:
  405.             genFactory.handleArg(arg)
  406.     if textfile and not addText:
  407.         f = codecs.open(textfile, 'r', config.textfile_encoding)
  408.         addText = f.read()
  409.         f.close()
  410.     if not generator:
  411.         generator = genFactory.getCombinedGenerator()
  412.     if not generator:
  413.         raise NoEnoughData(
  414.             'You have to specify the generator you want to use for the script!')    line (414)
  415.     if talkPage:
  416.         generator = pagegenerators.PageWithTalkPageGenerator(generator)
  417.         site = pywikibot.getSite()
  418.         for namespace in site.namespaces():
  419.             index = site.getNamespaceIndex(namespace)
  420.             if index % 2 == 1 and index > 0:
  421.                 namespaces += [index]
  422.         generator = pagegenerators.NamespaceFilterPageGenerator(
  423.             generator, namespaces)
  424.     for page in generator:
  425.         (text, newtext, always) = add_text(page, addText, summary, regexSkip,
  426.                                            regexSkipUrl, always, up, True,
  427.                                            reorderEnabled=reorderEnabled,
  428.                                            create=talkPage)
  429.  
  430. if __name__ == "__main__":
  431.     try:
  432.         main()               -(line 432)
  433.     finally:
  434.         pywikibot.stopme()
Advertisement
Add Comment
Please, Sign In to add comment