Content deleted Content added
Update with bug fix for CfD, cleaning up code significantly, and code for getting redirect data [Factotum] |
Update - fix redirect target notifications, RFD: check titles are redirects, hopefully fix major bug with options being global [Factotum] |
||
Line 1:
// <nowiki>
// todo (ignore): make counter inline, remove progresss and progressElement from editPage(), more dynamic reatelimit wait.
// counter semi inline; adjust align in createProgressBar()
// Function to wipe the text content of the page inside #bodyContent
// Batches aren't quite sync
// update normalise function for CfD - use mw.Title()
function capitalise(s) {
Line 73:
"userNotificationTemplate": 'Rfd mass notice',
"baseDiscussionPage": 'Wikipedia:Redirects for discussion/Log/',
"normaliseFunction": (title) => { return
"actions":
{
'prepend': '{{subst:rfd|${sectionName}|content=\n${pageText}\n}}'
},
"displayTemplate": "{{subst:rfd2|multi=yes|redirect=${pageName}|target=
}
}
Line 281:
}
function
var
type: 'warning',
style: 'background-color: yellow;'
});
return
}
Line 292:
var messageElement = new OO.ui.MessageWidget({
type: 'success',
});
return messageElement;
}
function createDoingElement() {
var messageElement = new OO.ui.MessageWidget({
type: 'info',
});
return messageElement;
Line 303 ⟶ 310:
}
function createErrorMessage(text) {
var
type: 'error',
});
errorMessage.setLabel(text);
return errorMessage;
}
function createNominationErrorMessage() { // pretty much a duplicate of ratelimitMessage
return createErrorMessage('Could not detect where to add new nomination.')
}
Line 377 ⟶ 388:
return `<a href="/wiki/${title}" target="_blank">${title}</a>`;
}
function getDateDifference(date1) {
const currentDate = new Date();
// now
let date2 = `${currentDate.getUTCFullYear()} ${currentDate.toLocaleString('en', { month: 'long', timeZone: 'UTC' })} ${currentDate.getUTCDate()}`
// Parse the dates
const parseDate = (dateString) => {
const [year, month, day] = dateString.split(' ');
return new Date(`${year}-${month}-${day}`);
};
const d1 = parseDate(date1);
const d2 = parseDate(date2);
// Calculate the time difference in milliseconds
const timeDifference = Math.abs(d2 - d1);
// Convert the time difference from milliseconds to days
const dayDifference = Math.ceil(timeDifference / (1000 * 60 * 60 * 24));
return dayDifference;
}
function deepCopy(obj) {
if (obj === null || typeof obj !== 'object') {
return obj;
}
if (obj instanceof OO.ui.Element) {
return obj;
}
if (Array.isArray(obj)) {
const copy = [];
for (let i = 0; i < obj.length; i++) {
copy[i] = deepCopy(obj[i]);
}
return copy;
}
const copy = {};
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
copy[key] = deepCopy(obj[key]);
}
}
return copy;
}
function parseHTML(html) {
Line 575 ⟶ 635:
format: 'json'
}).then(function (data) {
return data.query;
}).catch(function (error) {
console.error('Error occurred while fetching page author:', error);
Line 670 ⟶ 730:
let redirectTitles = titles.map(title => title.replace(/ /g, '_')); // Replace spaces with underscores
let redirectTargets = {};
let nonredirects = [];
for (let i = 0; i < redirectTitles.length; i += queryBatchSize) {
let batch = redirectTitles.slice(i, i + queryBatchSize);
Line 676 ⟶ 737:
await getRedirectData(batchTitles)
.then(data => {
});
let redirects = new Set(data.redirects.map(r => r.to))
let pages = new Set(Object.values(data.pages).map(p => p.title));
nonredirects.push(...[...pages].filter(x => !redirects.has(x)))
} else {
nonredirects.push(...Object.values(data.pages).map(p => p.title))
}
})
.catch(error => {
Line 692 ⟶ 754:
});
}
return [redirectTargets, nonredirects];
} catch (error_1) {
console.error('Error occurred while fetching redirect targets', error_1);
return [redirectTargets, nonredirects];
}
}
function editPage(options) {
console.log(options)
options.text = options.textToModify;
Line 715 ⟶ 778:
sleep(1000);
}
var requestData = {
action: 'edit',
// title: 'User:Qwerfjkl/sandbox/51',
title: options.title,
summary: options.summary,
Line 961 ⟶ 1,024:
if (nominationToggleOld.isSelected()) {
if (discussionLinkInputField.getValue().match(config.discussionLinkRegex)) {
sectionName = discussionLinkInputField.getValue().trim().match(config.discussionLinkRegex)[1];
}
}
Line 979 ⟶ 1,042:
return str;
}
} else if (XFD === 'RFD') {
if (str.toLowerCase().startsWith('{{subst:rfd|')) {
str = str.replace(/\{\{subst:rfd\|/i, '')
Line 993 ⟶ 1,056:
if (XFD !== 'CFD') {
prependTextInputField.setValue(config.actions.prepend.replace('${sectionName}', sectionName))
if (XFD === 'RFD') {
if (discussionLinkInputField.getValue().match(config.discussionLinkRegex)) {
let date = discussionLinkInputField.getValue().trim().match(/^Wikipedia:Redirects for discussion\/Log\/(\d\d\d\d \w+ \d\d)?#.+$/)[1]
let difference = getDateDifference(date)
if (difference !== 0) {
prependTextInputField.setValue(config.actions.prepend.replace('{{subst:rfd|${sectionName}|', `{{subst:rfd|${sectionName}|days=${difference}|`))
} // else leave as default above
}
}
}
discussionLinkInputField.on('change', function () {
Line 999 ⟶ 1,071:
sectionName = discussionLinkInputField.getValue().replace(config.discussionLinkRegex, '$1').trim();
var text = prependTextInputField.getValue();
if (XFD === 'RFD') {
const date = discussionLinkInputField.getValue().trim().match(/^Wikipedia:Redirects for discussion\/Log\/(\d\d\d\d \w+ \d\d?)#.+$/)[1]
if (/(\| *days *= *)\d+/.test(text)) { // already has days=, update
text = text.replace(/(\| *days *= *)\d+/, '$1'+getDateDifference(date))
text = replaceOccurence(text, oldSectionName, sectionName);
} else {
text = replaceOccurence(text, oldSectionName, sectionName+'|days='+getDateDifference(date));
}
} else text = replaceOccurence(text, oldSectionName, sectionName);
prependTextInputField.setValue(text);
}
});
Line 1,242 ⟶ 1,326:
return allTitles.concat(Object.keys(obj.titles));
}, []);
fetchingRedirectsElement.setLabel('Fetching redirect targets...')
fetchingRedirectsElement.$element.css('margin-top', '16px');
bodyContent.append(fetchingRedirectsElement.$element);
let fetchedRedirectsElement = createCompletedElement();
fetchedRedirectsElement.setLabel('Fetched redirect targets')
fetchedRedirectsElement.$element.css('margin-top', '16px');
var [redirectTargets, nonredirects] = await createRedirectTargetsList(allTitles);
// window.batches=batches
batches[0].titles = Object.assign(Object.keys(batches[0].titles).filter(x => !nonredirects.includes(x)), {})
console.log(batches)
if (!Object.keys(redirectTargets).length) {
var errorMessageElement = createErrorMessage('None of the titles are redirects, aborting.');
bodyContent.append(errorMessageElement.$element);
return;
}
console.log(nonredirects)
if (nonredirects.length) {
let nonredirectsWarningMessage = createWarningMessage();
let nonRedirectsHTML = $('<div>').append($('<span>').text('The following pages were ignored because they are not redirects:'))
let $listElement = $('<ul>')
nonredirects.forEach(item => {
const $listItem = $('<li>').html(makeLink(item));
$listElement.append($listItem);
});
nonRedirectsHTML.append($listElement)
nonredirectsWarningMessage.setLabel(nonRedirectsHTML)
bodyContent.append(nonredirectsWarningMessage.$element)
}
fetchingRedirectsElement.$element.hide();
bodyContent.append(fetchedRedirectsElement.$element);
}
console.log(redirectTargets);
let fetchingAuthorsElement = createDoingElement();
fetchingAuthorsElement.setLabel('Fetching authors...')
fetchingAuthorsElement.$element.css('margin-top', '16px');
bodyContent.append(fetchingAuthorsElement.$element);
let fetchedAuthorsElement = createCompletedElement();
fetchedAuthorsElement.setLabel('Fetched authors')
fetchedAuthorsElement.$element.css('margin-top', '16px');
let authors;
if (redirectTargets) {
authors = await createAuthorList(Object.keys(redirectTargets));
} else {
authors = await createAuthorList(allTitles);
}
fetchingAuthorsElement.$element.hide();
bodyContent.append(fetchedAuthorsElement.$element);
function processContent(options) {
function getKeyByValue(object, value) {
return Object.keys(object).find(key => object[key] === value);
}
// let {content, titles, textToModify, summary, type, doneMessage, headingLabel} = options
console.log(options)
Line 1,261 ⟶ 1,408:
fieldset.addItems([options.progressElement]);
options.ratelimitMessage =
options.ratelimitMessage.toggle(false);
fieldset.addItems([options.ratelimitMessage]);
Line 1,313 ⟶ 1,460:
for (const title of options.titles) {
// RfD needs special handling here, because it wraps around the whole page content
let data = deepCopy(options)
if (XFD === 'RFD' && text = await getWikitext(title);
console.log(text)
console.log(
}
data.textToModify = data.textToModify.replace('${redirectTitle}',getKeyByValue(redirectTargets, new mw.Title(title).getSubjectPage().getPrefixedText()) )
}
data.title = title
console.log('Data:')
console.log(data)
var promise = editPage(data);
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)
}
Line 1,343 ⟶ 1,498:
bodyContent.append(completedElement.$element);
}
resolve()
// alert('Resolved: done');
})
.catch(function (error) {
console.error("Error occurred during title processing:", error);
resolve();
// alert('Resolved: error')
});
});
Line 1,371 ⟶ 1,528:
const nominationSummary = `Adding mass nomination at [[#${newNomHeaderInputField.getValue().trim()}]]` + advSummary;
if (XFD === 'RFD') {
var redirectTargetNotification = `{{subst:Rfd notice|\${redirectTitle}|${
var redirectTargetNotificationSummary = `Notice of [[${summaryDiscussionLink}]]${advSummary}`
}
Line 1,380 ⟶ 1,537:
nominationText = `==== ${newNomHeaderInputField.getValue().trim()} ====\n`;
for (const batch of batches) {
var action = batch.actionInputField.getValue().trim() || false;
for (const page of Object.keys(batch.titles)) {
if (XFD == 'CFD') {
Line 1,398 ⟶ 1,555:
nominationText += `:* '''Propose ${action}''' {{${categoryTemplateDropdown.getValue()}|${page}}}${targetText}\n`;
} else {
nominationText += config.displayTemplate.replaceAll('${pageName}', page).replaceAll('${redirectTarget}', redirectTargets[page]) + '\n';
}
}
Line 1,441 ⟶ 1,598:
if (XFD === 'RFD') {
batchesToProcess.push({
id: 'rfd-notify-target',
titles: Object.values(redirectTargets).map(title => {
let page = new mw.Title(title)
Line 1,465 ⟶ 1,623:
// abort handling is now only in the editPage() function
for (const batch of batchesToProcess) {
// alert(`starting batch ${batch.headingLabel}`)
await processContent(batch);
// alert(`batch ${batch.headingLabel} done`)
}
Line 1,477 ⟶ 1,637:
});
});
}
}
|