#!/usr/bin/env python3r"""This script can be used for reverting certain edits.The following command line parameters are supported:-username Edits of which user need to be reverted. Default is bot's username (:code:`site.username()`).-rollback Rollback edits instead of reverting them. .. note:: No diff would be shown in this mode.-limit:num [int] Use the last num contributions to be checked for revert. Default is 500.Users who want to customize the behaviour should subclass the `BaseRevertBot`and override its `callback` method. Here is a sample:.. code:: python class myRevertBot(BaseRevertBot): '''Example revert bot.''' def callback(self, item) -> bool: '''Sample callback function for 'private' revert bot. :param item: an item from user contributions :type item: dict ''' if 'top' in item: page = pywikibot.Page(self.site, item['title']) text = page.get(get_redirect=True) pattern = re.compile(r'\[\[.+?:.+?\..+?\]\]') return bool(pattern.search(text)) return False"""## (C) Pywikibot team, 2008-2024## Distributed under the terms of the MIT license.#from__future__importannotationsimportpywikibotfrompywikibotimporti18nfrompywikibot.backportsimportContainerfrompywikibot.botimportOptionHandlerfrompywikibot.dateimportformat_date,formatYearfrompywikibot.exceptionsimportAPIError,Error
[docs]classBaseRevertBot(OptionHandler):"""Base revert bot. Subclass this bot and override callback to get it to do something useful. """available_options={'comment':'','rollback':False,'limit':500}def__init__(self,site=None,**kwargs)->None:"""Initializer."""self.site=siteorpywikibot.Site()self.user=kwargs.pop('user',self.site.username())super().__init__(**kwargs)
[docs]deflocal_timestamp(self,ts)->str:"""Convert Timestamp to a localized timestamp string. .. versionadded:: 7.0 """year=formatYear(self.site.lang,ts.year)date=format_date(ts.month,ts.day,self.site)*_,time=str(ts).strip('Z').partition('T')return' '.join((date,year,time))
[docs]defrevert(self,item)->str|bool:"""Revert a single item."""page=pywikibot.Page(self.site,item['title'])history=list(page.revisions(total=2))iflen(history)<=1:returnFalserev=history[1]pywikibot.info('\n\n>>> <<lightpurple>>{}<<default>> <<<'.format(page.title(as_link=True,force_interwiki=True,textlink=True)))ifnotself.opt.rollback:comment=i18n.twtranslate(self.site,'revertbot-revert',{'revid':rev.revid,'author':rev.user,'timestamp':self.local_timestamp(rev.timestamp)})ifself.opt.comment:comment+=': '+self.opt.commentold=page.textpage.text=page.getOldVersion(rev.revid)pywikibot.showDiff(old,page.text)page.save(comment)returncommenttry:self.site.rollbackpage(page,user=self.user,markbot=True)exceptAPIErrorase:ife.code=='badtoken':pywikibot.error('There was an API token error rollbacking the edit')returnFalseexceptError:passelse:return(f'The edit(s) made in {page.title()} by {self.user}'' was rollbacked')pywikibot.exception(exc_info=False)returnFalse
# for compatibility onlymyRevertBot=BaseRevertBot# noqa: N816
[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={}forarginpywikibot.handle_args(args):opt,_,value=arg.partition(':')ifnotopt.startswith('-'):continueopt=opt[1:]ifopt=='username':options['user']=valueorpywikibot.input('Please enter username of the person you want to revert:')elifopt=='rollback':options[opt]=Trueelifopt=='limit':options[opt]=int(value)bot=myRevertBot(**options)bot.revert_contribs()