User:Dclemens1971/BLARtool.js
//
(function () {
if (mw.config.get('wgNamespaceNumber') !== 0) return;
const config = {
defaultNotification: "prompt", // "A" = Uw-blar, "B" = friendly, "prompt" = ask each time
autoLog: true,
autoWatchlist: true
};
mw.loader.using(['mediawiki.api', 'mediawiki.util'], function () {
$(function () {
mw.util.addPortletLink(
'p-cactions',
'#',
'BLAR',
'ca-blar',
'Blank and redirect with {{R with history}}'
);
$('#ca-blar').on('click', async function (e) {
e.preventDefault();
if (!$('#blar-warning').length) {
$('#contentSub').prepend(`
⚠️ Please ensure you are familiar with the process at
WP:BLAR before using this script.
Do not blank and redirect a page if this action has already been done and contested; instead, discuss on the article talk page or open a
WP:AFD discussion.
You are responsible for any actions you take using this script.
`);
}
const isRedirect = mw.config.get('wgIsRedirect');
if (isRedirect) {
alert('This page is already a redirect. BLAR aborted.');
return;
}
let target = prompt('Enter the target page for the redirect (case-sensitive):');
if (target === null) return;
target = target.trim();
if (!target) return;
const pageName = mw.config.get('wgPageName');
const userName = mw.config.get('wgUserName');
const api = new mw.Api();
try {
// Fetch CSRF token
const token = await api.get({
action: 'query',
meta: 'tokens'
}).then(res => res.query.tokens.csrftoken);
// Get the page creator
const creator = await api.get({
action: 'query',
prop: 'revisions',
titles: pageName,
rvlimit: 1,
rvdir: 'newer',
rvprop: 'user'
}).then(res => {
const pages = res.query.pages;
return Object.values(pages)[0].revisions[0].user;
});
// Redirect target check
const redirectCheck = await api.get({
action: 'query',
titles: target,
redirects: 1
});
const redirectTo = (() => {
const pages = redirectCheck.query.pages;
const page = pages[Object.keys(pages)[0]];
return page.redirects ? page.redirects[0].title : null;
})();
if (redirectTo) {
const confirmRedirect = confirm(`The target page "${target}" is a redirect. Do you want to instead redirect to "${redirectTo}"?`);
if (!confirmRedirect) return;
target = redirectTo;
}
const redirectText = `#REDIRECT ${target}\n{{R with history|${target}}}`;
const summary = `WP:BLAR to ${target}.`;
// Perform the page redirect
await api.postWithToken('csrf', {
action: 'edit',
title: pageName,
text: redirectText,
summary: summary,
minor: false,
nocreate: true
});
// Target talk page - add template before TOC
const talkText = await api.get({
action: 'parse',
page: `Talk:${target}`,
prop: 'wikitext'
}).then(res => res.parse.wikitext['*']);
const tocPos = talkText.indexOf('__TOC__');
const newTalkText = tocPos !== -1
? talkText.slice(0, tocPos) + `\n{{Blank and redirect notice|${pageName}}}\n` + talkText.slice(tocPos)
: talkText + `\n{{Blank and redirect notice|${pageName}}}\n`;
await api.postWithToken('csrf', {
action: 'edit',
title: `Talk:${target}`,
text: newTalkText,
summary: `Notifying of redirect from ${pageName}`
});
// Notify page creator
let notifChoice = config.defaultNotification;
if (notifChoice === 'prompt') {
notifChoice = prompt(
'Notify page creator?\nA = Use {{Uw-blar}}\nB = Use friendly message\n(Leave blank to skip)',
'A'
);
if (notifChoice === null) return;
}
if (notifChoice.toUpperCase() === 'A' || notifChoice.toUpperCase() === 'B') {
const userTalk = `User talk:${creator}`;
let message = '';
if (notifChoice.toUpperCase() === 'A') {
message = '{{Uw-blar}}';
} else {
const defaultFriendly = `== BLAR notice ==\nHi there. While reviewing new pages, I noticed that a page you created, ${pageName.replace(/_/g, ' ')}, does not appear to meet Wikipedia's notability guidelines as a standalone article. As an alternative to deletion, I've redirected it to ${target}. If you disagree, feel free to revert my redirect and we can proceed to a deletion discussion at Wikipedia:Articles for deletion. (If you reply to me here, please ping me as I am not watching this page.) Thanks! Dclemens1971 (talk) 02:28, 11 April 2025 (UTC)`;
message = prompt('Edit the friendly message below before sending:', defaultFriendly);
if (message === null) return;
}
await api.postWithToken('csrf', {
action: 'edit',
title: userTalk,
appendtext: `\n${message}`,
summary: `Notifying about redirect of ${pageName}`
});
}
// Log to user BLAR log page
if (config.autoLog) {
const logTitle = `User:${userName}/BLAR log`;
let existingLogText = '';
try {
const logData = await api.get({
action: 'query',
titles: logTitle,
prop: 'revisions',
rvprop: 'content',
rvslots: 'main'
});
const pages = logData.query.pages;
const page = pages[Object.keys(pages)[0]];
if (page.revisions && page.revisions.length > 0) {
existingLogText = page.revisions[0].slots.main['*'];
}
const updatedLog = `${existingLogText}\n* ${pageName} → ${target} — 02:28, 11 April 2025 (UTC)`;
await api.postWithToken('csrf', {
action: 'edit',
title: logTitle,
text: updatedLog,
summary: `Logged BLAR of ${pageName}`,
createonly: false
});
} catch (logErr) {
console.warn('Could not update BLAR log:', logErr);
}
}
if (config.autoWatchlist) {
const expiry = new Date();
expiry.setDate(expiry.getDate() + 7);
const expiryStr = expiry.toISOString();
await api.postWithToken('csrf', {
action: 'watch',
titles: `${pageName}|Talk:${target}`,
expiry: expiryStr
});
}
// Success popup
const popup = document.createElement('div');
popup.innerHTML = `
`;
document.body.appendChild(popup);
setTimeout(() => popup.remove(), 5000);
} catch (error) {
console.error("BLAR script error:", error);
alert("An error occurred. Check the console for details.");
}
});
});
});
})();
//