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

#!/usr/bin/env python3
"""
python pwb.py updatewin -file:"mytools.py" -s:"çend amûrên nû"

Tools:

get_template_redirects

remove_template

remove_template_redirects

is_category_in_page

zaravayen_din

ucfirst

lcfirst

get_sitelinks (with qid)

without_comments

matrix_to_wikitable

"""
import datetime
import requests
import mwparserfromhell
import pywikibot
from pywikibot.tools import first_lower, first_upper
from typing import List, Union, Iterator

ku_months = {
    1: 'kanûna paşîn',
    2: 'sibat',
    3: 'adar',
    4: 'nîsan',
    5: 'gulan',
    6: 'hezîran',
    7: 'tîrmeh',
    8: 'tebax',
    9: 'îlon',
    10: 'çiriya pêşîn',
    11: 'çiriya paşîn',
    12: 'kanûna pêşîn'
}


def get_cur_month_year() -> str:
    """
    Returns current month and year as a string in Kurdish
    :return: month year
    """
    current_month_number = datetime.datetime.now().month
    current_year = datetime.datetime.now().year
    month_name = ku_months[current_month_number]
    month_year = f"{month_name} {current_year}"
    return month_year


def get_temps_in_category(site, category_name):
    category = pywikibot.Category(site, 'Category:' + category_name)

    members_list = []

    for member in category.members():
        if member.namespace() == 10:
            members_list.append(member.title().replace("Şablon:", ""))

    return members_list


def get_template_redirects(site, template_title):
    """
    Return a list of redirects of the given template.

    :param site: pywikibot Site
    :param template_title: without "Şablon:"
    :return: list of redirects including the given template
    """
    template_title = "Şablon:" + template_title
    template_page = pywikibot.Page(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])

    return redirect_titles


def remove_template(text: str, template_title: str) -> str:
    """
    Remove specified template from wiki text.

    :param text: Wiki text
    :param template_title: template name
    :return: str Wiki text
    """
    wikicode = mwparserfromhell.parse(text)

    for template in wikicode.filter_templates():
        template_name = template.name.strip()
        template_name = template_name[0].upper() + template_name[1:]
        if template_name == template_title:
            wikicode.remove(template)

    return str(wikicode)


def remove_template_redirects(text: str, template_redirects: List[str]) -> str:
    """
    Remove specified template or its redirect from wiki text.

    :param text: Wiki text
    :param template_redirects: List of template_redirects
    :return: str Wiki text
    """
    wikicode = mwparserfromhell.parse(text)

    for template in wikicode.filter_templates():
        template_name = template.name.strip()
        template_name = template_name[0].upper() + template_name[1:]
        if template_name in template_redirects:
            wikicode.remove(template)

    return str(wikicode)


def is_template_in_page(site: pywikibot.site.BaseSite, text: str, template_title: str) -> bool:
    """
    Check if a given template title is included in the page text.

    :param site: pywikibot Site
    :param text: Wiki text.
    :param template_title: The title of the category to check.
    :return: True if the category is included in the page categories, False otherwise.
    """
    wikicode = mwparserfromhell.parse(text)
    template_redirects = get_template_redirects(site, template_title)

    for template in wikicode.filter_templates():
        template_name = template.name.strip()
        template_name = template_name[0].upper() + template_name[1:]
        if template_name in template_redirects:
            return True

    return False


def is_category_in_page(page: pywikibot.page.BasePage, category_title: str) -> bool:
    """
    Check if a given category title is included in the categories of a page.

    :param page: A Pywikibot page object.
    :param category_title: The title of the category to check.
    :return: True if the category is included in the page categories, False otherwise.
    """
    if not page or not page.exists():
        return False

    category_title = category_title.strip()  # Remove leading/trailing spaces
    category = pywikibot.Category(page.site, category_title)

    # Iterate through the categories of the page
    for page_category in page.categories():
        # Check if the titles of the categories match
        if page_category.title(with_ns=False) == category.title(with_ns=False):
            return True

    return False


def zaravayen_din(categories: Iterator[pywikibot.Page]) -> bool:
    """
    Kontrol bike eger sayfe di kategoriyên zaravayan de ye.

    :param categories: pywikibot.Categories
    :return: True eger kategoriya zaravayan di rûpelê de be, wekî din False.
    """
    kurdish_categories = [
        "Gotara bi soranî",
        "Gotara bi kirmaşanî",
        "Gotara bi kurdiya başûr",
        "Gotara bi zazakî"
    ]

    page_categories = {c.title(with_ns=False) for c in categories}

    return any(cat in page_categories for cat in kurdish_categories)


def ucfirst(wikicode) -> str:
    """
    :param wikicode: text parsed by mwparserfromhell
    :return: First char uppercase string stripped. Use first_upper for other strings
    """
    return first_upper(str(wikicode).strip())


def lcfirst(wikicode) -> str:
    """
    :param wikicode: text parsed by mwparserfromhell
    :return: First char lowercase string stripped Use first_lower for other strings
    """
    return first_lower(str(wikicode).strip())


def get_sitelinks(qid: str, lang_codes: Union[str, List[str]]) -> dict:
    """
    Retrieve sitelinks for the specified Wikidata QID and language codes.

    :param qid: Wikidata QID
    :param lang_codes: String or list of language codes (without 'wiki' suffix). If a single language code is provided as a string, 'wiki' suffix will be appended automatically.
    :return: If ['ku', 'en'] send, returns dictionary with kuwiki, enwiki
    """
    url = f"https://www.wikidata.org/w/api.php"
    params = {
        "action": "wbgetentities",
        "format": "json",
        "ids": qid,
        "props": "sitelinks"
    }

    # Convert lang_codes to a list if it's a string
    if isinstance(lang_codes, str):
        lang_codes = [lang_codes]

    try:
        # Sending the API request
        response = requests.get(url, params=params)
        data = response.json()
        result = {}
        # Extracting titles of sitelinks for each language code
        if 'sitelinks' in data['entities'][qid]:
            sitelinks = data['entities'][qid]['sitelinks']
            for lang_code in lang_codes:
                lang_code_with_wiki = lang_code + 'wiki'
                site_data = sitelinks.get(lang_code_with_wiki, None)
                result[lang_code_with_wiki] = site_data['title'] if site_data else None
            return result
        else:
            return {lang_code + 'wiki': None for lang_code in lang_codes}
    except Exception as e:
        print(f"An error occurred: {e}")
        return {lang_code + 'wiki': None for lang_code in lang_codes}


# from #https://github.com/ashotjanibekyan/WikiPyScripts/blob/master/helpers.py
def without_comments(wiki_text):
    if wiki_text is None:
        return None
    wikicode = mwparserfromhell.parse(wiki_text)
    for node in wikicode.nodes[:]:
        if isinstance(node, mwparserfromhell.nodes.Comment):
            wikicode.remove(node)
    return str(wikicode).strip()


# from #https://github.com/ashotjanibekyan/WikiPyScripts/blob/master/helpers.py
def matrix_to_wikitable(matrix):
    text = '{| class="wikitable sortable"\n'
    text += '!' + '!!'.join(matrix[0]) + '\n'
    for i in range(1, len(matrix)):
        if isinstance(matrix[i], list) and len(matrix[i]) == len(matrix[0]):
            row = (str(x) if x or x == 0 else ' ' for x in matrix[i])
            text += '|-\n|' + '||'.join(row) + '\n'
    text += '|}'
    return text