#!/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 '| Page | Watchers | Active |
'
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 '| %s (%s) | %s | %s |
' % (
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 '
'
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()