def get_text(page: pywikibot.page.BasePage, old: Optional[str], create: bool) -> str: """ Get text on page. If old is not None, return old. :param page: The page to get text from :param old: If not None, return this rather than the page's text :param create: Declare that the page will be created if it doesn't exist :return: The page's text or the old parameter if not None """ if old is not None: return old try: return page.get() except NoPageError: if create: pywikibot.output("{} doesn't exist, creating it!" .format(page.title())) return '' else: pywikibot.output("{} doesn't exist, skip!".format(page.title())) return None except IsRedirectPageError: pywikibot.output('{} is a redirect, skip!'.format(page.title())) return None
def get_article_quality(page: pywikibot.page.BasePage) -> str: """Gets the content assement class from a wikiproject template""" if not page.isTalkPage(): page = page.toggleTalkPage() classes = [] valid_classes = { "fa": 1, "fl": 1, "a": 2, "ga": 3, "b": 4, "c": 5, "start": 6, "stub": 7, "list": 8, "draft": 8, } for value in page.templatesWithParams(): for para in value[1]: key, sep, value = para.partition("=") if sep and key.lower() == "class" and value.lower( ) in valid_classes: classes.append(value.lower()) classes = sorted(classes, key=valid_classes.__getitem__) if classes: return classes[0] else: return "unassessed"
def check_can_run(page: pywikibot.page.BasePage) -> bool: """Determinies if the bot should run on this page and returns a bool.""" if ((page.title() in skip) or (not page.has_permission("edit")) or (not page.botMayEdit()) or (not re.search("{{[iI][nN]aturalist[rR]eview}}", page.text))): return False else: return True
def get_article_metadata(page: pywikibot.page.BasePage) -> Article: """Returns article creator and content assesment class as a NamedTuple""" return Article( title=page.title(), quality=get_article_quality(page), author=page.oldest_revision.user, )
def fail_warning(page: pywikibot.page.BasePage, review_license: str, is_old: bool = False) -> None: user_talk = get_author_talk(page) message = string.Template(config["old_fail_warn"] if is_old else config["fail_warn"]).safe_substitute( filename=page.title(with_ns=True), review_license=review_license) summary = string.Template(config["review_summary"]).safe_substitute( status="fail", review_license=review_license, version=__version__) if not simulate: utils.check_runpage(site, run_override) logger.info(f"Saving {user_talk.title()}") utils.retry( utils.save_page, 3, text=message, page=user_talk, summary=summary, bot=False, minor=False, mode="append", ) else: logger.info("Saving disabled") logger.info(summary) logger.info(message)
def find_com_license(page: pywikibot.page.BasePage) -> str: """Find the license template currently used on the Commons page Returns the first license template used on the page. If no templates are found, return an empty string. """ category = pywikibot.Category(site, "Category:Primary license tags (flat list)") for template in page.itertemplates(): if template in category.members(namespaces=10): return template.title(with_ns=False) else: return ""
def find_ina_id( page: pywikibot.page.BasePage, ) -> Tuple[Optional[iNaturalistID], Optional[iNaturalistID]]: """Returns an iNaturalistID tuple from wikitext""" photos = set() observations = set() for url in page.extlinks(): url_id = parse_ina_url(url) if url_id is None: continue elif url_id.type == "observations": observations.add(url_id) elif url_id.type == "photos": photos.add(url_id) if photos and observations: return observations.pop(), photos.pop() elif observations: return observations.pop(), None elif photos: return None, photos.pop() else: return None, None
def put_text(page: pywikibot.page.BasePage, new: str, summary: str, count: int, asynchronous: bool = False) -> Optional[bool]: """ Save the new text. :param page: The page to change the text of :param new: The new text for the page :param summary: Summary of the page change :param count: Maximum number of attempts to reach the server :param asynchronous: If True, saves the page asynchronously :return: True if successful, False if unsuccessful, and None if awaiting the server """ page.text = new try: page.save(summary=summary, asynchronous=asynchronous, minor=page.namespace() != 3) except EditConflictError: pywikibot.output('Edit conflict! skip!') except ServerError: if count <= config.max_retries: pywikibot.output('Server Error! Wait..') pywikibot.sleep(config.retry_wait) return None raise ServerError( 'Server Error! Maximum retries exceeded') except SpamblacklistError as e: pywikibot.output( 'Cannot change {} because of blacklist entry {}' .format(page.title(), e.url)) except LockedPageError: pywikibot.output('Skipping {} (locked page)'.format(page.title())) except PageSaveRelatedError as error: pywikibot.output('Error putting page: {}'.format(error.args)) else: return True return False
def add_text(page: pywikibot.page.BasePage, addText: str, summary: Optional[str] = None, regexSkip: Optional[str] = None, regexSkipUrl: Optional[str] = None, always: bool = False, up: bool = False, putText: bool = True, oldTextGiven: Optional[str] = None, reorderEnabled: bool = True, create: bool = False ) -> Union[Tuple[bool, bool, bool], Tuple[str, str, bool]]: """ Add text to a page. :param page: The page to add text to :param addText: Text to add :param summary: Change summary, if None this uses the beginning of addText :param regexSkip: Abort if the text on the page matches this :param regexSkipUrl: Abort if the url matches this :param always: Edit without user confirmation :param up: Append text to the top of the page if True, otherwise the bottom :param putText: Save changes to the page if True, otherwise return (text, newtext, always) :param oldTextGiven: If None fetch page text, else use this text :param reorderEnabled: If True place text above categories and interwiki, else place at page bottom. No effect if up = False. :param create: Create the page if it does not exist :return: (success, success, always) if putText is True, otherwise (text, newtext, always) """ site = page.site if not summary: summary = i18n.twtranslate(site, 'add_text-adding', {'adding': addText[:200]}) if putText: pywikibot.output('Loading {}...'.format(page.title())) text = get_text(page, oldTextGiven, create) if text is None: return (False, False, always) # Understand if the bot has to skip the page or not # In this way you can use both -except and -excepturl if regexSkipUrl is not None: url = page.full_url() result = re.findall(regexSkipUrl, site.getUrl(url)) if result != []: pywikibot.output( 'Exception! regex (or word) used with -exceptUrl ' 'is in the page. Skip!\n' 'Match was: {}'.format(result)) return (False, False, always) if regexSkip is not None: result = re.findall(regexSkip, text) if result != []: pywikibot.output( 'Exception! regex (or word) used with -except ' 'is in the page. Skip!\n' 'Match was: {}'.format(result)) return (False, False, always) # If not up, text put below if not up: newtext = text # Translating the \\n into binary \n addText = addText.replace('\\n', '\n') if reorderEnabled: # Getting the categories categoriesInside = textlib.getCategoryLinks(newtext, site) # Deleting the categories newtext = textlib.removeCategoryLinks(newtext, site) # Getting the interwiki interwikiInside = textlib.getLanguageLinks(newtext, site) # Removing the interwiki newtext = textlib.removeLanguageLinks(newtext, site) # Adding the text newtext += '\n' + addText # Reputting the categories newtext = textlib.replaceCategoryLinks(newtext, categoriesInside, site, True) # Adding the interwiki newtext = textlib.replaceLanguageLinks(newtext, interwikiInside, site) else: newtext += '\n' + addText else: newtext = addText + '\n' + text if not putText: # If someone load it as module, maybe it's not so useful to put the # text in the page return (text, newtext, always) if text != newtext: pywikibot.output(color_format( '\n\n>>> {lightpurple}{0}{default} <<<', page.title())) pywikibot.showDiff(text, newtext) # Let's put the changes. error_count = 0 while True: if not always: try: choice = pywikibot.input_choice( 'Do you want to accept these changes?', [('Yes', 'y'), ('No', 'n'), ('All', 'a'), ('open in Browser', 'b')], 'n') except QuitKeyboardInterrupt: sys.exit('User quit bot run.') if choice == 'a': always = True elif choice == 'n': return (False, False, always) elif choice == 'b': pywikibot.bot.open_webbrowser(page) continue # either always or choice == 'y' is selected result = put_text(page, newtext, summary, error_count, asynchronous=not always) if result is not None: return (result, result, always) error_count += 1