User:DreamRimmer/massMessageLite.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. |
![]() | This user script seems to have a documentation page at User:DreamRimmer/massMessageLite. |
//<nowiki>
//WARNING: You take full responsibility for any actions taken using this script.
//You must read and understand all relevant Wikipedia policies and abide by them
//when using this tool; failure to do so may result in being blocked from editing.
$(document).ready(function() {
function initializeMassMessage() {
$('#mw-content-text > p').remove();
$('#firstHeading').text('massMessageLite');
var pagesTextarea = new OO.ui.MultilineTextInputWidget({
placeholder: 'User talk:Example user\nUser talk:Example user2\nWikipedia talk:Example',
autosize: true,
rows: 10
}),
subjectInputField = new OO.ui.TextInputWidget({
placeholder: 'Subject of the message'
}),
messageTextarea = new OO.ui.MultilineTextInputWidget({
placeholder: 'Body of the message',
autosize: true,
rows: 10
}),
summaryInputField = new OO.ui.TextInputWidget({
placeholder: 'Edit summary'
}),
visualPreviewButton = new OO.ui.ButtonWidget({
label: 'Preview',
flags: ['primary']
}),
startButton = new OO.ui.ButtonWidget({
label: 'Send Message',
icon: 'alert',
flags: ['primary', 'progressive'],
disabled: true
}),
cancelButton = new OO.ui.ButtonWidget({
label: 'Cancel',
flags: ['primary', 'destructive'],
href: 'https:' + mw.config.get('wgServer')
}),
skipDuplicateCheckbox = new OO.ui.CheckboxInputWidget({
selected: false
}),
logContainer = $("<ul>").css({
'padding': '10px',
'margin-top': '10px',
'border': '1px solid #ccc',
'list-style-type': 'none',
'display': 'table-row',
'width': '70%'
}).hide(),
previewContainer = $('<div>').css({
'padding': '10px',
'margin': '10px',
'overflow': 'auto',
'min-height': '200px',
'max-height': '400px',
'border': '1px solid #ccc',
'width': '65%',
'display': 'table-row'
}).hide();
$('#mw-content-text').append(
$('<p>').html('<span style="font-weight: bold; color: red;">Warning:</span> <span style="font-weight: bold; color: black;">You take full responsibility for any actions taken using this script. You must read and understand all relevant <a href="https://en.wikipedia.org/wiki/Wikipedia:Policies_and_guidelines" target="_blank">Wikipedia policies</a> and abide by them when using this tool; failure to do so may result in being <a href="https://en.wikipedia.org/wiki/Wikipedia:Blocking_policy" target="_blank">blocked from editing</a>.</span>'),
$('<p>').text('Enter list of pages (one per line):').css('font-weight', 'bold'),
pagesTextarea.$element,
$('<p>').text('Subject:').css('font-weight', 'bold'),
subjectInputField.$element,
$('<p>').text('Message:').css('font-weight', 'bold'),
messageTextarea.$element,
$('<p>').text('Edit summary:').css('font-weight', 'bold'),
summaryInputField.$element,
$('<div>').css('padding', '10px'),
$('<label>').append(skipDuplicateCheckbox.$element, ' Skip pages with the same section name already present'),
$('<div>').css('padding', '10px'),
$('<div>').append(visualPreviewButton.$element, startButton.$element, cancelButton.$element),
previewContainer,
'<br/>',
logContainer
);
function addLogEntry(icon, message, color) {
var logEntry = $('<li>').css({ 'margin-bottom': '5px', 'color': color }).append(
new OO.ui.IconWidget({ icon: icon }).$element.css({ 'margin-right': '5px' }),
$('<span>').text(message)
);
logContainer.append(logEntry).show();
}
function previewMessage() {
var subject = subjectInputField.getValue().trim(),
message = messageTextarea.getValue().trim(),
wikitext = `== ${subject} ==\n${message}`;
var previewBox = $('<div>').css({
'padding': '10px',
'margin': '10px',
'overflow': 'auto',
'width': '70%',
'height': '400px'
});
previewContainer.empty().append($('<h2>').text("Message preview:"), previewBox).show();
new mw.Api().post({
action: 'parse',
text: wikitext,
title: 'Preview',
contentmodel: 'wikitext',
pst: true,
format: 'json'
}).done(function(data) {
previewBox.html(data.parse.text['*']);
$('html, body').animate({
scrollTop: previewContainer.offset().top
}, 500);
}).fail(function() {
previewBox.html('<p>Error loading preview</p>');
});
startButton.setDisabled(false);
}
function sendMessage() {
var pages = pagesTextarea.getValue().split("\n").map(page => page.trim()).filter(page => page),
subject = subjectInputField.getValue().trim(),
message = messageTextarea.getValue().trim(),
summary = summaryInputField.getValue().trim() + " (using [[User:DreamRimmer/massMessageLite|massMessageLite]])",
wikitext = `== ${subject} ==\n${message}`,
skipDuplicate = skipDuplicateCheckbox.isSelected(),
userGroups = mw.config.get('wgUserGroups'),
isSysop = userGroups.includes('sysop'),
maxMessagesPerMinute = isSysop ? 25 : 15,
sentMessages = 0,
startTime = new Date().getTime();
if (pages.length === 0 || subject === "" || message === "" || summary === "") {
alert("Error: Please fill in all fields.");
return;
}
logContainer.empty().append($('<h2>').text("Delivery logs:")).css('margin-top', '5px');
logContainer.show();
var currentIndex = 0;
function processNextPage() {
if (currentIndex >= pages.length) {
return;
}
var page = pages[currentIndex];
new mw.Api().get({
action: 'query',
prop: 'revisions',
titles: page,
rvprop: 'content',
rvslots: '*'
}).done(function(data) {
var pageId = Object.keys(data.query.pages)[0];
if (pageId === '-1') {
addLogEntry('alert', `Page ${page} does not exist.`, 'red');
currentIndex++;
processNextPage();
return;
}
var content = data.query.pages[pageId].revisions[0].slots.main['*'];
if (content.includes("{{User:DreamRimmer/NoMassMessage}}")) {
addLogEntry('alert', `${page} was skipped; (opted-out of message delivery)`, 'red');
currentIndex++;
processNextPage();
return;
}
if (skipDuplicate && content.includes(`== ${subject} ==`)) {
addLogEntry('alert', `Message already exists on ${page}.`, 'red');
currentIndex++;
processNextPage();
return;
}
var newContent = content + "\n\n" + wikitext;
new mw.Api().postWithToken('csrf', {
action: 'edit',
title: page,
text: newContent,
summary: summary
}).done(function() {
addLogEntry('check', `Message sent to ${page}.`, 'green');
sentMessages++;
currentIndex++;
checkRateLimitAndContinue();
}).fail(function() {
addLogEntry('alert', `Failed to send message to ${page}.`, 'red');
currentIndex++;
checkRateLimitAndContinue();
});
}).fail(function() {
addLogEntry('alert', `Failed to retrieve content of ${page}.`, 'red');
currentIndex++;
checkRateLimitAndContinue();
});
}
function checkRateLimitAndContinue() {
var currentTime = new Date().getTime(),
elapsedTime = (currentTime - startTime) / 1000,
maxMessages = maxMessagesPerMinute,
sleepTime = (60 / maxMessages) * sentMessages - elapsedTime;
if (sleepTime > 0) {
addLogEntry('clock', `Sleeping for ${Math.ceil(sleepTime)} seconds to avoid flooding recent changes...`, 'blue');
setTimeout(processNextPage, sleepTime * 1000);
} else {
processNextPage();
}
}
processNextPage();
$('html, body').animate({
scrollTop: logContainer.offset().top
}, 500);
}
visualPreviewButton.on('click', previewMessage);
startButton.on('click', sendMessage);
}
function checkUserAccess() {
var username = mw.config.get('wgUserName');
new mw.Api().get({
action: 'query',
titles: 'User:DreamRimmer/massmessage.json',
prop: 'revisions',
rvprop: 'content'
}).done(function(data) {
var pageId = Object.keys(data.query.pages)[0];
if (pageId === '-1') {
alert("Error: Cannot retrieve access control list.");
window.location.href = mw.config.get('wgServer');
return;
}
var content = data.query.pages[pageId].revisions[0]['*'],
accessControl = JSON.parse(content);
if (accessControl.blockedUsers.includes(username)) {
alert("You are blocked from using this script.");
window.location.href = mw.config.get('wgServer');
return;
}
if (accessControl.allowedUsers.includes(username)) {
initializeMassMessage();
} else {
var userGroups = mw.config.get('wgUserGroups');
if (userGroups.includes('extendedconfirmed') || userGroups.includes('sysop')) {
initializeMassMessage();
} else {
alert("You do not have permission to use this script. Please contact User:DreamRimmer.");
window.location.href = mw.config.get('wgServer');
}
}
}).fail(function() {
alert("Error: Cannot retrieve access control list.");
window.location.href = mw.config.get('wgServer');
});
}
$.when(mw.loader.using('mediawiki.util'), $.ready).then(function() {
mw.util.addPortletLink(
'p-tb',
mw.util.getUrl('Special:BlankPage/massMessageLite'),
'massMessageLite'
);
});
if (mw.config.get('wgCanonicalSpecialPageName') === 'Blankpage' && mw.config.get('wgTitle').split('/', 2)[1] === 'massMessageLite') {
$.when(mw.loader.using('oojs-ui-core'), $.ready).then(function() {
checkUserAccess();
});
}
});
//</nowiki>