User:Username/BlockAbuser.js: Difference between revisions
Jump to navigation
Jump to search
Content deleted Content added
hopefully this makes my life easier |
No edit summary |
||
| Line 1: | Line 1: | ||
mw.loader.using(['mediawiki.util', 'mediawiki.api', 'jquery'], function () { |
mw.loader.using(['mediawiki.util', 'mediawiki.api', 'jquery'], function () { |
||
// Only run on the exact Special:AbuseLog main page |
|||
if (mw.config.get('wgPageName') !== 'Special:AbuseLog') { |
if (mw.config.get('wgPageName') !== 'Special:AbuseLog') { |
||
return; |
return; |
||
| Line 6: | Line 5: | ||
const $content = $('#mw-content-text'); |
const $content = $('#mw-content-text'); |
||
| ⚫ | |||
const seenUsers = new Set(); |
|||
| ⚫ | |||
const ipRegex = /^(?:\d{1,3}\.){3}\d{1,3}$|:/; |
const ipRegex = /^(?:\d{1,3}\.){3}\d{1,3}$|:/; |
||
// Helper: decode username from URL |
|||
function getUsernameFromHref(href) { |
function getUsernameFromHref(href) { |
||
const parts = href.split('/wiki/User:'); |
const parts = href.split('/wiki/User:'); |
||
| Line 18: | Line 14: | ||
} |
} |
||
// |
// Collect user info, group links by username |
||
$content.find('li').each(function () { |
$content.find('li').each(function () { |
||
const $li = $(this); |
const $li = $(this); |
||
| ⚫ | |||
// Find first user link inside this <li> |
|||
| ⚫ | |||
const href = $(this).attr('href') || ''; |
const href = $(this).attr('href') || ''; |
||
return href.includes('/wiki/User:'); |
return href.includes('/wiki/User:'); |
||
} |
}); |
||
if ($ |
if ($userLinks.length === 0) return; |
||
| ⚫ | |||
| ⚫ | |||
const $link = $(this); |
|||
| ⚫ | |||
if (ipRegex.test(username)) return; |
if (!username || ipRegex.test(username)) return; |
||
| ⚫ | |||
$li.find('a').each(function () { |
|||
const href = $(this).attr('href') || ''; |
|||
const match = href.match(/Special:AbuseLog\/(\d+)/); |
|||
| ⚫ | |||
logId = match[1]; |
|||
return false; |
|||
| ⚫ | |||
| ⚫ | |||
if (!logId) return; |
|||
| ⚫ | |||
// Find AbuseLog id from any 'details' or 'examine' link inside this <li> |
|||
userData[username] = { |
|||
| ⚫ | |||
| ⚫ | |||
extraHits: 0, |
|||
$li: $li, |
|||
$userLink: $link, |
|||
allLinks: [$link] |
|||
}; |
|||
| ⚫ | |||
| ⚫ | |||
| ⚫ | |||
| ⚫ | |||
| ⚫ | |||
| ⚫ | |||
| ⚫ | |||
userData[username].extraHits++; |
|||
} |
} |
||
}); |
}); |
||
| ⚫ | |||
// Store or update userData with most recent log id |
|||
| ⚫ | |||
userData[username] = { latestLogId: logId, extraHits: 0, $li: $li, $userLink: $userLink }; |
|||
| ⚫ | |||
| ⚫ | |||
| ⚫ | |||
| ⚫ | |||
| ⚫ | |||
| ⚫ | |||
| ⚫ | |||
| ⚫ | |||
}); |
}); |
||
// Delink all but most recent user link per user |
|||
// Insert checkboxes once per user, inside their latest abuse log <li> before username link |
|||
Object.entries(userData).forEach(([username, data]) => { |
Object.entries(userData).forEach(([username, data]) => { |
||
data.allLinks.forEach(($link) => { |
|||
if (data.$userLink.prev('.blockabuser-checkbox').length) return; // checkbox already exists |
|||
if ($link[0] !== data.$userLink[0]) { |
|||
$link.replaceWith(document.createTextNode($link.text())); |
|||
const $checkbox = $('<input>', { |
|||
} |
|||
}); |
|||
class: 'blockabuser-checkbox', |
|||
'data-username': username, |
|||
| ⚫ | |||
'data-extrahits': data.extraHits |
|||
| ⚫ | |||
marginRight: '6px', |
|||
verticalAlign: 'middle', |
|||
| ⚫ | |||
}).attr('title', 'Select this user for block review'); |
|||
data.$userLink.before($checkbox); |
|||
}); |
}); |
||
// Add |
// Add control button above log |
||
const $btn = $('<button>') |
const $btn = $('<button>') |
||
.text('Open |
.text('Open all user AbuseLogs, talk deletion, and show summary') |
||
.css({ |
.css({ |
||
margin: '1em 0', |
margin: '1em 0', |
||
| Line 91: | Line 82: | ||
$btn.on('click', function () { |
$btn.on('click', function () { |
||
const |
const usernames = Object.keys(userData); |
||
if ( |
if (usernames.length === 0) { |
||
alert(' |
alert('No users found to process.'); |
||
return; |
return; |
||
} |
} |
||
let summaryLines = []; |
let summaryLines = []; |
||
usernames.forEach(username => { |
|||
const |
const data = userData[username]; |
||
const |
const latestLogId = data.latestLogId; |
||
const |
const extraHits = parseInt(data.extraHits, 10); |
||
const extraHits = parseInt($cb.data('extrahits'), 10); |
|||
// Open |
// Open filtered AbuseLog tab |
||
const abuseLogUrl = mw.util.getUrl('Special:AbuseLog', { |
const abuseLogUrl = mw.util.getUrl('Special:AbuseLog', { |
||
wpSearchUser: username |
wpSearchUser: username |
||
}); |
}); |
||
window.open(abuseLogUrl, '_blank'); |
window.open(abuseLogUrl, '_blank'); |
||
// Open User Talk deletion tab with prefilled reason |
|||
const talkDeleteUrl = mw.util.getUrl('Special:Delete/' + 'User_talk:' + encodeURIComponent(username), { |
|||
reason: `Talk page of an indefinitely blocked user that has little value. The content was: blahblah.` |
|||
}); |
|||
window.open(talkDeleteUrl, '_blank'); |
|||
// Compose summary line |
// Compose summary line |
||
Revision as of 02:29, 21 January 2026
mw.loader.using(['mediawiki.util', 'mediawiki.api', 'jquery'], function () {
if (mw.config.get('wgPageName') !== 'Special:AbuseLog') {
return;
}
const $content = $('#mw-content-text');
const userData = {}; // username => { latestLogId, extraHits, $li, $userLink, allLinks: [] }
const ipRegex = /^(?:\d{1,3}\.){3}\d{1,3}$|:/;
function getUsernameFromHref(href) {
const parts = href.split('/wiki/User:');
if (parts.length < 2) return null;
return decodeURIComponent(parts[1]).replace(/_/g, ' ').trim();
}
// Collect user info, group links by username
$content.find('li').each(function () {
const $li = $(this);
const $userLinks = $li.find('a').filter(function () {
const href = $(this).attr('href') || '';
return href.includes('/wiki/User:');
});
if ($userLinks.length === 0) return;
$userLinks.each(function () {
const $link = $(this);
const username = getUsernameFromHref($link.attr('href'));
if (!username || ipRegex.test(username)) return;
let logId = null;
$li.find('a').each(function () {
const href = $(this).attr('href') || '';
const match = href.match(/Special:AbuseLog\/(\d+)/);
if (match) {
logId = match[1];
return false;
}
});
if (!logId) return;
if (!userData[username]) {
userData[username] = {
latestLogId: logId,
extraHits: 0,
$li: $li,
$userLink: $link,
allLinks: [$link]
};
} else {
userData[username].allLinks.push($link);
if (parseInt(logId) > parseInt(userData[username].latestLogId)) {
userData[username].latestLogId = logId;
userData[username].$li = $li;
userData[username].$userLink = $link;
}
userData[username].extraHits++;
}
});
});
// Delink all but most recent user link per user
Object.entries(userData).forEach(([username, data]) => {
data.allLinks.forEach(($link) => {
if ($link[0] !== data.$userLink[0]) {
$link.replaceWith(document.createTextNode($link.text()));
}
});
});
// Add control button above log
const $btn = $('<button>')
.text('Open all user AbuseLogs, talk deletion, and show summary')
.css({
margin: '1em 0',
padding: '6px 12px',
cursor: 'pointer'
});
$content.prepend($btn);
$btn.on('click', function () {
const usernames = Object.keys(userData);
if (usernames.length === 0) {
alert('No users found to process.');
return;
}
let summaryLines = [];
usernames.forEach(username => {
const data = userData[username];
const latestLogId = data.latestLogId;
const extraHits = parseInt(data.extraHits, 10);
// Open filtered AbuseLog tab
const abuseLogUrl = mw.util.getUrl('Special:AbuseLog', {
wpSearchUser: username
});
window.open(abuseLogUrl, '_blank');
// Open User Talk deletion tab with prefilled reason
const talkDeleteUrl = mw.util.getUrl('Special:Delete/' + 'User_talk:' + encodeURIComponent(username), {
reason: `Talk page of an indefinitely blocked user that has little value. The content was: blahblah.`
});
window.open(talkDeleteUrl, '_blank');
// Compose summary line
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');
alert(summaryText);
});
});