#!/usr/bin/env python # -*- coding: utf-8 -*- import wikipedia, pagegenerators import oursql connections = {} def getConn(wiki): if not wiki.endswith('_p'): wiki+='_p' if wiki not in connections: connections[wiki] = oursql.connect( db=wiki, host=wiki.replace('_', '-')+'.rrdb.toolserver.org', read_default_file='/home/dispenser/.my.cnf', charset=None, use_unicode=False ) return connections[wiki] def trusted_user(site, wrowner, wrtoken): if not wrowner or not wrtoken: return False wikipedia.logtime('User watchlist authentication') # Let users conn = getConn(site.dbName()) cursor = conn.cursor() cursor.execute(''' SELECT 1 FROM user WHERE user_name=? AND user_editcount >= ? ''', (wrowner, 500, )) has_enough_edits = cursor.fetchall() try: # Verify wrowner is on whitelist (~40 ms delay) conn = getConn('metawiki_p') cursor = conn.cursor() cursor.execute(''' SELECT 1 FROM page JOIN pagelinks ON pl_from=page_id WHERE page_namespace=? AND page_title=? AND pl_namespace IN (2,3) AND pl_title=REPLACE(?, " ", "_") ''', (0, 'Toolserver/watcher', wrowner,)) whitelisted = cursor.fetchall() except Exception, e: wikipedia.logtime(repr(e)) whitelisted = False if not (whitelisted or has_enough_edits): wikipedia.logtime('User is not on [[m:Toolserver/watchlist]] whitelist') return False wikipedia.logtime('User is whitelisted') # Verify wrowner + wrtoken with Wikimedia (~300 ms delay) data = { 'action': b'query', 'list': b'watchlistraw', 'format': b'xml', 'wrlimit': b'1', 'wrowner': wrowner, 'wrtoken': wrtoken, } mw_xml=site.getUrl(site.apipath(), data=data) if 'tools:~dispenser/view/Watcher') return generator = pagegenerators.DuplicateFilterPageGenerator(generator) try: if trusted_user(wikipedia.getSite(), wikipedia.SysArgs.get('username'), wikipedia.SysArgs.get('wltoken')): minwatchers = 0 except Exception, e: wikipedia.logtime('trusted_user() error: %r'%(e,)) def makelink(page, linktype, text=None): site = page.site() attr = '' if linktype==0 else ' class="mw-redirect' if linktype==1 else ' class="new"' return '%s' % ( attr, site.hostname(), (site.get_address if linktype==1 else site.nice_get_address)(page.urlname()), page.title().encode('utf-8'), text or page.title().encode('utf-8'), ) print '' print '' for page in generator: site=page.site() cursor = getConn(site.dbName()).cursor() db_title = page.titleWithoutNamespace(underscore=True).encode('utf-8') try: cursor.execute("""/* watcher LIMIT:15 NM */ SELECT SQL_NO_CACHE (SELECT page_is_redirect FROM page WHERE page_namespace=? AND page_title=?) AS page_redirect, (SELECT page_is_redirect FROM page WHERE page_namespace=? AND page_title=?) AS talk_redirect, COUNT(*) AS watchers, IFNULL(SUM(ts_wl_user_touched_cropped>NOW()-INTERVAL ? DAY), 0) AS active FROM watchlist WHERE wl_namespace=? AND wl_title=?; """, (page.namespace() | 1 - 1, db_title, page.namespace() | 1, db_title, active_days, page.namespace(), db_title,) ) except oursql.Error as (errno, strerror, extra): # Query timed out, use degraded query if errno in (1317, 2006, 2013): cursor.execute( "/* watcher LIMIT:5 */SELECT 0, 0, COUNT(*), -1 FROM watchlist WHERE wl_namespace=? AND wl_title=?", (page.namespace(), db_title) ) else: raise (page_redirect, talk_redirect, watchers, active) = cursor.fetchone() exists = page_redirect!=None or talk_redirect!=None title = page.titleWithoutNamespace(underscore=True).encode('utf-8') if page.isTalkPage(): talk = page page = wikipedia.Page(site, page.titleWithoutNamespace(), defaultNamespace=page.namespace()-1) else: talk = wikipedia.Page(site, page.titleWithoutNamespace(), defaultNamespace=page.namespace()+1) print '' % ( makelink(page, page_redirect), makelink(talk, talk_redirect, 'talk'), #"" if exists and watchers < minwatchers else watchers, "" if watchers < minwatchers else watchers, "" if active < minwatchers else active, ) print '
PageWatchersActive
%s (%s)%s%s
' if minwatchers: print '

Pages with fewer than %d watchers are hidden.

' % (minwatchers, ) if __name__ == "__main__" and wikipedia.handleUrlAndHeader(): try: wikipedia.startContent(form=True, head='') main() finally: wikipedia.endContent() wikipedia.stopme()