Bikarhêner:Balyozxane/skrîpt/py/templsubst.py

Ji Wîkîpediya, ensîklopediya azad.
#!/usr/bin/env python3
"""
python pwb.py updatewin -file:"templsubst.py" -s:"use referring_page_generator from mytools, ready for deployment"

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 = {'&params;': 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."""

        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()