Jump to content

User:JJPMaster/rollback.js

From Wikibooks, open books for an open world
Note: After saving, changes may not occur immediately. Click here to learn how to bypass your browser's cache.
  • Mozilla / Firefox / Safari: hold down Shift while clicking Reload, or press Ctrl-Shift-R (Cmd-Shift-R on Apple Mac);
  • Internet Explorer: hold Ctrl while clicking Refresh, or press Ctrl-F5;
  • Konqueror: simply click the Reload button, or press F5;
  • Opera users may need to completely clear their cache in Tools→Preferences.
async function getNonRolledBackEdit(page) {
	try {
	    var params = {
	        action: 'query',
	        prop: 'revisions',
	        rvprop: "user|ids|comment",
	        titles: page,
	        rvlimit: 'max',
	        format: 'json'
	    },
	    api = new mw.Api();
	
	    const data = await api.get( params );
	    var pages = data.query.pages,
	        p;
	    for ( p in pages ) {
	        var lastEditor = Object.values(pages)[0].revisions[0].user;
	        var otherIndex = pages[ p ].revisions.findIndex(i => i.user != lastEditor) - 1;
	        var lastEditByOther = pages[ p ].revisions[otherIndex + 1] ? pages[ p ].revisions[otherIndex + 1].revid : undefined;
	        var lastEdits = pages[ p ].revisions.slice(0, otherIndex + 1);
	        var numberOfEdits = lastEdits.length;
	        var lastEdit = Object.values(pages)[0].revisions[0].revid;
	        
	        return [lastEditor, lastEditByOther, lastEdit, numberOfEdits];
	    }
	}
	catch {
		alert("Luna: It appears that only one user has edited this page. Rollback cannot be applied.");
		return;
	}
}
async function doUndo(reason, from, to, page = mw.config.get("wgPageName")) {
	var anyOtherEdits = (await getNonRolledBackEdit(page))[1];
	var lastEdit = await getNonRolledBackEdit(page);
	if (typeof anyOtherEdits != "undefined") {
		var params = {
	        action: 'edit',
	        title: page,
	        undo: from,
	        undoafter: to,
	        summary: `Reverting ${lastEdit[3]} edit${lastEdit[3] == 1 ? "" : "s"} by [[Special:Contributions/${lastEdit[0]}|${lastEdit[0]}]]${reason ? ": " + reason : ""}`,
	        tags: "Luna",
	        format: 'json'
	    },
	    api = new mw.Api();
	    const data = await api.postWithToken( "csrf", params );
	    console.log(data);
	}
}
async function doRollback(reason, page = mw.config.get("wgPageName")) {
	var lastEdit = await getNonRolledBackEdit(page);
	if(myRights.indexOf("rollback") < 0) {
		try {
			await doUndo(reason, lastEdit[2], lastEdit[1], page);
			mw.notify("Luna: Rollback complete.");
		}
		catch (e) {
			mw.notify("Luna: Rollback failed. See the console for details.");
			console.error(e);
		}
	}
	else { 
		try {
			params = {
		        action: 'rollback',
		        title: page,
		    	user: lastEdit[0],
		        summary: `Rollback ${lastEdit[3]} edit${lastEdit[3] == 1 ? "" : "s"} by [[Special:Contributions/${lastEdit[0]}|${lastEdit[0]}]]${reason ? ": " + reason : ""}`,
		        tags: "Luna",
		        format: 'json'
		    },
		    api = new mw.Api();
		    const data = await api.postWithToken( "rollback", params );
			mw.notify("Luna: Rollback complete.");
			console.log(data);
		}
		catch {
			try {
				await doUndo(reason, lastEdit[2], lastEdit[1], page);
				mw.notify("Luna: Rollback complete.");
			}
			catch (e) {
				mw.notify("Luna: Rollback failed. See the console for details.");
				console.error(e);
			}
		}
	}
}
async function doRestore(reason, revid, page = mw.config.get("wgPageName")) {
	var cur = (await getNonRolledBackEdit(page))[2];
	var params, api;
	params = {
        action: 'edit',
        title: page,
        undo: cur,
        undoafter: revid,
        summary: `Restoring revision ${revid}${reason ? ": " + reason : ""}`,
        tags: "Luna",
        format: 'json'
    },
    api = new mw.Api();
    try {
	    const data = await api.postWithToken( "csrf", params );
	    mw.notify("Luna: Reversion complete.");
	    console.log(data);
    }
    catch (e) {
    	mw.notify("Luna: Reversion failed. See the console for details.");
		console.error(e);
    }
}
var spanTag = function( myClass, content ) {
    var span = document.createElement( 'span' );
    $(span).addClass(myClass);
    span.appendChild( document.createTextNode( content ) );
    return span;
};

