def _replace_bs_template_files(self, tpl: mwparserfromhell.nodes.Template, template: pywikibot.Page) -> None: assert self.site_config is not None for icon_prefix, templates in self.site_config.bs_templates.items(): if template not in templates: continue for param in tpl.params: if param.name.matches("1"): prefix = icon_prefix.strip() else: prefix = "" param_value = HTML_COMMENT.sub("", str(param.value)).strip() try: current_icon = BSiconPage(self.current_page.site, name=prefix + param_value) current_icon.title() except (pywikibot.exceptions.Error, ValueError): continue new_icon = self.opt.bsicons_map.get(current_icon, None) if not new_icon: continue # The replacement must have the same prefix. if new_icon.name[:len(prefix)] == prefix: param.value = str(param.value).replace( param_value, new_icon.name[len(prefix):] # noqa: E203 ) self.current_page.replacements.add( Replacement(current_icon, new_icon))
def _replace_rt_template_files( self, tpl: mwparserfromhell.nodes.Template) -> None: # Written for [[:cs:Template:Železniční trať]]. for param in tpl.params: param_value = HTML_COMMENT.sub("", str(param.value)).strip() if param.name.matches("typ"): if param_value[:2] == "ex": current_name = "exl" + param_value[2:] else: current_name = "l" + param_value else: current_name = param_value try: current_icon = BSiconPage(self.current_page.site, name=current_name) current_icon.title() except (pywikibot.exceptions.Error, ValueError): continue new_icon = self.opt.bsicons_map.get(current_icon, None) if not new_icon: continue if param.name.matches("typ"): if new_icon.name[:3] == "exl": replacement = "ex" + new_icon.name[3:] elif new_icon.name[:1] == "l": replacement = new_icon.name[1:] else: pywikibot.log(f"{new_icon} cannot be used in |typ=.") continue else: replacement = new_icon.name param.value = str(param.value).replace(param_value, replacement) self.current_page.replacements.add( Replacement(current_icon, new_icon))
def _replace_routemap_files(self, tpl: mwparserfromhell.nodes.Template) -> None: for param in tpl.params: if not re.search(r"^(?:map\d*|\d+)$", str(param.name).strip()): continue param_value = str(param.value) for match in ROUTEMAP_BSICON.findall(param_value): current_name = HTML_COMMENT.sub("", match[1]).strip() try: current_icon = BSiconPage(self.current_page.site, name=current_name) current_icon.title() except (pywikibot.exceptions.Error, ValueError): continue new_icon = self.opt.bsicons_map.get(current_icon, None) if not new_icon: continue param_value = param_value.replace( "".join(match), match[0] + match[1].replace(current_name, new_icon.name) + match[2], ) self.current_page.replacements.add( Replacement(current_icon, new_icon)) param.value = param_value
def replace_gallery_files( self, wikicode: mwparserfromhell.wikicode.Wikicode) -> None: """ Replace files in <gallery>. :param wikicode: Parsed wikitext """ for tag in wikicode.ifilter_tags(): if tag.tag.lower() != "gallery": continue lines = str(tag.contents).splitlines() for i, line in enumerate(lines): title, sep, caption = removeDisabledParts(line).partition("|") if not title: continue try: current_icon = BSiconPage(self.current_page.site, title) current_icon.title() except (pywikibot.exceptions.Error, ValueError): continue new_icon = self.opt.bsicons_map.get(current_icon, None) if new_icon: lines[i] = f"{new_icon.title()}{sep}{caption}" self.current_page.replacements.add( Replacement(current_icon, new_icon)) if self.current_page.replacements: tag.contents = "\n".join(lines) + "\n"
def output_edits( *, site: pywikibot.site.APISite, start: datetime.datetime, end: datetime.datetime, prefix: str, ) -> None: """Write edits to a page.""" changes_page = Page( site, f"{prefix}/{start.strftime('%Y-%m')}", ) if start.date().isoformat() in get_headers(changes_page.text): return changes_page = get_page_from_size(changes_page) if start.date().isoformat() in get_headers(changes_page.text): return if not changes_page.exists(): changes_page.save( text=f"{{{{nobots}}}}{{{{{prefix}}}}}", summary="Create changes page", ) file_changes = "" for recent_change in site.recentchanges( start=start, end=end, reverse=True, namespaces=6, changetype="edit|new", ): try: file = BSiconPage(site, recent_change["title"]) except (KeyError, ValueError): continue if not file.exists(): continue _handle_hidden(recent_change) file_changes += ( "\n|-\n| {{{{bsq2|{name}}}}} || {rc[revid]} || {rc[timestamp]} || " "{rc[user]} || <nowiki>{rc[comment]}</nowiki>".format( name=file.name, rc=recent_change)) if file_changes: file_changes = ( f'{{| class="wikitable sortable mw-collapsible mw-collapsed"' f"\n! BSicon !! revid !! Date/time !! User !! Summary" f"{file_changes}\n|}}") else: file_changes = ": No changes" try: changes_page.save( text=file_changes, section="new", summary=start.date().isoformat(), minor=False, force=True, ) except pywikibot.exceptions.Error: pywikibot.exception(tb=True)
def output_log( *, site: pywikibot.site.APISite, logtype: str, start: datetime.datetime, end: datetime.datetime, prefix: str, bsicon_template_title: str = "bsq2", ) -> None: """Write logevents to a page.""" log_page = Page( site, f"{prefix}/{logtype}/{start.strftime('%Y-%m')}", ) if start.date().isoformat() in get_headers(log_page.text): return log_page = get_page_from_size(log_page) if start.date().isoformat() in get_headers(log_page.text): return if not log_page.exists(): log_page.save( text=f"{{{{nobots}}}}{{{{{prefix}}}}}", summary="Create log page", ) log_text = "" for logevent in site.logevents( logtype=logtype, namespace=6, start=start, end=end, reverse=True, ): try: bsicon = BSiconPage(logevent.page()) except ValueError: continue _handle_hidden(logevent.data) log_text += ( "\n|-\n| {{{{{tpl}|{name}}}}} || {r[logid]} || {r[timestamp]} " "|| {r[user]} || <nowiki>{r[comment]}</nowiki>".format( tpl=bsicon_template_title, name=bsicon.name, r=logevent.data)) if log_text: log_text = ( f'{{| class="wikitable sortable mw-collapsible mw-collapsed"' f"\n! BSicon !! logid !! Date/time !! User !! Summary" f"{log_text}\n|}}") else: log_text = ": None" try: log_page.save( text=log_text, section="new", summary=start.date().isoformat(), minor=False, force=True, ) except pywikibot.exceptions.Error: pywikibot.exception(tb=True)
def replace_file_links(self, text: str) -> str: """ Return text with file links replaced. :param text: Article text """ assert self.site_config is not None for match in self.site_config.file_regex.finditer( removeDisabledParts(text)): try: current_icon = BSiconPage(self.current_page.site, match.group("filename")) current_icon.title() except (pywikibot.exceptions.Error, ValueError): continue new_icon = self.opt.bsicons_map.get(current_icon, None) if new_icon: text = text.replace(match.group("filename"), new_icon.title(with_ns=False)) self.current_page.replacements.add( Replacement(current_icon, new_icon)) return text
def output_move_log( *, site: pywikibot.site.APISite, start: datetime.datetime, end: datetime.datetime, prefix: str, ) -> None: """Write move logevents to a page.""" logtype = "move" log_page = Page( site, f"{prefix}/{logtype}/{start.strftime('%Y-%m')}", ) if start.date().isoformat() in get_headers(log_page.text): return log_page = get_page_from_size(log_page) if start.date().isoformat() in get_headers(log_page.text): return if not log_page.exists(): log_page.save( text=f"{{{{nobots}}}}{{{{{prefix}}}}}", summary="Create log page", ) log_text = "" for logevent in site.logevents( logtype=logtype, namespace=6, start=start, end=end, reverse=True, ): page = logevent.page() row_text = "\n|-\n| " try: page = BSiconPage(page) except ValueError: row_text += page.title(as_link=True, textlink=True) else: row_text += f"{{{{bsn|{page.name}}}}}" row_text += " || " target = logevent.target_page try: target = BSiconPage(target) except ValueError: row_text += target.title(as_link=True, textlink=True) else: row_text += f"{{{{bsq2|{target.name}}}}}" if not (isinstance(page, BSiconPage) or isinstance(target, BSiconPage)): continue log_text += row_text _handle_hidden(logevent.data) log_text += (" || {r[logid]} || {r[timestamp]} || {r[user]} || " "<nowiki>{r[comment]}</nowiki>".format(r=logevent.data)) if log_text: log_text = ( f'{{| class="wikitable sortable mw-collapsible mw-collapsed"' f"\n! Page !! Target !! logid !! Date/time !! User !! Summary" f"{log_text}\n|}}") else: log_text = ": None" try: log_page.save( text=log_text, section="new", summary=start.date().isoformat(), minor=False, force=True, ) except pywikibot.exceptions.Error: pywikibot.exception(tb=True)
def process_global_config( config: ConfigJSONObject, site: pywikibot.site.APISite ) -> tuple[Iterable[pywikibot.Page], dict[BSiconPage, BSiconPage], LocalConfig]: """Process the global config.""" redirects = config.redirects(set(), require_list, GenToPages(site)) disallowlist = config.blacklist(set(), require_list, GenToPages(site)) allowlist = config.whitelist(set(), require_list, GenToPages(site)) bsicons_map = {} gen: Iterable[pywikibot.Page] = chain() for page in redirects - (disallowlist - allowlist): # Must be a redirect, and both must be BSicons. try: page = BSiconPage(page) bsicons_map[page] = BSiconPage(page.getRedirectTarget()) except (ValueError, pywikibot.exceptions.IsNotRedirectPageError) as e: pywikibot.warning(e) else: gen = chain(gen, page.globalusage(), page.usingPages()) # T199398 replacement_map = config.replacement_map({}, ToReplacementMap(site)) for key, value in replacement_map.items(): # Both must be BSicons. try: page = BSiconPage(site, key) bsicons_map[page] = BSiconPage(site, value) except ValueError as e: pywikibot.warning(e) else: gen = chain(gen, page.globalusage(), page.usingPages()) # T199398 local_config = process_local_config(config) return gen, bsicons_map, local_config