User:XXN/massmerge.js
< User:XXN
Note: After publishing, you may have to bypass your browser's cache to see the changes.
- Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
- Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
- Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5.
// Script for mass merging items
// Works with two parallel pair lists of items (sources & targets)
// Once installed, go to [[Special:MassMerge]] and provide the two lists of items: (1) source items, and (2) target items
// Author: XXN
mw.loader.using(['mediawiki.api.edit', 'mediawiki.Title'], function () {
"use strict";
var config = mw.config.get(['wgNamespaceNumber', 'wgTitle', 'skin']);
function removeBlanks(arr) {
var ret = [];
var i, len;
for (i = 0, len = arr.length; i < len; i++) {
var s = arr[i];
s = s.trim();
if (s) {
ret.push(s);
}
}
return ret;
}
function doMassMerge() {
var sources = document.getElementById("wdMassMergeQ1").value.split("\n");
sources = removeBlanks(sources);
if (!sources.length) {
return;
}
var targets = document.getElementById("wdMassMergeQ2").value.split("\n");
targets = removeBlanks(targets);
if (!targets.length) {
return;
}
var
api = new mw.Api(),
wdMassMergeSummary = document.getElementById("wdMassMergeSummary").value,
merged = 0,
failed = [],
error = [],
deferreds = [],
onSuccess = function () {
merged++;
document.getElementById("wdMassMergeSubmit").value = "(" + merged + ")";
};
function makeMergeFunc(source, target) {
return function () {
return $.Deferred(function (deferred) {
var options = {
action: 'wbmergeitems',
ignoreconflicts: 'description',
fromid: source,
toid: target,
summary: '[[User:XXN/massmerge.js|massmerge.js]] ' + wdMassMergeSummary
};
var promise = api.postWithEditToken(options);
promise.done(onSuccess);
promise.fail(function (code, obj) {
failed.push(source);
error.push(obj.error.info);
});
promise.always(function () {
deferred.resolve();
});
});
};
}
/*
function createRedirect(source, target) {
// we have to clear the entity first before creating the redirect...
return api.postWithEditToken({
action: 'wbeditentity',
id: source,
clear: true,
summary: 'Clearing item to prepare for redirect',
data: '{}'
}).then(function () {
return api.postWithEditToken({
action: 'wbcreateredirect',
from: source,
to: target
});
});
}
*/
// Make a chain of deferred objects. We chain them rather than execute them in
// parallel so that we don't make 1000 simultaneous merge requests and bring the
// site down. We use deferred objects rather than the promise objects returned
// from the API request so that the chain continues even if some pages gave errors.
var deferred = makeMergeFunc(sources[0], targets[0])();
for (var i = 1, len = sources.length, len2 = targets.length; i < len && i < len2; i++) {
deferred = deferred.then(makeMergeFunc(sources[i], targets[i]));
}
// Show the output and do cleanup once all the requests are done.
$.when(deferred).then(function () {
document.getElementById("wdMassMergeSubmit").value = "Done (" + merged + ")";
if (failed.length) {
var $failedList = $('<ul>');
for(var x = 0; x < failed.length; x++) {
// Link the items in the "failed" array
var failedTitle = mw.Title.newFromText(failed[x]);
var $failedItem = $('<li>');
if (failedTitle) {
$failedItem.append( $('<a>')
.attr('href', failedTitle.getUrl())
.text(failed[x])
);
} else {
$failedItem.text(failed[x]);
}
$failedItem.append(document.createTextNode(': ' + error[x]));
$failedList.append($failedItem);
}
$('#wdMassMergeFailedContainer')
.append($('<br />'))
.append($('<b>')
.text('Failed merges:')
)
.append($failedList);
}
});
}
function massMergeForm() {
var bodyContent = (config.skin == "cologneblue" ? "article" : "bodyContent");
document.getElementsByTagName("h1")[0].textContent = "XXN's mass-merge tool for Wikidata (beta)";
document.title = "XXN's mass-merge tool for Wikidata";
document.getElementById(bodyContent).innerHTML = //'<h3 id="siteSub">Wikidata</h3>' +
// '<p>XXN\'s mass-merge tool</p>' +
'<br /><br />' +
'<form id="wdMassMerge" name="wdMassMerge">' +
'<b>If you abuse this tool, it\'s <i>your</i> fault, not mine.</b>' +
'<div id="wdMassMergeFailedContainer"></div>' +
'<br /><br />' +
'Merge from items (one on each line, please):<br />' +
'<textarea tabindex="1" name="wdMassMergeQ1" id="wdMassMergeQ1" rows="5" cols="5"></textarea>' +
'Merge to items (one on each line, please):<br />' +
'<textarea tabindex="2" name="wdMassMergeQ2" id="wdMassMergeQ2" rows="5" cols="5"></textarea>' +
'<br /><br /><table style="background-color:transparent">' +
'<tr><td>Summary (optional):</td>' +
'<td><input type="text" id="wdMassMergeSummary" name="wdMassMergeSummary" maxlength="255" /></td></tr>' +
'<tr><td><input type="button" id="wdMassMergeSubmit" name="wdMassMergeSubmit" value="Merge" /></td>' +
'</form>';
document.getElementById("wdMassMergeSubmit").addEventListener("click", function (e) {
doMassMerge();
});
}
if (config.wgNamespaceNumber == -1 && config.wgTitle.toLowerCase() == "massmerge") {
massMergeForm();
}
});