function addRollbackLinks(selector) {
	var list = $("#bodyContent").find(selector);
    var revNode = document.createElement('strong');
    var revLink = document.createElement('a');
    revLink.style.textDecoration = "none";
    revLink.appendChild( spanTag( "luna-rollback-link", 'rollback' ) );
    revNode.appendChild(revLink);

    var revVandNode = document.createElement('strong');
    var revVandLink = document.createElement('a');
    revVandLink.style.textDecoration = "none";
    revVandLink.appendChild( spanTag( "luna-vand-link", 'vandalism' ) );
    revVandNode.appendChild(revVandLink);

    list.each(function(key, current) {
        var href = $(current).find('.mw-changeslist-diff').attr('href') ? $(current).find('.mw-changeslist-diff').attr('href') : `${mw.config.get("wgScript")}?title=${mw.config.get("wgPageName")}`;
        current.appendChild(document.createTextNode(' '));
        var tmpNode = revNode.cloneNode(true);
        var pageTitle = new URLSearchParams(new URL("http:" + mw.config.get("wgServer") + href).search).get("title");
        $(tmpNode).click(() => {
        	var rzn = prompt("Why would you like to revert this edit?");
        	if (rzn != null) {
        		doRollback(prompt("Why would you like to revert this edit?"), pageTitle);
        	}
        });
        current.appendChild(tmpNode);
        current.appendChild(document.createTextNode(' '));
        tmpNode = revVandNode.cloneNode(true);
        $(tmpNode).click(() => doRollback("Vandalism", pageTitle));
        current.appendChild(tmpNode);
    });
}
function addRestoreLinks(selector) {
	var list = $("#bodyContent").find(selector);
    var resNode = document.createElement('strong');
    var resLink = document.createElement('a');
    resLink.style.textDecoration = "none";
    resLink.appendChild( spanTag( "luna-restore-link", 'restore' ) );
    resNode.appendChild(resLink);

    list.each(function(key, current) {
        var href = $(current).find('.mw-changeslist-diff').attr('href') ? $(current).find('.mw-changeslist-diff').attr('href') : `${mw.config.get("wgScript")}?title=${mw.config.get("wgPageName")}`;
        var oldid = !!$(current).data('mw-revid') ? $(current).data('mw-revid') : $(current).find('[data-mw-revid]').data('mw-revid');
        current.appendChild(document.createTextNode(' '));
        var tmpNode = resNode.cloneNode(true);
        var pageTitle = new URLSearchParams(new URL("http:" + mw.config.get("wgServer") + href).search).get("title");
        $(tmpNode).click(() => {
        	var rzn = prompt("Why would you like to restore this version?");
        	if (rzn != null) {
        		doRestore(rzn, oldid, pageTitle);
        	}
        });
        current.appendChild(tmpNode);
    });
}
function addAppropriateLinks() {
	switch (mw.config.get('wgCanonicalSpecialPageName')) {
		case "Contributions":
			addRollbackLinks("ul li:has(span.mw-uctop)");
			addRestoreLinks("ul.mw-contributions-list li:not(:has(span.mw-uctop))");
			break;
		case "Recentchanges":
			addRollbackLinks(".mw-changeslist .mw-changeslist-last.mw-changeslist-src-mw-edit");
			addRestoreLinks(".mw-changeslist :not(.mw-changeslist-last).mw-changeslist-src-mw-edit");
			break;
		case "Recentchangeslinked":
			addRollbackLinks(".mw-changeslist .mw-changeslist-last.mw-changeslist-src-mw-edit");
			addRestoreLinks(".mw-changeslist :not(.mw-changeslist-last).mw-changeslist-src-mw-edit");
			break;
		case "Watchlist":
			addRollbackLinks(".mw-changeslist .mw-changeslist-last.mw-changeslist-src-mw-edit");
			addRestoreLinks(".mw-changeslist :not(.mw-changeslist-last).mw-changeslist-src-mw-edit");
			break;
		default:
			if (mw.config.get("wgIsProbablyEditable")) {
				if (mw.config.get("wgAction") == "history") {
					addRollbackLinks("#pagehistory li:first");
					addRestoreLinks("#pagehistory li:not(:first)");
				}
				else if (mw.config.get('wgDiffOldId') && (mw.config.get('wgDiffOldId') !== mw.config.get('wgDiffNewId'))) {
					addRollbackLinks("#mw-diff-ntitle2");
					addRestoreLinks("#mw-diff-otitle2");
				}
				else if ($("#mw-revision-info")) {
					addRestoreLinks("#mw-revision-info");
				}
			}
	}
}

if (mw.config.get("wgCanonicalSpecialPageName") == "Recentchanges" || mw.config.get("wgCanonicalSpecialPageName") == "Relatedchanges" || mw.config.get("wgCanonicalSpecialPageName") == "Watchlist") {
	mw.hook('wikipage.content').add((item) => {
		if (item.is('div')) {
			addAppropriateLinks();
		}
	});
}
else if (mw.config.get('wgDiffNewId') || mw.config.get('wgDiffOldId')) {
	mw.hook('wikipage.diff').add(() => {
		addAppropriateLinks();
	});
}
else {
	addAppropriateLinks();
}
if (mw.config.get('wgIsProbablyEditable') && mw.config.get('wgArticleId') > 0) {
	$(mw.util.addPortletLink('luna-actions', '#', 'Quick rollback', 'luna-qrb', 'Quickly revert all edits made by the last editor')).click(() => {
		doRollback(prompt("Why would you like to revert this edit?"), mw.config.get("wgPageName"));
	});
}