User:Danski454/move-links.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:Danski454/move-links. |
//TODO: Image links, transclusions
moveLinks = {};
(function ($, mw){
if (mw.config.get("wgUserGroups").indexOf("autoconfirmed") === -1 && mw.config.get("wgUserGroups").indexOf("confirmed") === -1){
return;
}
var currentIntervalID, left = 0, target, active = false, origin, limit;
var templatequery, otherquery, transclusionquery;
function confirm(nonredir, redir, transclusions){
if (nonredir + redir + transclusions <= 50) {
limit = 55;
return true;
}
var groups = mw.config.get("wgUserGroups");
if (groups.indexOf("extendedconfirmed") !== -1 || groups.indexOf("sysop") !== -1) {
limit = 100000;
var total = nonredir + redir + trans;
var time = total / 12;
if (nonredir >= 500 || redir >= 500 || transclusions >= 500) {
time = Math.floor(time / 5) * 5;
total = Math.floor(total / 10) * 10;
return window.confirm("This page is linked from at least " +
total + " pages, converting all links will take at least" + time +
" minutes. Some links may not be converted. Do you wish to continue?");
}
time = Math.round(time);
return window.confirm("This page is linked from " + total + " pages, converting all links will take about " + time + " minutes. Do you wish to continue?");
}
limit = 50;
return window.confirm("This page is linked from over 50 pages. As you are not extended confirmed, some links may not be converted. Do you wish to continue?");
}
function run(o, t, templates, redirects, articles, files, other, transclusions){
if (active) {///only allow one copy per page, as we have state
console.log("Only one instance of move links can be run at once.");
return;
}
active = true;
target = t;
origin = o;
var namespaces = [];
if (other) {
for (var ns in mw.config.get("wgFormattedNamespaces")) {
if (ns <= 0 || ns === 6 || ns === 10) {
continue;
}
namespaces.push(ns);
}
}
if (articles) {
namespaces.push(0);
}
if (templates) {
namespaces.push(10);
}
if (files) {
namespaces.push(6);
}
var redir, nonredir = namespaces.length ? undefined : 0, redirquery, trans;
if (redirects) {
$.ajax({
url: mw.config.get("wgServer") + mw.config.get("wgScriptPath") + '/api.php?action=query&format=json&list=backlinks&blfilterredir=redirects&bllimit=500&bltitle=' +
encodeURIComponent(origin),
dataType: "json",
success: function(data){
redir = data.query.backlinks.length;
redirquery = data.query.backlinks;
if (nonredir !== undefined && trans !== undefined) {
if (confirm(nonredir, redir, trans)) {
doConversions(origin, templates, redirects, articles, files, other, transclusions, redirquery);
}
}
},
error: function() {
redir = 0;
console.log("Move links failed to load redirects.");
}
});
}
else {
redir = 0;
}
if (transclusions) {
$.ajax({
url: mw.config.get("wgServer") + mw.config.get("wgScriptPath") + '/api.php?action=query&format=json&prop=transcludedin&tiprop=title&tilimit=500&titles=' +
encodeURIComponent(origin),
dataType: "json",
success: function(data){
for (var p in data.query.pages) {
trans = data.query.pages[p].transcludedin.length;
transclusionquery = data.query.pages[p].transcludedin;
}
left += trans;
if (nonredir !== undefined && redir !== undefined) {
if (confirm(nonredir, redir, trans)) {
doConversions(origin, templates, redirects, articles, files, other, transclusions, redirquery);
}
}
},
error: function() {
redir = 0;
console.log("Move links failed to load transclusions.");
}
});
}
else {
trans = 0;
}
if (namespaces.length) {
$.ajax({
url: mw.config.get("wgServer") + mw.config.get("wgScriptPath") + '/api.php?action=query&format=json&list=backlinks&blfilterredir=nonredirects&bllimit=500&bltitle=' +
encodeURIComponent(origin) + "&blnamespace=" + namespaces.join("%7C"),
dataType: "json",
success: function(data){
nonredir = data.query.backlinks.length;
if (redir !== undefined && trans !== undefined) {
if (confirm(nonredir, redir, trans)) {
doConversions(origin, templates, redirects, articles, files, other, transclusions, redirquery);
}
}
},
error: function() {
nonredir = 0;
console.log("Move links failed to load non-redirects.");
}
});
}
}
//these functions are used when we finish ging through a set of pages
function templateNext(){
if (templatequery) {
left -= templatequery.length;
currentIntervalID = window.setInterval(intervalConversions, 5000, templatequery, othersNext, "link");
}
else {
othersNext();
}
}
function othersNext(){
if (otherquery) {
left -= otherquery.length;
currentIntervalID = window.setInterval(intervalConversions, 5000, otherquery, transclusionsNext, "link");
}
else {
transclusionsNext();
}
}
function transclusionsNext(){
if (transclusionquery) {
left -= transclusionquery.length;
currentIntervalID = window.setInterval(intervalConversions, 5000, transclusionquery, done, "transclusion");
}
else {
done();
}
}
function doConversions(origin, templates, redirects, articles, files, other, transclusions, redirquery){
function next(){
if (redirects) {
currentIntervalID = window.setInterval(intervalConversions, 5000, redirquery, templateNext, "redirect");
}
else {
templateNext();
}
}
$("#move-link-box").html('<span id="move-links-pages-left">Unknown</span> pages remaining (estimated time left: <span id="move-links-time-left">unknown</span>)');
var namespaces = [];
if (other) {
for (var ns in mw.config.get("wgFormattedNamespaces")) {
if (ns <= 0 || ns === 6 || ns === 10) {
continue;
}
namespaces.push(ns);
}
}
if (articles) {
namespaces.push(0);
}
if (files) {
namespaces.push(6);
}
if (articles || files || other) {
$.ajax({
url: mw.config.get("wgServer") + mw.config.get("wgScriptPath") + '/api.php?action=query&format=json&list=backlinks&blfilterredir=nonredirects&bllimit=500&bltitle=' +
encodeURIComponent(origin) + "&blnamespace=" + namespaces.join("%7C"),
dataType: "json",
success: function(data){
otherquery = data.query.backlinks;
left += otherquery.length;
if (templatequery !== undefined) {
next();
}
},
error: function() {
nonredir = 0;
console.log("Move links failed to load others, artciles and files.");
}
});
}
else{
otherquery = null;
}
if (templates) {
$.ajax({
url: mw.config.get("wgServer") + mw.config.get("wgScriptPath") + '/api.php?action=query&format=json&list=backlinks&blfilterredir=nonredirects&bllimit=500&bltitle=' +
encodeURIComponent(origin) + "&blnamespace=10",
dataType: "json",
success: function(data){
templatequery = data.query.backlinks;
left += templatequery.length;
if (otherquery !== undefined) {
next();
}
},
error: function() {
nonredir = 0;
console.log("Move links failed to load templates.");
}
});
}
else{
templatequery = null;
}
}
function intervalConversions(links, next, type) {
if (links.length === 0) {
//complete
window.clearInterval(currentIntervalID);
next();
return;
}
var pagesLeft = Math.min(links.length + left, limit);
var timeLeft = Math.floor(pagesLeft/12) + ":" + (((pagesLeft % 12) * 5).toString().padStart(2, "0"));//format time as m:ss
if (limit-- <= 0) {// we have done the maximum number of edits.
window.clearInterval(currentIntervalID);
done();
return;
}
$("#move-links-pages-left").text(pagesLeft.toString());
$("#move-links-time-left").text(timeLeft);
var link = links.pop();
var title = link.title;
$.getJSON(
mw.util.wikiScript('api'),
{
format: 'json',
action: 'query',
prop: 'revisions',
rvprop: 'content',
rvlimit: 1,
titles: title
}
)
.done(function ( data ) {//FIXME
var page, wikitext;
//try {
for ( page in data.query.pages ) {
wikitext = data.query.pages[page].revisions[0]['*'];
convertWikitext(wikitext, title, type);
}
//} catch ( e ) {
// console.log("Failed to edit " + title);
//}
})
.fail( function() {
console.log("Failed to edit " + title);
});
}
function done(){
active = false;
$("#move-link-box").html('<b>Done</b><br/>Check <b><a href="/wiki/Special:WhatLinksHere/' + encodeURIComponent(origin) + '">What links here</a></b>, as some links may not have been updated.');
}
function convertWikitext(wikitext, title, type){
var head, tail;
if (mw.config.get("wgNamespaceIds")[origin.split(":")[0].toLowerCase().replace(/ /g, "_")]) {// get namespace ids, check if namespae is valid (in lowercase, spaces replaced with _)
head = origin.split(":")[0] + ":" + origin.split(":")[1].charAt();//first char and namespace is case insensitive
}
else {
head = origin.charAt();//first char is case insensitive
}
tail = origin.slice(head.length).replace(/[.*+?^${}()|[\]\\\/]/g, '\\$&').replace(/[ _]/g, "[ _]");//tail is not case insensitive, but is escaped,spaces and underscores are identical
var safeHead = "";
for (var i = 0; i < head.length; i++) {
if (head.charAt(i).toLowerCase() === head.charAt(i).toUpperCase()) {
safeHead = safeHead + head.charAt(i).replace(/[.*+?^${}()|[\]\\\/]/g, '\\$&').replace(/[ _]/g, "[ _]");//escape this, it could be bad, also do spaces
}
else {
safeHead = safeHead + "[" + head.charAt(i).toLowerCase() + head.charAt(i).toUpperCase() + "]";//add both variants
}
}
var newWikitext;
switch (type) {//
case "redirect":
var re = new RegExp("(\\[\\[\\s*:?\\s*)" + safeHead + tail + "((#[^[\\]]*)?\\s*(\\|[^[\\n]+)?\\]\\])", "g");
newWikitext = wikitext.replace(re, "$1" + target + "$2");//convert redirect
break;
case "transclusion":
if (safeHead.len <= 4) {//mainspace needs :
safeHead = ":" + safeHead;
}
else if (mw.config.get("wgNamespaceIds")[origin.split(":")[0].toLowerCase().replace(/ /g, "_")] === 10) {//templates do not need prefix
safeHead = "(?::?" + safeHead.split(":")[0] + ":)?" + safeHead.split(":")[1];//use non-capturing group to not confuse replace()
}
else {//colon is optional otherwise
safeHead = ":?" + safeHead;
}
var re = new RegExp("(\\{\\{\\s*)" + safeHead + tail + "(\\s*(\\||\\}\\}))", "g");
newWikitext = wikitext.replace(re, "$1" + target + "$2");//convert template
break;
default:
var pipeRe = new RegExp("(\\[\\[\\s*:?\\s*)" + safeHead + tail + "((#[^[\\]]*)?\\s*\\|[^[\\n]+\\]\\])", "g");
var noPipeRe = new RegExp("(\\[\\[\\s*:?\\s*)(" + safeHead + tail + "(#[^[\\]|]*)?\\s*\\]\\])", "g");
var fairUseRe = new RegExp("(\\{\\{\\s*([Nn]on-free (use rationale( 2| logo)?|(media|image) rationale)|[Ll]ogo fur)\\s*\\|([^}]}?)*?\\|\\s*[Aa]rticle\\s*=\\s*)" + safeHead + tail + "(\s*\|.*?\}\})", "gs");//match all fair-use templates with >1000 uses
newWikitext = wikitext.replace(pipeRe, "$1" + target + "$2");//convert the links
newWikitext = newWikitext.replace(noPipeRe, "$1" + target + "$3|$2");//convert the links
newWikitext = newWikitext.replace(fairUseRe, "$1" + target + "$7");//convert fair use template
}
if (newWikitext === wikitext) {
//no changes, purge the page
$.ajax({
url: mw.config.get("wgServer") + mw.config.get("wgScriptPath") + '/api.php?action=purge&format=json&forcelinkupdate=1&titles=' +
encodeURIComponent(title),
dataType: "json"
});
}
else {
//save changes
$.ajax({
url: mw.util.wikiScript( 'api' ),
type: 'POST',
dataType: 'json',
data: {
format: 'json',
action: 'edit',
title: title,
text: newWikitext,
summary: "Converted links from [[" + origin + "]] to [[" + target + "]] ([[User:Danski454/move-links|move links]])",
minor: true,
token: mw.user.tokens.get( 'editToken' )
}
})
.fail(function(){
console.log("Could not save " + title);
});
}
}
$(document).ready(function(){
if (mw.config.get("wgPageName") === "Special:MovePage" && $("h1").first().text() === "Move succeeded") {
load();
}
});
function start(){
var t, o;
o = $("#mw-content-text p").first().find("b a").first().text();
t = $($("#mw-content-text p").first().find("b a")[1]).text();
run(o, t, $('#move-link-templates').is(':checked'), $('#move-link-redir').is(':checked'),
$('#move-link-article').is(':checked'), $('#move-link-file').is(':checked'), $('#move-link-other').is(':checked'), $('#move-link-trans').is(':checked'));
}
function load(){
$("#mw-content-text").append('<div id="move-link-box"><b>Update links from</b><br/><input type="checkbox" value="redirects" id="move-link-redir" checked /> Redirects <input type="checkbox" value="templates" id="move-link-templates" checked /> Templates <input type="checkbox" value="articles" id="move-link-article" checked /> Articles <input type="checkbox" value="files" id="move-link-file" checked /> Files <input type="checkbox" value="others" id="move-link-other" /> Others <input type="checkbox" value="others" id="move-link-trans" /> Transclusions<br/><input id="move-links-go" type="button" value="Submit" onclick="moveLinks.start();" /></div>');
}
moveLinks.start = start;
moveLinks.run = run;
moveLinks.load = load;
})(jQuery, mediaWiki);