User:DreamRimmer/test.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. |
![]() | Documentation for this user script can be added at User:DreamRimmer/test. |
mw.loader.using(['mediawiki.api', 'mediawiki.util', 'oojs-ui'], function () {
'use strict';
const api = new mw.Api();
let token = null;
async function getToken() {
try {
const res = await api.get({
action: 'query',
meta: 'tokens',
type: 'csrf'
});
token = res.query.tokens.csrftoken;
} catch (e) {
console.error('Error getting token:', e);
throw e;
}
}
function UserInputWidget(type) {
OO.ui.Widget.call(this);
this.textInput = new OO.ui.TextInputWidget({
placeholder: type === 'rename' ? 'Old username' : 'Enter username',
required: true
});
if (type === 'rename') {
this.newTextInput = new OO.ui.TextInputWidget({
placeholder: 'New username',
required: true
});
this.layout = new OO.ui.HorizontalLayout({
items: [this.textInput, this.newTextInput]
});
} else {
this.layout = new OO.ui.HorizontalLayout({
items: [this.textInput]
});
}
this.$element
.addClass('userInputWidget')
.css({
'margin-bottom': '4px'
});
this.$element.append(this.layout.$element);
}
OO.inheritClass(UserInputWidget, OO.ui.Widget);
function createUserField(type) {
return new UserInputWidget(type);
}
function ManageRALDialog(config) {
ManageRALDialog.super.call(this, config);
}
OO.inheritClass(ManageRALDialog, OO.ui.ProcessDialog);
ManageRALDialog.static.name = 'manageRALDialog';
ManageRALDialog.static.title = 'Manage RAL';
ManageRALDialog.static.actions = [
{ action: 'accept', label: 'Submit', flags: ['primary', 'progressive'] },
{ action: 'cancel', label: 'Cancel', flags: 'safe' }
];
ManageRALDialog.prototype.initialize = function () {
ManageRALDialog.super.prototype.initialize.apply(this, arguments);
this.actionDropdown = new OO.ui.DropdownInputWidget({
options: [
{ data: 'add', label: 'Add users' },
{ data: 'remove', label: 'Remove users' },
{ data: 'rename', label: 'Rename users' }
],
value: 'add'
});
this.userContainer = new OO.ui.FieldsetLayout({
label: 'Users:'
});
this.userContainer.addItems([createUserField('add')]);
this.actionDropdown.on('change', (value) => {
this.userContainer.clearItems();
this.userContainer.addItems([createUserField(value)]);
this.updateSize();
});
const addButton = new OO.ui.ButtonWidget({
label: '+',
flags: ['progressive']
});
addButton.$element.css({
'margin-top': '4px'
});
addButton.on('click', () => {
this.userContainer.addItems([createUserField(this.actionDropdown.getValue())]);
this.updateSize();
});
this.content = new OO.ui.PanelLayout({ padded: true, expanded: false });
this.content.$element.append(
new OO.ui.FieldsetLayout({
items: [
new OO.ui.FieldLayout(this.actionDropdown, { label: 'Action:', align: 'top' }),
this.userContainer,
new OO.ui.FieldLayout(addButton)
]
}).$element
);
this.$body.append(this.content.$element);
this.alertContainer = new OO.ui.LabelWidget({ label: '' });
this.alertContainer.$element.css({
padding: '5px',
margin: '5px 0',
display: 'none'
});
this.$body.append(this.alertContainer.$element);
};
ManageRALDialog.prototype.getBodyHeight = function () {
return this.content.$element.outerHeight(true) + this.alertContainer.$element.outerHeight(true) + 20;
};
ManageRALDialog.prototype.getActionProcess = function (action) {
if (action === 'accept') {
return new OO.ui.Process(async () => {
const users = this.userContainer.items.map(widget => {
return {
oldUsername: widget.textInput.getValue(),
newUsername: widget.newTextInput ? widget.newTextInput.getValue() : null
};
}).filter(user => user.oldUsername);
const actionType = this.actionDropdown.getValue();
if (users.length === 0) {
this.showAlert('Please enter at least one username.', 'error');
return;
}
const result = await editRALPage(users, actionType);
let message = '';
if (actionType === 'add') {
if (result.added.length) message += 'Added: ' + result.added.join(', ') + '. ';
if (result.alreadyExists.length) message += 'Already in list: ' + result.alreadyExists.join(', ') + '.';
} else if (actionType === 'remove') {
if (result.removed.length) message += 'Removed: ' + result.removed.join(', ') + '. ';
if (result.failedRemove.length) message += 'Failed to remove: ' + result.failedRemove.join(', ') + '.';
} else if (actionType === 'rename') {
if (result.renamed.length) message += 'Renamed: ' + result.renamed.join(', ') + '. ';
if (result.failedRename.length) message += 'Failed to rename: ' + result.failedRename.join(', ') + '.';
}
this.showAlert(message, 'success');
setTimeout(() => {
window.location.href = mw.util.getUrl('User:DreamRimmer/sandbox', { diff: 'cur' });
this.close({ action: 'accept' });
}, 6000);
});
} else if (action === 'cancel') {
return new OO.ui.Process(() => {
this.close({ action: 'cancel' });
});
}
};
ManageRALDialog.prototype.showAlert = function (message, type) {
this.alertContainer.setLabel(message);
this.alertContainer.$element.css('color', type === 'error' ? 'red' : 'green');
this.alertContainer.$element.show();
this.updateSize();
};
async function editRALPage(users, actionType) {
if (!token) await getToken();
const res = await api.get({
action: 'query',
prop: 'revisions',
titles: 'User:DreamRimmer/sandbox',
rvprop: 'content',
format: 'json'
});
const pages = res.query.pages;
const data = pages[Object.keys(pages)[0]];
let content = data.revisions[0]['*'];
const startMarker = '<!-- DannyS712 bot III: autopatrol list start -->';
const endMarker = '<!-- DannyS712 bot III: autopatrol list end -->';
const startIndex = content.indexOf(startMarker) + startMarker.length;
const endIndex = content.indexOf(endMarker);
let listContent = content.substring(startIndex, endIndex).trim().split('\n').filter(line => line.trim());
let added = [], alreadyExists = [], removed = [], failedRemove = [], renamed = [], failedRename = [];
users.forEach(user => {
const oldUserEntry = `* {{user2|${user.oldUsername}}}`;
const newUserEntry = `* {{user2|${user.newUsername}}}`;
if (actionType === 'add') {
if (!listContent.includes(oldUserEntry)) {
listContent.push(oldUserEntry);
added.push(user.oldUsername);
} else {
alreadyExists.push(user.oldUsername);
}
} else if (actionType === 'remove') {
const index = listContent.indexOf(oldUserEntry);
if (index !== -1) {
listContent.splice(index, 1);
removed.push(user.oldUsername);
} else {
failedRemove.push(user.oldUsername);
}
} else if (actionType === 'rename') {
if (user.newUsername) {
const index = listContent.indexOf(oldUserEntry);
if (index !== -1) {
listContent.splice(index, 1);
const insertionIndex = listContent.findIndex(entry => entry > newUserEntry);
if (insertionIndex === -1) {
listContent.push(newUserEntry);
} else {
listContent.splice(insertionIndex, 0, newUserEntry);
}
renamed.push(user.oldUsername + '->' + user.newUsername);
} else {
failedRename.push(user.oldUsername);
}
}
}
});
const newListContent = listContent.join('\n');
const newContent = content.substring(0, startIndex) + '\n' + newListContent + '\n' + content.substring(endIndex);
const editResult = await api.postWithToken('csrf', {
action: 'edit',
title: 'User:DreamRimmer/sandbox',
text: newContent,
summary: `Updating RAL`,
format: 'json'
});
return { added, alreadyExists, removed, failedRemove, renamed, failedRename, revisionId: editResult.edit.newrevid };
}
function init() {
if (mw.config.get('wgPageName') !== 'User_talk:DreamRimmer/sandbox') {
return;
}
const button = new OO.ui.ButtonWidget({
label: 'Manage RAL',
flags: ['primary', 'progressive']
});
button.$element.css({
position: 'fixed',
bottom: '20px',
right: '5px',
zIndex: 1000,
margin: '5px'
});
document.body.appendChild(button.$element[0]);
button.on('click', function () {
const windowManager = new OO.ui.WindowManager();
$(document.body).append(windowManager.$element);
const manageRALDialog = new ManageRALDialog({ size: 'medium' });
windowManager.addWindows([manageRALDialog]);
windowManager.openWindow(manageRALDialog);
});
}
init();
});