#!/usr/bin/env python # -*- coding: utf-8 -*- # # markpages.py # # Copyright 2016 GOLDERWEB – Jonathan Golder # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # MA 02110-1301, USA. # # """ Bot to mark pages which were/are subjects of redundance discussions with templates """ from datetime import datetime from pywikibot import pagegenerators from pywikibot.bot import CurrentPageBot import mwparserfromhell as mwparser import jogobot from lib.redfam import RedFamWorker class MarkPagesBot( CurrentPageBot ): # sets 'current_page' on each treat() """ Bot class to mark pages which were/are subjects of redundance discussions with templates """ def __init__( self, genFactory, **kwargs ): """ Constructor Parameters: @param genFactory GenFactory with parsed pagegenerator args to build generator @type genFactory pagegenerators.GeneratorFactory @param **kwargs Additional args @type iterable """ # Init attribute self.__redfams = None # Will hold a generator with our redfams # We do not use predefined genFactory as there is no sensefull case to # give a generator via cmd-line for this right now self.genFactory = pagegenerators.GeneratorFactory() # Build generator with genFactory self.build_generator() # Run super class init with builded generator super( MarkPagesBot, self ).__init__(generator=self.gen) @property def redfams(self): """ Holds redfams generator to work on in this bot """ # Create generator if not present if not self.__redfams: end_after = datetime.strptime( jogobot.config["red.markpages"]["mark_done_after"], "%Y-%m-%d" ) self.__redfams = RedFamWorker.gen_by_status_and_ending( "archived", end_after) return self.__redfams def build_generator( self ): """ Builds generator to pass to super class """ # Add Talkpages to work on to generatorFactory self.genFactory.gens.append( self.redfam_talkpages_generator() ) # Set generator to pass to super class self.gen = pagegenerators.PreloadingGenerator( self.genFactory.getCombinedGenerator() ) def redfam_talkpages_generator( self ): """ Wrappers the redfam.article_generator and passes it to pagegenerators.PageWithTalkPageGenerator(). Then it iterates over the generator and adds a reference to the related redfam to each talkpage-object. """ for redfam in self.redfams: # We need the talkpage (and only this) of each existing page for talkpage in pagegenerators.PageWithTalkPageGenerator( redfam.article_generator( filter_existing=True, exclude_article_status=["marked"] ), return_talk_only=True ): # Add reference to redfam to talkpages talkpage.redfam = redfam yield talkpage def treat_page( self ): """ Handles work on current page We get a reference to related redfam in current_page.redfam """ # First we need to have the current text of page # and parse it as wikicode self.current_wikicode = mwparser.parse( self.current_page.text ) # Add notice self.add_disc_notice_template() # Convert wikicode back to string to save self.new_text = str( self.current_wikicode ) # Define edit summary summary = jogobot.config["red.markpages"]["mark_done_summary"].format( reddisc=self.current_page.redfam.get_disc_link() ).strip() # Make sure summary starts with "Bot:" if not summary[:len("Bot:")] == "Bot:": summary = "Bot: " + summary.strip() # Save self.put_current( self.new_text, summary=summary ) def add_disc_notice_template( self ): """ Will take self.current_wikicode and adds disc notice template after the last template in leading section or as first element if there is no other template in leading section """ # The notice to add self.disc_notice = \ self.current_page.redfam.generate_disc_notice_template() # Check if it is already present in wikicode if self.disc_notice_present(): return False # Find the right place to insert notice template # Therfore we need the first section (if there is one) leadsec = self.current_wikicode.get_sections( flat=False, include_lead=True )[0] # There is none on empty pages, so we need to check if leadsec: # Get the last template in leadsec ltemplate = leadsec.filter_templates()[-1] # If there is one, add notice after this if ltemplate: self.current_wikicode.insert_after(ltemplate, self.disc_notice) # To have it in its own line we need to add a linbreak before self.current_wikicode.insert_before(self.disc_notice, "\n" ) # If there is no template, add before first element on page else: self.current_wikicode.insert( 0, self.disc_notice ) # If there is no leadsec (and therefore no template in it, we will add # before the first element else: self.current_wikicode.insert( 0, self.disc_notice ) # Notice was added return True def disc_notice_present(self): """ Checks if disc notice which shall be added is already present. """ # Iterate over Templates with same name (if any) to search equal # Link to decide if they are the same for present_notice in self.current_wikicode.ifilter_templates( matches=self.disc_notice.name ): # Get reddisc page.title of notice to add add_notice_link_tile = self.disc_notice.get( "Diskussion").partition("#")[0] # Get reddisc page.title of possible present notice present_notice_link_tile = present_notice.get( "Diskussion").partition("#")[0] # If those are equal, notice is already present if add_notice_link_tile == present_notice_link_tile: return True # If nothing is found, loop will run till its end else: return False