Bikarhêner:Wikihez/skrîpt/py/templsubst.py
Xuyakirin
#!/usr/bin/env python3
"""
python pwb.py updatewin -file:"templsubst.py" -s:"skip ns 10 just incase"
Skrîpta ji bo subst:kirina şablonan. Nimûne:
https://ku.wikipedia.org/w/index.php?title=Bikarh%C3%AAner:Balyozxane/ceribandin&diff=prev&oldid=1572867
Bikaranîn
Auto-run:
Works on all pages transcluding templates in category "Şablonên ku otomatîk were substkirin"
python pwb.py templsubst -always -async
Manual:
python pwb.py templsubst -ns:0 -transcludes:"Modul:CS1 translator" -always
python pwb.py templsubst -ns:0 -transcludes:"Modul:CS1 translator" -showdiff
The following parameters are supported:
-always The bot won't ask for confirmation when putting a page.
-showdiff The bot will show the differences in the console.
-async Edits will be performed asynchronously.
-summary: Set the action summary message for the edit.
Use global -simulate option for test purposes. No changes to live wiki
will be done.
"""
#
# (C) w:ku:User:Balyozxane :)
#
# Distributed under the terms of the MIT license.
#
import pywikibot
from pywikibot import pagegenerators
from pywikibot.bot import (
AutomaticTWSummaryBot,
ConfigParserBot,
ExistingPageBot,
SingleSiteBot,
)
from kucosmetics import CANCEL, CosmeticChangesToolkit
import mwparserfromhell
import mytools
# This is required for the text that is shown when you run this script
# with the parameter -help.
docuReplacements = {'¶ms;': pagegenerators.parameterHelp} # noqa: N816
TESTING = False
VERBOSE = False
class TemplSubstBot(
# Refer pywikobot.bot for generic bot classes
SingleSiteBot, # A bot only working on one site
ConfigParserBot, # A bot which reads options from scripts.ini setting file
# CurrentPageBot, # Sets 'current_page'. Process it in treat_page method.
# # Not needed here because we have subclasses
ExistingPageBot, # CurrentPageBot which only treats existing pages
AutomaticTWSummaryBot, # Automatically defines summary; needs summary_key
):
use_redirects = False # treats non-redirects only
summary_key = 'basic-changing'
def __init__(self, **kwargs):
self.templates = kwargs.pop('templates', [])
super().__init__(**kwargs)
global VERBOSE
VERBOSE = self.opt.get("showdiff", False)
self.bot_name = "Bikarhêner:Balyozxane/skrîpt/py/templsubst.py"
self.cat_title = "Kategorî:Şablonên ku otomatîk were substkirin"
self.templates = self.include_redirects()
if VERBOSE:
print(self.templates)
update_options = {
'async': False,
'showdiff': False,
'ignore': CANCEL.MATCH,
}
def include_redirects(self):
with_redir = set()
for template in self.templates:
redirects = mytools.get_template_redirects(self.site, template)
with_redir.update(redirects)
return with_redir
@staticmethod
def log_to_page(page_title, ref_content):
site = pywikibot.Site("ku", "wikipedia")
log_page = pywikibot.Page(site, "User:Balyozbot/kontrol/tempsubst")
log_text = f"\n\nPage title: {page_title}\nRef content causing ValueError: {ref_content}"
# Append the log text to the existing content of the log page
log_page.text += log_text
# Save the changes to the log page
log_page.save(summary="Logging ValueError")
def subst_ref_tags(self, parsed_wikitext):
for index, tag in enumerate(parsed_wikitext.filter_tags()):
if tag.tag == "ref":
ref_content = tag.contents.strip()
parsed_ref = mwparserfromhell.parse(ref_content)
sablon_heye = self.should_edit_template(parsed_ref)
if sablon_heye:
if tag.has("name"):
name = tag.get("name").value.strip()
replaced_content = f'{{{{safesubst:#tag:ref|{ref_content}|name="{name}"}}}}'
else:
replaced_content = f'{{{{safesubst:#tag:ref|{ref_content}}}}}'
try:
# Attempt to replace the tag content
parsed_wikitext.replace(tag, replaced_content)
except ValueError as e:
# If ValueError occurs, log the error and skip replacement
pywikibot.error(f"Error replacing tag: {e}. Skipping replacement.")
ref_log = f"{{{{subst:codenowiki |1={str(tag)}}}}}"
self.log_to_page(self.current_page.title(), ref_log)
return
def should_edit_template(self, parsed_content):
for template in parsed_content.filter_templates():
template_name = mytools.ucfirst(template.name)
if template_name in self.templates:
if template.has("demo"):
demo = mytools.lcfirst(template.get("demo").value.strip())
if demo == "yes" or demo == "erê" or demo == "1":
return False
else:
return True
elif template.has("nosubst"):
demo = mytools.lcfirst(template.get("nosubst").value.strip())
if demo == "yes" or demo == "erê" or demo == "1":
return False
else:
return True
else:
return True
return False
def subst_templates(self, parsed_wikitext):
for template in parsed_wikitext.filter_templates():
template_name = mytools.ucfirst(template.name)
if template_name in self.templates:
if template.has("demo"):
demo = mytools.lcfirst(template.get("demo").value.strip())
if demo == "yes" or demo == "erê" or demo == "1" or demo == "y":
continue
else:
template.name = "subst:" + template_name
elif template.has("nosubst"):
demo = mytools.lcfirst(template.get("nosubst").value.strip())
if demo == "yes" or demo == "erê" or demo == "1":
continue
else:
template.name = "subst:" + template_name
else:
template.name = "subst:" + template_name
def do_kozmetik(self, old_text):
kozmetik_cebu = ""
cc_toolkit = CosmeticChangesToolkit(self.current_page,
ignore=self.opt.ignore)
new_text, summaries = cc_toolkit.change(old_text)
applied_summaries = ', '.join(summaries.values())
if new_text is not False and new_text != old_text:
kozmetik_cebu = "; paqijiyên kozmetîk"
if applied_summaries:
kozmetik_cebu += f' ({applied_summaries}.)'
return new_text, kozmetik_cebu
def treat_page(self) -> None:
"""Load the given page, do some changes, and save it."""
if self.current_page.namespace() == 10:
return
text = self.current_page.text
old_text = text
parsed_wikitext = mwparserfromhell.parse(text)
self.subst_ref_tags(parsed_wikitext)
self.subst_templates(parsed_wikitext)
new_text = str(parsed_wikitext)
kozmetik_cebu = ""
if old_text != new_text:
if TESTING:
new_text = new_text
else:
cleaned_new_text, kozmetik_cebu = self.do_kozmetik(new_text)
new_text = cleaned_new_text
summary = f'[[{self.bot_name}|Bot]]: Şablonên ku otomatîk were [[{self.cat_title}|subst:kirin]] hat subst:kirin{kozmetik_cebu}'
self.put_current(
new_text,
summary=summary,
asynchronous=self.opt['async'],
show_diff=self.opt['showdiff']
)
def main(*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 = {}
# Process global arguments to determine desired site
local_args = pywikibot.handle_args(args)
# This factory is responsible for processing command line arguments
# that are also used by other scripts and that determine on which pages
# to work on.
gen_factory = pagegenerators.GeneratorFactory()
# Process pagegenerators arguments
local_args = gen_factory.handle_args(local_args)
# Parse your own command line arguments
for arg in local_args:
arg, _, value = arg.partition(':')
option = arg[1:]
if option in ('-always', '-async', '-showdiff'):
options[option[1:]] = True
elif option == '-ignore':
value = value.upper()
try:
options['ignore'] = getattr(CANCEL, value)
except AttributeError:
raise ValueError(f'Unknown ignore mode {value!r}!')
# take the remaining options as booleans.
# You will get a hint if they aren't pre-defined in your bot class
else:
options[option] = True
template_names = mytools.get_cat_members(pywikibot.Site(), "Şablonên ku otomatîk were substkirin", namespace=10)
if VERBOSE:
if template_names:
print(template_names)
else:
print("templates?")
# The preloading option is responsible for downloading multiple
# pages from the wiki simultaneously.
gen = gen_factory.getCombinedGenerator(preload=True)
if gen:
bot = TemplSubstBot(generator=gen, templates=template_names, **options)
bot.run()
else:
page_list = []
for template_name in template_names:
template_page = pywikibot.Page(pywikibot.Site(), f"Template:{template_name}")
pages = mytools.referring_page_generator(template_page,
only_template_inclusion=True)
page_list.extend(pages)
if not pywikibot.bot.suggest_help(missing_generator=not page_list):
if VERBOSE:
print(page_list)
bot = TemplSubstBot(generator=page_list, templates=template_names, **options)
bot.run()
if __name__ == '__main__':
main()