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

Ji Wîkîpediya, ensîklopediya azad.
#!/usr/bin/env python3
"""
Şablona Bêkategorî lê zêde dike an radike.
Eger hemû kategoriya rûpelê veşartî be, lê zêde dike. Wekî din radike. Tenê li ser gotaran dixebite.

python pwb.py updatewin -file:addbekategori.py -summary:


Bikaranîn

python pwb.py addbekategori -ns:0 -cat:"Kategorî:Hemû rûpelên bêkategorî"  -always

python pwb.py addbekategori -ns:0 -cat:"Kategorî:Hemû rûpelên bêkategorî" -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.

Use global -simulate option for test purposes. No changes to live wiki
will be done.


Use global -simulate option for test purposes. No changes to live wiki
will be done.


"""
#
# (C) Pywikibot team, 2006-2022
#
# Distributed under the terms of the MIT license.
#

import pywikibot
from pywikibot import pagegenerators
from pywikibot.bot import (
    AutomaticTWSummaryBot,
    ConfigParserBot,
    ExistingPageBot,
    SingleSiteBot,
)
import mwparserfromhell
from kucosmetics import CANCEL, CosmeticChangesToolkit
import re
import mytools

VERBOSE = False

# This is required for the text that is shown when you run this script
# with the parameter -help.
docuReplacements = {'&params;': pagegenerators.parameterHelp}  # noqa: N816


class BekategoriBot(
    # 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'

    update_options = {
        'async': False,
        'showdiff': False,
        'ignore': CANCEL.MATCH,
    }

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # Retrieve redirects for templates
        self.bekat_redirects = self.get_template_redirects("Bêkategorî")
        self.bot_name = "User:Balyozxane/skrîpt/py/addbekategori.py"

    def get_template_redirects(self, template_title):
        template_title = "Şablon:" + template_title
        template_page = pywikibot.Page(self.site, template_title)
        redirects = template_page.backlinks(filter_redirects=True, namespaces=[10])
        redirect_titles = [redirect.title(with_ns=False) for redirect in redirects]
        redirect_titles.append(template_title.split(":")[-1])

        if VERBOSE:
            print(f"{template_title} redirects:\n{redirect_titles}")
        return redirect_titles

    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 bekat_inpage(self, parsed):

        bekat_inpage = False
        for template in parsed.filter_templates():
            template_name = mytools.ucfirst(template.name)
            if template_name in self.bekat_redirects:
                bekat_inpage = True

        return bekat_inpage

    def remove_template(self, parsed):
        for template in parsed.filter_templates():
            template_name = mytools.ucfirst(template.name)
            if template_name in self.bekat_redirects:
                parsed.remove(template)

        new_next = str(parsed)
        return new_next

    @staticmethod
    def are_categories_hidden(categories):
        ku_months = {
            'January': 'kanûna paşîn',
            'February': 'sibat',
            'March': 'adar',
            'April': 'nîsan',
            'May': 'gulan',
            'June': 'hezîran',
            'July': 'tîrmeh',
            'August': 'tebax',
            'September': 'îlon',
            'October': 'çiriya pêşîn',
            'November': 'çiriya paşîn',
            'December': 'kanûna pêşîn'
        }

        # Check if any of the categories are not hidden
        for category in categories:

            if VERBOSE:
                print(f"Checking category: {category.title(with_ns=False)}")

            if category.exists():
                if not category.isHiddenCategory():
                    if VERBOSE:
                        print(f"Category '{category.title(with_ns=False)}' is not hidden.")
                    return False
            else:
                # Check if the category matches any of the patterns
                pattern_matched = False
                for month_name, kurdish_month in ku_months.items():
                    pattern = fr".+ ji {kurdish_month} \d+"

                    if re.search(pattern, category.title(with_ns=False)):
                        if VERBOSE:
                            print(f"Match found for category '{category.title(with_ns=False)}'.")
                        pattern_matched = True
                        break

                # If no match is found, continue to the next category
                if not pattern_matched:
                    if VERBOSE:
                        print(f"No match found for category '{category.title(with_ns=False)}'.")
                    continue

                if VERBOSE:
                    print("Match found. Returning True.")
                return True
        if VERBOSE:
            print("All categories checked. Returning True.")
        return True

    def treat_page(self) -> None:

        if self.current_page.namespace() != 0:
            if VERBOSE:
                print("Skipping Namespace not 0.")
            return

        text = self.current_page.text
        parsed = mwparserfromhell.parse(text)

        categories = self.current_page.categories()

        if self.are_categories_hidden(categories):
            if VERBOSE:
                print("All categories of the page are hidden.")
            cats_hidden = True

        else:
            if VERBOSE:
                print("Not all categories of the page are hidden.")
            cats_hidden = False

        if self.bekat_inpage(parsed):
            if VERBOSE:
                print("Bêkategorî di rûpelê de heye.")
            bekat_inpage = True
        else:
            if VERBOSE:
                print("Bêkategorî tine ye.")
            bekat_inpage = False

        if cats_hidden and not bekat_inpage:
            new_template = "\n{{subst:Bêkategorî}}"
            updated_text = text + new_template
            done = "lê hat zêdekirin"
        elif not cats_hidden and bekat_inpage:
            updated_text = self.remove_template(parsed)
            done = "hat rakirin"

        else:
            if VERBOSE:
                print("Skipping... All categories are hidden and Bêkategorî is in page.")
            return

        cleaned_new_text, kozmetik_cebu = self.do_kozmetik(updated_text)

        summary = f'[[{self.bot_name}|Bot]]: Şablona {{{{[[Şablon:Bêkategorî|bêkategorî]]}}}} {done}{kozmetik_cebu}'

        self.put_current(
            cleaned_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
    # The preloading option is responsible for downloading multiple
    # pages from the wiki simultaneously.
    gen = gen_factory.getCombinedGenerator(preload=True)

    # check if further help is needed
    if not pywikibot.bot.suggest_help(missing_generator=not gen):
        # pass generator and private options to the bot
        bot = BekategoriBot(generator=gen, **options)
        bot.run()  # guess what it does


if __name__ == '__main__':
    main()