Bikarhêner:Wikihez/skrîpt/py/dengbot.py
Xuyakirin
#!/usr/bin/env python3
"""
Bikaranîn
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.
"""
#
#
import pywikibot
from pywikibot import pagegenerators
from pywikibot.bot import SingleSiteBot, ConfigParserBot, AutomaticTWSummaryBot
import mwparserfromhell
import re
import json
import mytools
from typing import Set
class DengBot(
SingleSiteBot,
ConfigParserBot,
AutomaticTWSummaryBot,
):
use_redirects = False
update_options = {
'async': False,
'showdiff': False,
}
REPORT_PAGE_TITLE = "User:Balyozbot/kontrol/dengbot"
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.bot_name = "Bikarhêner:Wikihez/skrîpt/py/dengbot.py"
json_title = "Bikarhêner:Wikihez/skrîpt/json/botoptions.json"
json_page = pywikibot.Page(self.site, json_title)
self.json_content = json_page.text
try:
self.botoptions = json.loads(self.json_content).get('dengbot')
self.country_replacements = self.botoptions.get('country_replacements', {})
self.deng_redirects = self.botoptions.get('redirects', {})
self.dever_countries = self.botoptions.get('dever_countries', {})
except json.JSONDecodeError as e:
pywikibot.error(f"Error decoding JSON content: {e}")
self.botoptions = {}
# --- report-page bookkeeping (param 3 anomalies) ---
self.report_page = pywikibot.Page(self.site, self.REPORT_PAGE_TITLE)
self.reported_values: Set[str] = set()
if self.report_page.exists():
for line in self.report_page.text.splitlines():
m = re.match(r"^\*\s*\[\[.*?\]\]:\s*(.+)$", line.strip())
if m:
self.reported_values.add(m.group(1).strip())
self.new_reports = []
def report_third_param(self, page_title: str, value: str) -> None:
"""Queue an unrecognized param-3 value for the control page, skipping duplicates."""
if value in self.reported_values:
return
self.reported_values.add(value)
self.new_reports.append(f"* [[{page_title}]]: {value}")
def treat_page(self) -> None:
page = self.current_page
if not page.exists():
pywikibot.error(f"Skipping {page.title()} since it does not exist")
return
if page.namespace() != 0 and page.title() != 'Bikarhêner:Wikihez/ceribandin':
pywikibot.output(f"Skipping page '{page.title()}' because it is not in namespace 0")
return
text = page.text
wikicode = mwparserfromhell.parse(text)
deng_list = ["deng", "Deng", "audio", "Audio"]
for template in wikicode.filter_templates():
if not template.name.strip().replace('\u200e', '') in self.deng_redirects:
continue # Skip non-"deng" templates
if template.has("dever"):
dever_value = template.get("dever").value.strip()
match = re.search(r"^(.+?) \((.+?)\)$", dever_value)
new_value = None
match2 = dever_value.split(",")
if dever_value in self.country_replacements:
new_value = self.country_replacements[dever_value]
elif match:
if (dever_value == "Almanya (Berlîn)" or dever_value == "Berlîn, Almanya") and "(zza)-Mirzali-" in template.get(2).value:
new_value = "Pilemor"
else:
country, city = match.groups()
# Apply country replacements
country = self.country_replacements.get(country, country)
city = self.country_replacements.get(city, city)
new_value = f"{city}, {country}"
elif len(match2) == 2:
city = match2[0].strip()
country = match2[1].strip()
# Apply country replacements
country = self.country_replacements.get(country, country)
city = self.country_replacements.get(city, city)
if country and city:
# Preserve the original comma spacing instead of
# always forcing "city, country" (e.g. keep
# "London,QY" as-is if there was no space after
# the comma in the source).
comma_idx = dever_value.find(",")
if comma_idx != -1 and comma_idx + 1 < len(dever_value) and dever_value[comma_idx + 1] == " ":
separator = ", "
else:
separator = ","
new_value = f"{city}{separator}{country}"
if new_value:
template.add("dever", new_value)
elif template.has("spr"):
lang = template.get(1).value.strip()
spr_val = template.get("spr").value.strip()
third_param = None
if template.has(3):
third_param = template.get(3).value.strip()
if lang == "de" and spr_val == "at":
if third_param and third_param in deng_list:
template.remove(3)
template.remove("spr")
template.add("dever", "Awistirya")
if third_param and third_param == self.current_page.title():
template.remove(3)
template.remove("spr")
template.add("dever", "Awistirya")
if not third_param:
template.remove("spr")
template.add("dever", "Awistirya")
elif template.has(4):
# Move param 4 into "dever".
dever_value = template.get(4).value.strip()
template.remove(4)
if dever_value:
template.add("dever", dever_value)
# Handle param 3: drop it if it's just a generic
# deng/audio label, otherwise flag the value for manual
# review
if template.has(3):
third_param = template.get(3).value.strip()
if third_param in deng_list:
template.remove(3)
else:
self.report_third_param(page.title(), third_param)
elif template.has(3):
third_param = template.get(3).value.strip()
new_value = None
deng = None
if third_param in self.country_replacements:
new_value = self.country_replacements[third_param]
else:
match = re.search(r"^(.+?) \((.+?)\)$", third_param)
if match:
deng, dever = match.groups()
country = self.country_replacements.get(dever, None) # Replace or keep the same
if country:
new_value = country
elif dever in self.dever_countries:
new_value = dever
if new_value:
if deng and deng.strip() in deng_list:
template.remove(3)
elif deng:
template.add(3, deng.strip())
template.add("dever", new_value)
elif third_param.strip() in deng_list:
template.remove(3)
new_text = str(wikicode)
if text != new_text:
summary = f'[[{self.bot_name}|Bot]]: Formata parametreya "dever" hat guhartin'
self.put_current(
new_text,
summary=summary,
asynchronous=self.opt['async'],
show_diff=self.opt['showdiff']
)
def teardown(self):
if self.new_reports:
old_text = self.report_page.text if self.report_page.exists() else ""
addition = "\n".join(self.new_reports)
if old_text.strip():
new_text = old_text.rstrip("\n") + "\n" + addition + "\n"
else:
new_text = addition + "\n"
self.report_page.text = new_text
self.report_page.save(
summary=f"[[{self.bot_name}|Bot]]: Zêdekirina nirxên nenas ên parametreya 3",
asynchronous=self.opt['async'],
)
super().teardown()
def main(*args: str) -> None:
local_args = pywikibot.handle_args(args)
gen_factory = pagegenerators.GeneratorFactory()
local_args = gen_factory.handle_args(local_args)
options = {}
for arg in local_args:
option, _, value = arg.partition(':')
if option in ('-always', '-async', '-showdiff'):
options[option[1:]] = True
# The preloading option is responsible for downloading multiple
# pages from the wiki simultaneously.
gen = gen_factory.getCombinedGenerator(preload=True)
if gen:
bot = DengBot(generator=gen, **options)
bot.run()
else:
page_list = []
template_page = pywikibot.Page(pywikibot.Site(), f"Template:deng")
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):
bot = DengBot(generator=page_list, **options)
bot.run()
if __name__ == '__main__':
main()