#!/usr/bin/env python3"""Allows access to the bot account's watchlist.The watchlist can be updated manually by running this script.Syntax: python pwb.py watchlist [-all | -count | -count:all | -new]Command line options:-all Reloads watchlists for all wikis where a watchlist is already present.-count Count only the total number of pages on the watchlist of the account the bot has access to.-count:all Count only the total number of pages on all wikis watchlists that the bot is connected to.-new Load watchlists for all wikis where accounts is set in user config file.. versionchanged:: 7.7 watchlist is retrieved in parallel tasks."""## (C) Pywikibot team, 2005-2024## Distributed under the terms of the MIT license.#from__future__importannotationsimportdatetimeimportosfromconcurrent.futuresimportThreadPoolExecutor,as_completedimportpywikibotfrompywikibotimportconfigfrompywikibot.data.apiimportCachedRequestfrompywikibot.exceptionsimportInvalidTitleErrortry:fromscripts.maintenance.cacheimportCacheEntryexceptModuleNotFoundError:frompywikibot_scripts.maintenance.cacheimportCacheEntry
[docs]defget(site=None)->list[str]:"""Load the watchlist, fetching it if necessary."""ifsiteisNone:site=pywikibot.Site()return[p.title()forpinsite.watched_pages()]
[docs]defcount_watchlist(site=None)->None:"""Count only the total number of page(s) in watchlist for this wiki."""ifsiteisNone:site=pywikibot.Site()watchlist_count=len(refresh(site))pywikibot.info(f'There are {watchlist_count} page(s) in the watchlist.')
[docs]defcount_watchlist_all(quiet=False)->None:"""Count only the total number of page(s) in watchlist for all wikis."""ifnotquiet:pywikibot.info('Counting pages in watchlists of all wikis...')withThreadPoolExecutor()asexecutor:futures={executor.submit(refresh,pywikibot.Site(lang,family))forfamilyinconfig.usernamesforlanginconfig.usernames[family]}wl_count_all=sum(len(future.result())forfutureinas_completed(futures))ifnotquiet:pywikibot.info(f'There are a total of {wl_count_all} page(s) in the'' watchlists for all wikis.')
[docs]defisWatched(pageName,site=None):# noqa: N802, N803"""Check whether a page is being watched."""watchlist=get(site)returnpageNameinwatchlist
[docs]defrefresh(site):"""Fetch the watchlist."""pywikibot.info(f'Retrieving watchlist for {site}.')returnlist(site.watched_pages(force=True))
[docs]defrefresh_all()->None:"""Reload watchlists for all wikis where a watchlist is already present."""cache_path=CachedRequest._get_cache_dir()files=os.scandir(cache_path)seen=set()withThreadPoolExecutor()asexecutor:forfilenameinfiles:entry=CacheEntry(cache_path,filename)entry._load_cache()entry.parse_key()entry._rebuild()ifentry.siteinseen:continue# for generator API usage we have to check the modulesmodules=entry._params.get('modules',[])modules_found=any(module.endswith('watchlistraw')formoduleinmodules)# for list API usage 'watchlistraw' is directly foundifmodules_foundor'watchlistraw'inentry._data:executor.submit(refresh,entry.site)seen.add(entry.site)
[docs]defrefresh_new()->None:"""Load watchlists of all wikis for accounts set in user config."""pywikibot.info(f'Downloading all watchlists for your accounts in 'f'{config.user_config_file}')count_watchlist_all(quiet=True)
[docs]defmain(*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 """opt_all=Falseopt_new=Falseopt_count=Falseopt_count_all=Falseforarginpywikibot.handle_args(args):ifargin('-all','-update'):opt_all=Trueelifarg=='-new':opt_new=Trueelifarg=='-count':opt_count=Trueelifarg=='-count:all':opt_count_all=Trueifopt_all:refresh_all()elifopt_new:refresh_new()elifopt_count:count_watchlist()elifopt_count_all:count_watchlist_all()else:site=pywikibot.Site()count_watchlist(site)watchlist=list(site.watched_pages(force=True))forpageinwatchlist:try:pywikibot.stdout(page.title())exceptInvalidTitleErrorase:pywikibot.error(e)