User:Username/BlockAbuser.js: Difference between revisions

From Test Wiki
Content deleted Content added
No edit summary
...
Line 1: Line 1:
mw.loader.using( [ 'mediawiki.util' ] ).then( function () {
mw.loader.using(['mediawiki.util', 'mediawiki.api', 'jquery'], function () {
if (mw.config.get('wgCanonicalSpecialPageName') !== 'AbuseLog') {

// Only run on Special:AbuseFilter
if ( mw.config.get( 'wgCanonicalSpecialPageName' ) !== 'AbuseFilter' ) {
return;
return;
}
}


const $content = $('#mw-content-text');
const seenUsers = new Set();
const seenUsers = new Set();
const userData = {}; // username => { latestLogId, extraHits }


// Very strict IPv4 / IPv6 detection
const ipRegex = /^(?:\d{1,3}\.){3}\d{1,3}$|:/;
const ipRegex = /^(?:\d{1,3}\.){3}\d{1,3}$|:/;


// Helper: decode username from URL
// Find all links inside the abuse log table/content
$( '#mw-content-text a' ).each( function () {
function getUsernameFromHref(href) {
const $link = $( this );
const parts = href.split('/wiki/User:');
const href = $link.attr( 'href' );
if (parts.length < 2) return null;
const text = $link.text();
return decodeURIComponent(parts[1]).replace(/_/g, ' ').trim();
}


// 1. Scan all user links, build data for each user (latest log ID, counts)
if ( !href || !text ) {
$content.find('a').each(function () {
return;
const $link = $(this);
const href = $link.attr('href');
if (!href || !href.includes('/wiki/User:')) return;

const username = getUsernameFromHref(href);
if (!username) return;
if (ipRegex.test(username)) return; // skip IPs

// The abuse log entry ID is usually part of the URL in a sibling 'details' link or 'examine' link
// but since your example shows a pattern, we'll grab the closest abuse log id from a nearby 'details' link

// Try to find closest "details" link in this log row (it's a link with URL containing 'Special:AbuseLog/')
let $row = $link.closest('li, tr, div'); // abuse log entries are typically in <li> or <tr> or <div>
if ($row.length === 0) {
// fallback: parent of parent
$row = $link.parent().parent();
}
}


// Only User: links
if ($row.length === 0) return;

if ( !href.includes( '/wiki/User:' ) ) {
// Find 'details' or 'examine' link with abuse log id
let logId = null;
$row.find('a').each(function () {
const $a = $(this);
const ahref = $a.attr('href') || '';
const match = ahref.match(/Special:AbuseLog\/(\d+)/);
if (match) {
logId = match[1];
return false; // break
}
});

if (!logId) return; // no log id found, skip

// Store only the most recent log id (higher number assumed more recent)
if (!userData[username]) {
userData[username] = { latestLogId: logId, extraHits: 0, $link: $link };
} else {
// Update latestLogId if this is newer (numerical compare)
if (parseInt(logId) > parseInt(userData[username].latestLogId)) {
userData[username].latestLogId = logId;
userData[username].$link = $link; // store link for checkbox placement
}
// Increment extra hits count
userData[username].extraHits++;
}
});

// 2. Add checkboxes ONLY next to the most recent log entry user link
Object.entries(userData).forEach(([username, data]) => {
if (!data.$link || data.$link.prev('.blockabuser-checkbox').length) {
return; // already has a checkbox
}
const $checkbox = $('<input>', {
type: 'checkbox',
class: 'blockabuser-checkbox',
'data-username': username,
'data-latestlogid': data.latestLogId,
'data-extrahits': data.extraHits
}).css({
marginRight: '6px',
verticalAlign: 'middle',
cursor: 'pointer'
}).attr('title', 'Select this user for block review');

data.$link.before($checkbox);
});

// 3. Add control button above abuse log to process checked users
const $btn = $('<button>')
.text('Open selected user AbuseLogs and generate summary')
.css({
margin: '1em 0',
padding: '6px 12px',
cursor: 'pointer'
});

$content.prepend($btn);

$btn.on('click', function () {
const checked = $('.blockabuser-checkbox:checked');
if (!checked.length) {
alert('Please select at least one user.');
return;
return;
}
}

let summaryLines = [];
checked.each(function () {
const $cb = $(this);
const username = $cb.data('username');
const latestLogId = $cb.data('latestlogid');
const extraHits = parseInt($cb.data('extrahits'), 10);

// Open user filtered AbuseLog in new tab
const abuseLogUrl = mw.util.getUrl('Special:AbuseLog', {
wpSearchUser: username
});
window.open(abuseLogUrl, '_blank');

// Compose summary line for this user
let line = `[[Special:AbuseLog/${latestLogId}]]`;
if (extraHits > 0) {
line += ` (+[[Special:AbuseLog/${username}|${extraHits}]])`;
}
summaryLines.push(line);
});

const summaryText =
'Spambot or spam-only accounts detected. Details:\n' +
summaryLines.join('\n');

// Show summary in a popup for easy copy-paste
alert(summaryText);
});
});