#!/usr/bin/env python3"""This script fixes links that contain common spelling mistakes.This is only possible on wikis that have a template for these misspellings.Command line options: -always:XY instead of asking the user what to do, always perform the same action. For example, XY can be "r0", "u" or "2". Be careful with this option, and check the changes made by the bot. Note that some choices for XY don't make sense and will result in a loop, e.g. "l" or "m". -main only check pages in the main namespace, not in the Talk, Project, User, etc. namespaces. -start:XY goes through all misspellings in the category on your wiki that is defined (to the bot) as the category containing misspelling pages, starting at XY. If the -start argument is not given, it starts at the beginning."""## (C) Pywikibot team, 2007-2024## Distributed under the terms of the MIT license.#from__future__importannotationsfromitertoolsimportchainfromtypingimportGeneratorimportpywikibotfrompywikibotimporti18n,pagegeneratorstry:fromscripts.solve_disambiguationimport(DisambiguationRobotasBaseDisambigBot,)exceptModuleNotFoundError:frompywikibot_scripts.solve_disambiguationimport(DisambiguationRobotasBaseDisambigBot,)HELP_MSG="""\nmisspelling.py does not support site {site}.Help Pywikibot team to provide support for your wiki by submittinga bug to:https://phabricator.wikimedia.org/maniphest/task/edit/form/1/?tags=pywikibot-corewith category containing misspelling pages or a template forthese misspellings.\n"""
[docs]classMisspellingRobot(BaseDisambigBot):"""Spelling bot."""misspelling_templates={'wikipedia:de':('Falschschreibung','Obsolete Schreibung'),}# Optional: if there is a category, one can use the -start parametermisspelling_categories=('Q8644265','Q9195708')update_options={'start':None}@propertydefgenerator(self)->Generator[pywikibot.Page]:"""Generator to retrieve misspelling pages or misspelling redirects."""templates=self.misspelling_templates.get(self.site.sitename)categories=[catforcatin(self.site.page_from_repository(item)foriteminself.misspelling_categories)ifcatisnotNone]iftemplates:pywikibot.info('<<yellow>>Working on templates...')ifisinstance(templates,str):templates=(templates,)generators=(pywikibot.Page(self.site,template_name,ns=10).getReferences(follow_redirects=False,only_template_inclusion=True)fortemplate_nameintemplates)ifself.opt.start:pywikibot.info('-start parameter is not supported on this wiki\n''because templates are used for misspellings.')elifcategories:pywikibot.info('<<yellow>>Working on categories...')generators=(pagegenerators.CategorizedPageGenerator(cat,recurse=True,start=self.opt.start)forcatincategories)else:pywikibot.info(HELP_MSG.format(site=self.site))returnyield frompagegenerators.PreloadingGenerator(chain(*generators))
[docs]deffindAlternatives(self,page)->bool:"""Append link target to a list of alternative links. Overrides the BaseDisambigBot method. :return: True if alternate link was appended """ifpage.isRedirectPage():self.opt.pos.append(page.getRedirectTarget().title())returnTruesitename=page.site.sitenametemplates=self.misspelling_templates.get(sitename)iftemplatesisNone:returnFalseifisinstance(templates,str):templates=(templates,)fortemplate,paramsinpage.templatesWithParams():iftemplate.title(with_ns=False)intemplates:# The correct spelling is in the last parameter.correct_spelling=params[-1]# On de.wikipedia, there are some cases where the# misspelling is ambiguous, see for example:# https://de.wikipedia.org/wiki/Buthanformatchinself.linkR.finditer(correct_spelling):self.opt.pos.append(match['title'])ifnotself.opt.pos:# There were no links in the parameter, so there is# only one correct spelling.self.opt.pos.append(correct_spelling)returnTruereturnFalse
[docs]defsetSummaryMessage(self,page,*args,**kwargs)->None:"""Setup the summary message. Overrides the BaseDisambigBot method. """# TODO: setSummaryMessage() in solve_disambiguation now has parameters# new_targets and unlink. Make use of these here.self.summary=i18n.twtranslate(self.site,'misspelling-fixing',{'page':page.title()})
[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=='always':# the option that's always selected when the bot wonders# what to do with a link. If it's None, the user is prompted# (default behaviour).options[opt]=valueelifopt=='start':options[opt]=valueorpywikibot.input('At which page do you want to start?')elifopt=='main':options[opt]=Truebot=MisspellingRobot(**options)bot.run()