#!/usr/bin/env python # -*- coding: utf-8 -*- from __future__ import division import wikipedia, pagegenerators import oursql, re, time, urllib import cgitb; cgitb.enable(logdir='tracebacks') def colorValue(subset, total, revert = False): v = min(255 * subset // max(subset, total), 255) if (revert): v = 255 - v; blue = 00 if (v < 128): # Red to Yellow red = 255 green = 2 * v else: # Yellow to Green red = 2 * (255 - v) green = 255 return "#%02X%02X%02X" % (red, green, blue) 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='utf8', use_unicode=False ) return connections[wiki] class UserActivity: def __init__(self): self.page = wikipedia.MyPage self.days = 365 def main(self): site = wikipedia.getSite() action = 0 for arg in wikipedia.handleArgs(): if arg.startswith('-page:'): self.page = wikipedia.Page(site, arg[6:]) site = self.page.site() elif arg.startswith('-inactivetime:'): pass elif arg.startswith('-view:edit'): action = 2 elif arg.startswith('-days:'): try: self.days = int(arg[6:]) except: pass print '
' if not self.page.title(): return self.dbname = site.dbName() self.domain = site.hostname() conn = getConn(site.dbName()) self.cursor = conn.cursor() self.cursor.execute(""" SELECT page_is_redirect, CONCAT(ns_name, ':', rd_title) FROM page LEFT JOIN redirect ON rd_from=page_id LEFT JOIN toolserver.namespacename ON ns_id=rd_namespace AND ns_is_favorite=1 AND dbname=(SELECT DATABASE()) WHERE page_namespace=? AND page_title=?""", (self.page.namespace(), self.page.titleWithoutNamespace(underscore=True).encode('utf-8'),) ) exists = self.cursor.fetchall() if not exists: wikipedia.output("%s does not exist"%self.page.aslink()) return elif 1 in exists[0]: print '
%s'% (
wikipedia.escape(exists[0][1]),
wikipedia.escape(exists[0][1]),
)
return
else:
pass
#self.cursor.execute("CREATE DATABASE IF NOT EXISTS u_dispenser_p")
self.cursor.execute('SET @ThirtyDays = (SELECT DATE_FORMAT(NOW()-INTERVAL 30 DAY, "%Y%m%d"))')
self.cursor.execute("""/* useractivity LIMIT:300 */
CREATE TEMPORARY TABLE u_dispenser_p.userlist (
pl_title VARBINARY(255) NOT NULL,
pl_user VARBINARY(255) NOT NULL,
last_edit DATETIME NULL,
PRIMARY KEY (`pl_title`)
) ENGINE=MyISAM AS
SELECT DISTINCT pl_title, REPLACE(pl_title, "_", " ") AS pl_user, NULL AS last_edit
FROM page AS list
JOIN pagelinks ON list.page_id=pl_from
WHERE list.page_namespace=? AND list.page_title=?
AND pl_namespace IN (2,3) AND pl_title NOT LIKE "%/%"
""", (self.page.namespace(), self.page.titleWithoutNamespace(underscore=True).encode('utf-8'),))
# Do this seperate since MySQL's optimizer screws it up
self.cursor.execute("SELECT pl_user FROM u_dispenser_p.userlist;")
for (pl_user,) in self.cursor:
self.cursor.execute("""/* useractivity LIMIT:300 */
UPDATE u_dispenser_p.userlist
SET last_edit=TIMESTAMP((SELECT MAX(rev_timestamp) FROM revision WHERE rev_user_text=?))
WHERE pl_user=?
""", (pl_user, pl_user,))
self.cursor.execute("""/* useractivity LIMIT:300 */
SELECT SQL_NO_CACHE
REPLACE(pl_title,"_"," ") AS user_name,
pl_title AS user_title,
rd_title AS renamed,
user_editcount,
IFNULL(DATE_FORMAT(user_registration, "%Y-%m-%d"), "") AS user_reg_text,
user_registration,
ipb_expiry,
ipb_reason,
user_email_authenticated,
mail.up_value AS disablemail,
IFNULL(gndr.up_value, '') AS user_gender,
COUNT(wl_namespace) AS watchers,
SUM(ts_wl_user_touched_cropped>=@ThirtyDays),
last_edit,
(SELECT TIMESTAMPDIFF(DAY, last_edit, NOW())) AS days_since,
(SELECT tl_title
FROM templatelinks
WHERE tl_namespace=10 AND tl_from=page_id AND tl_title IN ("Retired", "Grounded")
) AS tl_title
FROM u_dispenser_p.userlist
LEFT JOIN page ON page_namespace=2 AND page_title=pl_title
LEFT JOIN redirect ON rd_from=page_id AND rd_namespace=2
LEFT JOIN user ON user_name = pl_user
/* for performance we do not use ipb_address */
LEFT JOIN ipblocks ON ipb_user=user_id
LEFT JOIN user_properties AS gndr ON gndr.up_user=user_id AND gndr.up_property="gender"
LEFT JOIN user_properties AS mail ON mail.up_user=user_id AND mail.up_property="disablemail"
LEFT JOIN watchlist ON wl_namespace=2 AND wl_title=pl_title
GROUP BY pl_title
ORDER BY pl_title
""")
if action == 0:
self.infoTable()
else:
self.updatePage()
def get_last_edit_timestamp(self, user):
'''
'''
return cursor.fetchall()
def updatePage(self):
try:
self.page.get() # first call, handles errors!
except wikipedia.NoPage as errmsg:
wikipedia.output('NoPage error encountered %s', (errmsg,))
return
except wikipedia.IsRedirectPage:
target = wikipedia.Page(site, self.page._redirarg)
print('
%s' % (target.title(asUrl=True, allowInterwiki=True), wikipedia.escape(target.title().encode('utf-8')),))
return
#
text = re.sub(r'\[\[([^:]+:([^[\]{|}\n]*?))\|\2\]\](?![^<]*)', r'[[\1|]]', self.page.get())
old_text = text
msg_commented = 0
msg_removed = 0
msg_renamed = 0
msg_blocked = 0
for user_name, user_title, user_rd, user_editcount, userreg, user_registration, ipb_expiry, ipb_reason, user_email_authenticated, disablemail, gender, watchers, active_watchers, last_edit, days_since, notes in self.cursor:
from dabfix import wikilinkregex
p = re.compile(ur'(^(?:[#*;:|].*|)(?:\[\[|\{\{)(?:User|User[ _]talk)[:|] *)(%s)( *(?=[]{|}[]).*)' % wikilinkregex(user_name), re.M | re.I | re.U)
n = 0
# List update logic
if user_editcount < 32 and user_rd:
user_rd = user_rd.replace('_', ' ').decode('utf-8')
wikipedia.output(u'Renaming [[User:%s]] → [[User:%s]]'%(user_name.decode('utf-8'), user_rd,))
text, n = p.subn(r'\g<1>%s\g<3>'%user_rd, text)
msg_renamed += n
elif user_editcount == 1 and days_since > 180:
wikipedia.output('Comment out [[User:%s]] single edit account (%d months inactive)'%(user_name.decode('utf-8'), days_since//30))
text, n = p.subn(r'', text)
msg_commented += n
elif user_editcount == 0:
if not last_edit:
wikipedia.output(u'Removing [[User:%s]] - No edits, possible [[wp:vanish]]ed'%user_name.decode('utf-8'))
text, n = p.subn(r'', text)
msg_removed += n
else:
n = -1
wikipedia.output(u'Bad edit info for [[User:%s]]'%user_name.decode('utf-8'))
elif ipb_expiry == "infinity":
wikipedia.output(u'[[User:%s]] is indefinitely blocked: \03{lightblue}%s\03{default}'%(user_name.decode('utf-8'), ipb_reason.decode('utf-8'),))
text, n = p.subn(r'', text)
msg_blocked += n
elif ipb_expiry:
wikipedia.output(u'[[User:%s]] is blocked until %s: %s'%(user_name.decode('utf-8'), ipb_expiry, ipb_reason.decode('utf-8'), ))
n = -1
elif days_since > self.days:
#if min(user_editcount/day_begun, 20) >= days_since * 1.5:
#if days_since/user_editcount >= user_editcount/day_begun * 0.20:
wikipedia.output('Comment out [[User:%s]] (%d edits, %d months inactive)' % (user_name.decode('utf-8'), user_editcount or -1, days_since and days_since//30, ))
text, n = p.subn(last_edit.strftime(r""), text)
msg_commented += n
else:
n = -1
pass
if n == 0:
wikipedia.output(u"\03{lightred}NOT successful\03{default}")
wikipedia.showDiff(old_text, text)
wikipedia.setAction(self.summary(parts={
'remove':msg_removed,
'renaming':msg_renamed,
'comment out':msg_commented,
'blocked': msg_blocked
}))
self.page.put(text)
def summary(self, parts):
msg = []
advert = " with [[tools:~dispenser/cgi-bin/useractivity.py|Useractivity]]"
wordform = ('user', 'users')
for key, value in parts.iteritems():
if key and value:
msg.append("%s %s" % (key, wordform[0],) if value==1 else "%s %d %s" % (key, value, wordform[1],))
if len(msg) == 0:
return ''
elif len(msg) < 3:
return ' and '.join(msg).capitalize() + advert
else:
return (', '.join(msg[:-1]) + ', and '+msg[-1]).capitalize() + advert
def infoTable(self):
print '| ', ' | '.join( 'User,Timeline,Registered,Blocks,Stalkers,Active,Gender,Email,Last edit'.split(',') ), ' | Disabled | ' if disablemail else 'Yes | ' else: mailable = 'No | ' if watchers < 20: watchers = '' if active_watchers < 20: active_watchers = '' print '''|||
|---|---|---|---|---|---|---|---|
| %(user_name)s (talk • contribs) | %(userreg)s | %(ipb_expiry)s | %(watchers)s | %(active_watchers)s | %(gender)s | %(mailable)s%(last_active)s |