User:Splarka/contribsrange.js
From Wikipedia, the free encyclopedia
Note: After saving, you have to bypass your browser's cache to see the changes. In Internet Explorer and Firefox, hold down the Ctrl key and click the Refresh or Reload button. Opera users have to clear their caches through Tools→Preferences, see the instructions for Opera. Konqueror and Safari users can just click the Reload button.
/* Special:Contributions Wildcard/CIDR lookup, version [0.1.4] Originally from: http://en.wikipedia.org/wiki/User:Splarka/contribsrange.js Notes: * Uses the API (Requires http://svn.wikimedia.org/viewvc/mediawiki?view=rev&revision=31312), which is faster than most CIDR contrib tools. * Currently uses a GET json via <script src=""> to avoid ajax problems. * Only currently works if submitted (or called by URL parameter, eg Special:Contributions/User). ** Checks namespace and date options in form. * Uses: Submit any IP CIDR range /16 or from /24 to /32. Submit any string (at least 3 characters) with a suffixed asterisk. ** eg: [123.123.123.0/24 ] or [123.123.123.* ] or [Willy* ]. ** NOTE: Currently seems broken with spaces in the search string. Possibly a fault of the API. %20,+,_ don't work To do: * Sortable by address? (not useful until pagination is available). * More like normal Special:Recentchanges (hist)(diff) blah blah blah (except talk page existence for red/blue link) with BiDi characters? * Option to refresh on page? (not really needed, but might be more handy than onload action only). * Respect limit in user prefs? frm.limit.value ? */ if(wgCanonicalSpecialPageName == 'Contributions') { addOnloadHook(prefixContribsInit); var prefixlimit = 500; var frm = ''; //global } function prefixContribsInit() { var show = (document.getElementById('contentSub')) ? document.getElementById('contentSub') : document.getElementById('topbar') show.appendChild(document.createTextNode(' \u2022 Javascript-enhanced contributions lookup enabled. You may enter a CIDR range or append an asterisk to do a prefix search.')) frm = document.getElementsByTagName('form')[0]; if(!frm.target) return; //general optionlets independant of type of search. var opt_ns = (parseInt(frm.namespace[frm.namespace.selectedIndex].value) > -1) ? '&ucnamespace=' + frm.namespace[frm.namespace.selectedIndex].value : ''; var opt_ts = ''; if(queryString('ucstart')) { opt_ts = '&ucstart=' + queryString('ucstart'); } else { var m = '' + frm.month.selectedIndex; var y = frm.year.value; if(m.length == 1) m = '0' + m if(y > 2000 && y < 2100) opt_ts = '&ucstart=' + y + '-' + m + '-01T00:00:00Z' } var options = opt_ns + opt_ts; var patternCIDR = /(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\/(2[4-9]|3[0-2]|16)/i ; var patternWild = /^.{3,}\*$/i ; if(frm.target.value.search(patternCIDR) == 0) { prefixContribsStartbox(frm.parentNode); var cidr = frm.target.value.match(patternCIDR)[0]; var range = cidr.match(/[^\/]\d{1,2}$/i)[0]; if(range == 24 || range == 16) { //prefixable CIDR, lets do-er if(range == 24) { cidr = cidr.match(/\d{1,3}\.\d{1,3}\.\d{1,3}\./)[0]; } else { cidr = cidr.match(/\d{1,3}\.\d{1,3}\./)[0]; } var url = wgScriptPath + '/api.php?action=query&format=json&callback=prefixContribs&list=usercontribs' + options + '&uclimit=' + parseInt(prefixlimit) + '&ucuserprefix=' + cidr; prefixContribsCall(url); } else { //complex CIDR, lets figure it out var oct3 = cidr.match(/\.\d{1,3}\//i)[0].replace(/(\.|\/)/g,''); cidr = cidr.match(/\d{1,3}\.\d{1,3}\.\d{1,3}\./)[0]; var num = Math.pow(2,32 - range); var start = oct3 - oct3 % num; var url = wgScriptPath + '/api.php?action=query&format=json&callback=prefixContribs&list=usercontribs' + options + '&uclimit=' + parseInt(prefixlimit) + '&ucuser='; for(var i=start;i<=start + num;i++) { url += '' + cidr + i; if(i != start + num) url += '|' } prefixContribsCall(url); } } else if(frm.target.value.search(patternWild) == 0) { //very simple wildcard, lets do-er prefixContribsStartbox(frm.parentNode); var prefix = frm.target.value.replace(/\*$/,''); prefix = prefix.substr(0,1).toUpperCase() + prefix.substr(1); var url = wgScriptPath + '/api.php?action=query&format=json&callback=prefixContribs&list=usercontribs' + options + '&uclimit=' + parseInt(prefixlimit) + '&ucuserprefix=' + prefix; prefixContribsCall(url); } } function prefixContribsStartbox(parent) { var res = document.createElement('div'); res.setAttribute('id','results-from-CIDR'); res.style.border = '1px solid black'; res.style.padding = '.5em'; var prog = document.createElement('img'); prog.setAttribute('id','prefixcontribs-prog'); prog.setAttribute('src',stylepath + '/common/images/spinner.gif'); res.appendChild(prog); parent.appendChild(res); } function prefixContribsCall(url) { var scriptElem = document.createElement('script'); scriptElem.setAttribute('src',url); scriptElem.setAttribute('type','text/javascript'); document.getElementsByTagName('head')[0].appendChild(scriptElem); } function prefixContribs(obj) { if(!obj['query'] || !obj['query']['usercontribs']) return var prog = document.getElementById('prefixcontribs-prog'); if(prog) prog.parentNode.removeChild(prog) cidr = obj['query']['usercontribs']; var res = document.getElementById('results-from-CIDR'); res.appendChild(document.createElement('hr')); if(cidr.length == 0) { res.appendChild(document.createTextNode('No changes were found for this wildcard/CIDR range.')); res.appendChild(document.createElement('hr')); return; } res.appendChild(document.createTextNode(cidr.length + ' matches in the wildcard/CIDR range specified (chronologically): ')); if(cidr.length == parseInt(prefixlimit)) { res.appendChild(document.createElement('br')); res.appendChild(document.createTextNode('Click ')); var ns = (parseInt(frm.namespace[frm.namespace.selectedIndex].value) > -1) ? '&namespace=' + frm.namespace[frm.namespace.selectedIndex].value : ''; var ts = (obj['query-continue']) ? obj['query-continue'].usercontribs.ucstart : cidr[cidr.length-1].timestamp; addlinkchild(res, wgScript + '?title=Special:Contributions&target=' + encodeURIComponent(frm.target.value) + ns + '&ucstart=' + ts, 'here'); res.appendChild(document.createTextNode(' to see the next ' + prefixlimit + ' results.')); } res.appendChild(document.createElement('hr')); for(var i=0;i<cidr.length;i++) { res.appendChild(document.createTextNode('\u2022 ' + cidr[i].timestamp.replace(/T[\d:]*Z/,' '))); addlinkchild(res, wgScript + '?title=Special:Contributions/' + cidr[i].user, cidr[i].user); res.appendChild(document.createTextNode(' edited (')); addlinkchild(res, wgScript + '?title=-&curid=' + cidr[i].pageid + '&diff=' + cidr[i].revid , 'diff'); res.appendChild(document.createTextNode(') ')); addlinkchild(res, wgScript + '?title=-&curid=' + cidr[i].pageid, cidr[i].title); if(cidr[i].comment) res.appendChild(document.createTextNode(' (' + cidr[i].comment + ')')); res.appendChild(document.createElement('br')); } } function addlinkchild(obj,href,text,id,classes) { if(!obj || !href || !text) return false; var a = document.createElement('a'); a.setAttribute('href',href); a.appendChild(document.createTextNode(text)); if(id) a.setAttribute('id',id); if(classes) a.setAttribute('class',classes); obj.appendChild(a); } function queryString(p) { var re = RegExp('[&?]' + p + '=([^&]*)'); var matches; if (matches = re.exec(document.location)) { try { return decodeURI(matches[1]); } catch (e) { } } return null; }