Content deleted Content added
cleanup, bugfixes: adding nomination to page, filtering users to notify [Factotum] |
Update with bug fix for CfD, cleaning up code significantly, and code for getting redirect data [Factotum] |
||
Line 1:
// <nowiki>
//
// todo: make counter inline, remove progresss and progressElement from editPAge(), more dynamic reatelimit wait.
Line 567 ⟶ 564:
}
});
});
}
function getRedirectData(titles) {
var api = new mw.Api();
return api.get({
action: 'query',
titles,
redirects: 1,
format: 'json'
}).then(function (data) {
return data.query; // needs redirects and normalized
}).catch(function (error) {
console.error('Error occurred while fetching page author:', error);
return false;
});
}
Line 611 ⟶ 623:
});
}
// Function to create a list of page authors and filter duplicates
Line 631 ⟶ 644:
.then(response => {
response.forEach(user => {
console.log(user)
if (user
&& (!user.blockexpiry || user.blockexpiry !== "infinite" || 'blockpartial' in user)
&& !user.groups?.includes('bot')
&& !filteredAuthorList.includes('User talk:' + user.name))
filteredAuthorList.push('User talk:' + user.name);
Line 650 ⟶ 664:
}
// Function to
async function createRedirectTargetsList(titles) {
try {
let queryBatchSize = 50;
let redirectTitles = titles.map(title => title.replace(/ /g, '_')); // Replace spaces with underscores
let redirectTargets = {};
for (let i = 0; i < redirectTitles.length; i += queryBatchSize) {
let batch = redirectTitles.slice(i, i + queryBatchSize);
let batchTitles = batch.join('|');
await getRedirectData(batchTitles)
.then(data => {
let normalized = {};
data.normalized.forEach(normalizedTitle => {
normalized[normalizedTitle.to] = normalizedTitle.from;
}
)
let redirects = data.redirects;
redirects.forEach(item => {
if (item.from in normalized) redirectTargets[normalized[item.from]] = item.to;
else redirectTargets[item.from] = item.to;
})
})
.catch(error => {
console.error("Error querying API:", error);
});
}
return redirectTargets;
} catch (error_1) {
console.error('Error occurred while fetching redirect targets', error_1);
return redirectTargets;
}
}
function editPage(options) {
console.log(options)
options.text = options.textToModify;
var api = new mw.Api();
Line 658 ⟶ 708:
messageElement.setLabel((options.retry) ? $('<span>').text('Retrying ').append($(makeLink(options.title))) : $('<span>').text('Editing ').append($(makeLink(options.title))));
options.progressElement.$element.append(messageElement.$element);
var container = $('.sticky-container');
container.scrollTop(container.prop("scrollHeight"));
if (options.retry) {
sleep(1000);
}
Line 668 ⟶ 718:
var requestData = {
action: 'edit',
//title: 'User:Qwerfjkl/sandbox/51',
summary: options.summary,
format: 'json'
};
if (options.type === 'prepend') { //
requestData.nocreate = 1; // don't create new page when tagging
// parse title
var targets = options.titlesDict[options.title];
for (let i = 0; i < targets.length; i++) {
// we add 1 to i in the replace function because placeholders start from $1 not $0
let placeholder = '$' + (i + 1);
options.text = options.text.replace(placeholder, targets[i]);
}
options.text = options.text.replace(/\$\d/g, ''); // remove unmatched |$x
requestData.prependtext = options.text.trim() + '\n\n';
} else if (options.type === 'append') { // user
requestData.appendtext = '\n\n' + options.text.trim();
} else if (options.type === 'text') {
requestData.text = options.text;
}
console.log(requestData)
return new Promise(function (resolve, reject) {
if (window.abortEdits) {
Line 702 ⟶ 754:
if (data.edit && data.edit.result === 'Success') {
messageElement.setType('success');
messageElement.setLabel($('<span>' + makeLink(options.title) + ' edited successfully</span><span class="massxfdundo" data-revid="' + data.edit.newrevid + '" data-title="' + options.title + '"></span>'));
resolve();
Line 708 ⟶ 760:
messageElement.setType('error');
messageElement.setLabel($('<span>Error occurred while editing ' + makeLink(options.title) + ': ' + data + '</span>'));
console.error('Error occurred while prepending text to page:', data);
reject();
}
}).catch(function (error) {
messageElement.setType('error');
messageElement.setLabel($('<span>Error occurred while editing ' + makeLink(options.title) + ': ' + error + '</span>'));
console.error('Error occurred while prepending text to page:', error); // handle: editconflict, ratelimit (retry)
if (error == 'editconflict') {
editPage(
resolve();
});
} else if (error == 'ratelimited') {
options.progress.setDisabled(true);
handleRateLimitError(options.ratelimitMessage).then(function () {
options.progress.setDisabled(false);
editPage(
resolve();
});
Line 1,076 ⟶ 1,128:
startButton.on('click', async function () {
var isOld = nominationToggleOld.isSelected();
Line 1,107 ⟶ 1,159:
}
batches = actions.map(function ({ titleListInputField, prependTextInputField, label, actionInputField }) {
if (!(prependTextInputField.getValue().trim()) || (XFD === 'RFD' && !prependTextInputField.getValue().includes('${pageText}'))) {
prependTextInputField.setValidityFlag(false);
error = true;
Line 1,191 ⟶ 1,243:
}, []);
let authors = await createAuthorList(allTitles)
if (XFD === 'RFD') var redirectTargets = await createRedirectTargetsList(allTitles);
function processContent(options)
// let {content, titles, textToModify, summary, type, doneMessage,
if (!Array.isArray(options.titles)) {
options.titlesDict = options.titles;
options.titles = Object.keys(options.titles);
} else options.titlesDict = {}
var fieldset = createFieldset(options.headingLabel);
})
.catch
updateProgress();
resolve(error);
})
.error(error => {
rejectedCount++;
updateCounter();
updateProgress();
resolve(error);
});
});
}
var promises = [];
for (const title of options.titles) {
// RfD needs special handling here, because it wraps around the whole page content
if (XFD === 'RFD' && options.type === 'prepend') { // prepend implicitly means page tagging, not actually prepend in this case
text = await getWikitext(title);
console.log(text)
console.log(options.textToModify)
options.textToModify = options.textToModify.replace('${pageText}', text);
options.type = 'text';
}
options.title = title
var promise = editPage(options);
promises.push(trackPromise(promise));
if (!window.abortEdits) await sleep(100); // space out calls - not needed if they're being rejected
await massXFDratelimitPromise; // stop if ratelimit reached (global variable)
}
if (window.abortEdits) {
var abortMessage = createAbortMessage();
let revertEditsLink = $('<a id="massxfdrevertlink">Revert?</a>')
revertEditsLink.on('click', revertEdits)
abortMessage.setLabel($('<span>').append('Edits manually aborted. ').append(revertEditsLink));
var completedElement = createCompletedElement();
completedElement.setLabel(options.doneMessage);
completedElement.$element.css('margin-bottom', '16px');
bodyContent.append(completedElement.$element);
}
resolve();
})
.catch(function (error) {
console.error("Error occurred during title processing:", error);
resolve();
});
});
}
const date = new
const month = date.toLocaleString('en',
var discussionPage = `${config.baseDiscussionPage}${year} ${month} ${day}`;
if (isOld) summaryDiscussionLink = discussionLinkInputField.getValue().trim();
else if (isNew) summaryDiscussionLink = `${discussionPage}#${newNomHeaderInputField.getValue().trim()}`;
const advSummary = ' ([[User:Qwerfjkl/scripts/massXFD.js|via MassXfD.js]])';
// WIP, not finished
const categorySummary = 'Tagging page for [[' + summaryDiscussionLink + ']]' + advSummary;
const userSummary = 'Notifying user about [[' + summaryDiscussionLink + ']]' + advSummary;
const userNotification = `{{ subst: ${config.userNotificationTemplate} | ${summaryDiscussionLink} }} ~~~~`;
const nominationSummary = `Adding mass nomination at [[#${newNomHeaderInputField.getValue().trim()}]]` + advSummary;
if (XFD === 'RFD') {
var redirectTargetNotification = `{{subst:Rfd notice|\${redirectTitle}|${summaryDiscussionLink}}}`
var redirectTargetNotificationSummary = `Notice of [[${summaryDiscussionLink}]]${advSummary}`
}
var batchesToProcess = [];
}
}
nominationText += `:* '''Propose ${action}''' {{${categoryTemplateDropdown.getValue()}|${page}}}${targetText}\n`;
} else {
nominationText += config.displayTemplate.replaceAll('${pageName}', page) + '\n';
}
}
}
var rationale = rationaleInputField.getValue().trim().replace(/\n/, '<br />'); resolve();
}
}).catch(function
console.error('An error occurred in fetching wikitext:', error);
resolve();
});
} else resolve();
});
newNomPromise.then(async function () {
batches.forEach(batch => {
batchesToProcess.push({
titles: batch.titles,
textToModify: batch.prependText,
summary: categorySummary,
type: 'prepend',
doneMessage: 'All pages edited.',
headingLabel: 'Editing nominated pages' + ((batches.length > 1) ? ' — ' + batch.label : '')
});
});
});
}
if (notifyCheckbox.isSelected()) { doneMessage: 'All users
});
}
let promise = Promise.resolve();
// abort handling is now only in the editPage() function
for (const batch of batchesToProcess) {
await processContent(batch);
}
promise.then(() => {
abortButton.setLabel('Revert');
// All done
}).catch(err => {
console.error('Error occurred:', err);
});
});
});
});
|