#!/usr/bin/env python3"""Delink removed files from wiki.This script keeps track of image deletions and delinks removed filesfrom current wiki in namespace 0. This script is suitable to delinkfiles from an image repository as well as for local images.The following parameters are supported:-exclude: If the deletion log contains this pattern, the file is not delinked (default is 'no-delink').-localonly Retrieve deleted File pages from local log only-since: Start the deletion log with this timestamp given in MediaWiki timestamp format. If no `-since` option is given, the start timestamp is read from setting file. If the option is empty, the processing starts from the very beginning. If the script stops, the last timestamp is written to the settings file and the next script call starts there if no `-since` is given... note:: This sample script is a :class:`ConfigParserBot <bot.ConfigParserBot>`. All settings can be made either by giving option with the command line or with a settings file which is scripts.ini by default. If you don't want the default values you can add any option you want to change to that settings file below the [delinker] section like... versionadded:: 7.2 This script is completely rewriten from compat branch."""## (C) Pywikibot team, 2006-2023## Distributed under the terms of the MIT license.#from__future__importannotationsimportconfigparserimportheapqimportreimportpywikibotfrompywikibot.backportsimportremoveprefixfrompywikibot.botimport(AutomaticTWSummaryBot,ConfigParserBot,SingleSiteBot,calledModuleName,)frompywikibot.textlibimportcase_escape,ignore_case
[docs]classCommonsDelinker(SingleSiteBot,ConfigParserBot,AutomaticTWSummaryBot):"""Bot to delink deleted images."""update_options={'exclude':'no-delink','localonly':False,'since':'',}summary_key='delinker-delink'@propertydefgenerator(self):"""Read deletion logs and yield the oldest entry first."""ts=(pywikibot.Timestamp.fromtimestampformat(self.opt.since)ifself.opt.sinceelseNone)params={'logtype':'delete','namespace':6,'reverse':True,'start':ts,}iterables=[self.site.logevents(**params)]repo=self.site.image_repository()ifnotself.opt.localonlyelseNoneifrepo:iterables.append(repo.logevents(**params))forentryinheapq.merge(*iterables,key=lambdaevent:event.timestamp()):self.last_ts=entry.timestamp()ifentry['action']=='delete' \
andself.opt.excludenotinentry.get('comment',''):yieldentry
[docs]definit_page(self,item)->pywikibot.page.FilePage:"""Upcast logevent to FilePage and combine edit summary."""self.summary_parameters=dict(item)returnpywikibot.FilePage(self.site,item['title'])
[docs]defskip_page(self,page)->bool:"""Skip pages which neither exists locally nor on shared repository."""pywikibot.info('.',newline=False)ifpage.file_is_shared()orpage.exists():returnTruereturnsuper().skip_page(page)
[docs]deftreat(self,file_page):"""Set page to current page and delink that page."""# use image_regex from image.pynamespace=file_page.site.namespaces[6]escaped=case_escape(namespace.case,file_page.title(with_ns=False),underscore=True)self.image_regex=re.compile(r'\[\[ *(?:{})\s*:\s*{} *(?P<parameters>\|'r'(?:[^\[\]]|\[\[[^\]]+\]\]|\[[^\]]+\])*|) *\]\]'.format('|'.join(ignore_case(s)forsinnamespace),escaped))shown=Falseforpageinfile_page.using_pages(content=True,namespaces=0):ifnotshown:pywikibot.info('\n>>> <<lightgreen>>Delinking {}<<default>> <<<'.format(file_page.title()))shown=Truesuper().treat(page)
[docs]deftreat_page(self):"""Delink a single page."""new=re.sub(self.image_regex,'',self.current_page.text)self.put_current(new)
[docs]defteardown(self):"""Save the last used logevent timestamp."""ifnothasattr(self,'last_ts'):returnpywikibot.info(f"\nUpdate 'since' to {self.INI} file")conf=configparser.ConfigParser(inline_comment_prefixes=[';'])conf.read(self.INI)section=calledModuleName()ifnotconf.has_section(section):conf.add_section(section)conf.set(section,'since',self.last_ts.totimestampformat())withopen(self.INI,'w')asf:conf.write(f)
[docs]defmain(*args:str)->None:""" Process command line arguments and invoke bot. If args is an empty list, sys.argv is used. :param args: command line arguments """options={}local_args=pywikibot.handle_args()forarginlocal_args:opt,_,value=arg.partition(':')opt=removeprefix(opt,'-')ifopt=='localonly':options[opt]=Trueelse:options[opt]=valuebot=CommonsDelinker(site=pywikibot.Site(),**options)bot.run()