User:Richwales/markusers.js
Appearance
Code that you insert on this page could contain malicious content capable of compromising your account. If you import a script from another page with "importScript", "mw.loader.load", "iusc", or "lusc", take note that this causes you to dynamically load a remote script, which could be changed by others. Editors are responsible for all edits and actions they perform, including by scripts. User scripts are not centrally supported and may malfunction or become inoperable due to software changes. A guide to help you find broken scripts is available. If you are unsure whether code you are adding to this page is safe, you can ask at the appropriate village pump. This code will be executed when previewing this page. |
Documentation for this user script can be added at User:Richwales/markusers. |
function Richwales_markUsers() {
var users = []
var userLinks = []
var userBlocked = {}
var userToolTips = {}
var userSysops = {}
var userSysopsPlus = {}
var userArbs = {}
var userUnconfirmed = {}
var userEdits = {}
var userStyle = {}
if (!window.mbTempStyle)
mbTempStyle = 'opacity: 0.7; text-decoration: line-through'
if (!window.mbIndefStyle)
mbIndefStyle = 'opacity: 0.4; font-style: italic; text-decoration: line-through'
if (!window.mbTipBoxStyle)
mbTipBoxStyle = 'font-size:smaller; background:#FFFFF0; ' +
'border:1px solid #FEA; padding:0 0.3em; color:#AAA'
if (!window.mbTooltip) {
i18n = {
// 'dsb': '(blokěrowany wót $2 za traśe wót $1: $3)',
'en': '(blocked by $2 with an expiry time of $1: $3)',
// 'eo': '(forbarita de $2 por daŭro de $1: $3)',
// 'hsb': '(zablokowany wot $2 za traće wot $1: $3)',
// 'ja': '($2によるブロック。期限:$1 理由:$3)',
// 'pt': '(bloqueado por $2 até $1: $3)',
// 'ru': '(блокировка $2 на срок $1: $3)',
// 'sv': '(har blockerats av $2 till $1: $3)',
// 'uk': '(блокування $2 на термін $1: $3)'
}
mbTooltip = /* i18n[mw.config.get('wgUserLanguage')] || */ i18n.en
}
appendCSS('.user-blocked-temp {' + mbTempStyle + '}\n' +
'.user-blocked-indef {' + mbIndefStyle + '}\n' +
'.user-blocked-tipbox {' + mbTipBoxStyle + '}\n' +
'.user-not-blocked { }\n' +
'.user-is-unconfirmed { background-color: #ddd }\n' +
'.user-is-new { background-color: #fdd }\n' +
'.user-is-sysop { background-color: #cff }\n' +
'.user-is-sysop-plus { background-color: #cfc }\n' +
'.user-may-be-arb { background-color: #fddd77 }\n' +
'.user-is-ordinary { }\n');
function apiRequest(params, callback) {
var aj = sajax_init_object()
aj.onreadystatechange = function() {
if (aj.readyState != 4 || aj.status != 200) return
callback(eval('(' + aj.responseText + ')'))
}
aj.open('GET', mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/api.php?format=json&' + params, false)
aj.send('')
}
function target(link) {
var hr = link.href;
if (!hr || hr == '') hr = link.baseURI;
if (hr.match(/&action=edit/) && !hr.match(/&action=edit&redlink=1/)) return '';
hr = hr.replace(/^.*\/(wiki\/|w\/index\.php\?title=)/, '');
hr = hr.replace(/[?&].*$/, '');
hr = hr.replace(/_/g, ' ');
hr = decodeURIComponent(hr);
if (hr.match(/#/)) hr = '';
if (hr.match(/\//) && !hr.match(/Special:Contributions\//)) hr = '';
return hr;
}
function checkLinks(namespaces) {
var content = document.getElementById('content') ||
document.getElementById('mw_content') ||
document.body
var links = content.getElementsByTagName('a')
var ns = namespaces.query.namespaces
var ca
for (var i = 0; i < namespaces.query.specialpagealiases.length; i++) {
if (namespaces.query.specialpagealiases[i].realname == 'Contributions')
ca = namespaces.query.specialpagealiases[i].aliases
}
if (!namespaces.fromcookie) {
document.cookie = 'mbNamespaces='
+ escape([ns[-1]['*'], ns[2]['*'], ns[3]['*'], ca.join('|')].join(':'))
+ '; expires=' + (new Date((new Date).getTime() + Math.exp(20))).toGMTString()
}
// User: User_talk: Special:Contributions/ in canonical form, as they are in hrefs
var isUser = new RegExp('^((' + ns[2]['*'] + '|' + ns[3]['*'] + '):|' + ns[-1]['*'] +
':(' + ca.join('|').replace(/_/g, ' ') + ')\\/)([^\\/#]*)$')
var j = 0
for (i = 0; i < links.length; i++) {
var li = links[i]
var tli = target(li)
if (!tli || tli == '') continue
if (tli.match(isUser)) {
users[j] = tli.replace(isUser, '$4')
userLinks[j++] = li
li.style.opacity = window.mbLoadingOpacity || 0.65 // a way to mark that the data is loading
}
}
if (j == 0) return // nobody to mark
// performing sort and duplicate cleanup, otherwise we risk of some users being marked twice
var usersTemp = users.join('|').split('|')
usersTemp.sort()
var u = []
u[0] = usersTemp[0]
if (usersTemp[1]) {
j = 1
for (i = 1; i < usersTemp.length; i++) {
if (usersTemp[i] != usersTemp[i-1])
u[j++] = usersTemp[i]
}
}
usersTemp = null
for (i = 0; i < links.length; i++)
links[i].style.opacity = '';
// do API requests to find blocked and special users, in batches of no more than about 1000 characters each
var query = ''
for (i = 0; i < u.length; i++) {
query += (query ? '|' : '') + encodeURIComponent(u[i])
if (query.length > 1000) {
apiRequest('action=query&list=users&usprop=groups|editcount&ususers=' + query, findSysops)
apiRequest('action=query&list=blocks&bkprop=user|expiry|by|reason&bkusers=' + query, findBlocked)
query = ''
}
}
// take care of API request for any final, leftover batch of users
if (query) {
apiRequest('action=query&list=users&usprop=groups|editcount&ususers=' + query, findSysops)
apiRequest('action=query&list=blocks&bkprop=user|expiry|by|reason&bkusers=' + query, findBlocked)
}
// mark everyone according to results of API requests
doUserMarking()
}
function findBlocked(ulist) {
if (!ulist || !ulist.query)
return;
var ul = ulist.query.blocks;
if (!ul) return;
for (var i = 0; i < ul.length; i++) {
var u = ul[i]
if (u.expiry) {
var name = u.user
userToolTips[name] = ' ' + mbTooltip.replace('$1', u.expiry.replace(/(.*)T(.*)Z/, '$1 $2 UTC'))
.replace('$2', u.by)
.replace('$3', u.reason)
userBlocked[name] = (u.expiry.substr(0,2) == 'in') ? 'indef' : 'temp'
// alert ('findBlocked: user ' + name + ': blocked (' + userBlocked[name] + ')')
}
}
}
function findSysops(ulist) {
if (!ulist || !ulist.query)
return;
var ul = ulist.query.users;
if (!ul) return;
var name;
for (var i = 0; i < ul.length; i++) {
name = ul[i].name;
var usergroups = [];
var gl = ul[i].groups;
if (gl) {
for (var gi = 0; gi < gl.length; gi++)
usergroups[gl[gi]] = 1;
if (usergroups['sysop'])
userSysops[name] = 1;
if (usergroups['checkuser'] && usergroups['oversight'])
userArbs[name] = 1;
if (usergroups['checkuser'] || usergroups['oversight'] ||
usergroups['steward'] || usergroups['bureaucrat'])
userSysopsPlus[name] = 1;
if (! usergroups['autoconfirmed'] && ! usergroups['confirmed'])
userUnconfirmed[name] = 1;
}
userEdits[name] = ul[i].editcount;
// var alertString = 'findSysops: user ' + name + ': ' + userEdits[name] + ' edits'
// if (userSysops[name]) alertString += '; sysop'
// if (userArbs[name]) alertString += '; arb?'
// if (userSysopsPlus[name]) alertString += '; func'
// if (userUnconfirmed[name]) alertString += '; unconfirmed'
// alert (alertString)
}
}
function doUserMarking() {
var span
for (var i = 0; i < users.length; i++) {
var name = users[i]
if (userStyle[name]) {
userLinks[i].className += userStyle[name]
continue
}
var us = ''
if (userBlocked[name]) {
us += ' user-blocked-' + userBlocked[name]
if (window.mbTipBox) {
span = document.createElement('span')
span.title = name + userToolTips[name]
span.className = 'user-blocked-tipbox'
span.innerHTML = '#'
userLinks[i].parentNode.insertBefore(span, ul)
}
else userLinks[i].title += tips[name]
}
else us += ' user-not-blocked'
if (userArbs[name])
us += ' user-may-be-arb'
else if (userSysopsPlus[name])
us += ' user-is-sysop-plus'
else if (userSysops[name])
us += ' user-is-sysop'
else if (userUnconfirmed[name])
us += ' user-is-unconfirmed'
else if (userEdits[name] < 100)
us += ' user-is-new'
else
us += ' user-is-ordinary'
// alert ('doUserMarking: user ' + name + ': ' + us);
userLinks[i].className += us
userStyle[name] = us
}
}
if (ca = document.getElementById('ca-showblocks'))
ca.parentNode.removeChild(ca)
var cookie = document.cookie.match(/mbNamespaces=(.*?);/)
if (cookie) {
cookie = unescape(cookie[1]).split(':')
checkLinks({
'query': {
'namespaces': { '-1': { '*': cookie[0] }, '2': { '*': cookie[1] }, '3': { '*': cookie[2] } },
'specialpagealiases': [{'realname': 'Contributions', 'aliases': cookie[3].split('|')}]
},
'fromcookie': 1
})
} else {
apiRequest('action=query&meta=siteinfo&siprop=namespaces|specialpagealiases', checkLinks)
}
}
// alert ('hooking Richwales_markUsers')
$(Richwales_markUsers);