User:Rutilant/ajax-watchlist.js

This is an old revision of this page, as edited by Rutilant (talk | contribs) at 08:26, 30 January 2019. The present address (URL) is a permanent link to this revision, which may differ significantly from the current revision.
Note: After saving, you have to bypass your browser's cache to see the changes. Google Chrome, Firefox, Microsoft Edge and Safari: Hold down the ⇧ Shift key and click the Reload toolbar button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.
/*
Last update: January 30, 2019
Status: Experimental
*/
(function() {
	var watchlist_ajax={timer:null,status:false}, token=false, current_revs={}, last_message = {};
	if(test_currentPage()){
		var top_content="<input id='watchlist-ajax-timeOut' placeholder='Refresh rate in milliseconds'><button id='a-w-start'>Start</button><button id='a-w-stop'>Stop</button><br>Status: <span id='aj-w-status'>not running</span>";
		var main_content="<div id='auto-updating-watchlist'></div>";
		$("div#watchlist-ajax").html(top_content+main_content);
		$("#a-w-start").click(function(){start_update_w()});
		$("#a-w-stop").click(function(){stop_update_w()});
	}

	function start_update_w(){
		if(test_currentPage() && !watchlist_ajax.status){
			var timeout=$.isNumeric($("#watchlist-ajax-timeOut").val())?$("#watchlist-ajax-timeOut").val():5000;
			watchlist_ajax.status=true;
			$("#auto-updating-watchlist").html("");
			update_watchlistAjax(timeout);
			$("#aj-w-status").html(`running (${timeout} ms)`);
		}
	}
	function stop_update_w(){
		watchlist_ajax.status=false;
		clearTimeout(watchlist_ajax.timer);
		$("#aj-w-status").html('stopped');
	}

	function update_watchlistAjax(timeout){
		if(test_currentPage() && watchlist_ajax.status){
			var start_from="";
			$.ajax({
				type: 'GET',
				url: '/w/api.php?action=query&list=watchlist&wllimit=30&wlprop=ids|title|sizes|flags|user|comment&format=json&curtimestamp=true&wlallrev=true'+start_from,
				dataType: 'json',
				loop_timeout:timeout,
				success:function(returndata){
					var sitelink=''; /* for local testing */
					var watchlist_items="";
					var fetched_revs=[];
					returndata=returndata.query.watchlist;
					if(returndata.length>0){
						returndata.forEach(function(e){
							fetched_revs.push(e.pageid);
							let length=e.newlen-e.oldlen;
							let edit_summary=e.comment.substring(0, 400)||"<span style='color:#cecccc'>No edit summary.</span>" /* trim extremely long edit summary*/ ; 
							edit_summary=edit_summary.replace(/\[\[(.*?)\|(.*?)\]\]/g, "<a href=\"/wiki/$1\">$2</a>"); /* parse wikilinks */
							let difflink=sitelink+`/w/index.php?title=${e.title}&diff=${e.revid}`;
							let histlink=sitelink+`/w/index.php?title=${e.title}&action=history`;
							let rollback_msg = "ajax rollback";
							if (e.revid in last_message){
								rollback_msg = last_message[e.revid];
							}
							let rollback_btn = `[<a href='#' class='aj-rollback-btn' data-rollback-pageid="${e.pageid}"  data-rollback-revid="${e.revid}" data-rollback-user="${e.user}">${rollback_msg}</a>]`;
							if( e.pageid in current_revs ){
								if(current_revs[e.pageid] != e.revid){
									rollback_btn = "";
								}
							}

							let userlink=`
							<a href='${sitelink}/wiki/User:${e.user}'>${e.user}</a>
							(<a href='${sitelink}/wiki/User talk:${e.user}'>talk</a> | 
							<a href='${sitelink}/wiki/Special:Contributions/${e.user}'>contrib</a>)
							`;
							length=(length<0?'<span style=color:red>'+length+'</span>':'<span style=color:green>+'+length+'</span>');
							watchlist_items+=`
							<div style='margin-bottom:5px; padding:3px; font-family:Calibri; width: 100%; word-break:break-all'>
							(<a href="${difflink}">diff</a> | <a href="${histlink}">hist</a>)
							<a href="${sitelink}/wiki/${e.title}">${e.title}</a> (${e.type}) (${length}) &mdash; ${userlink} (<span style='font-style:italic'>${edit_summary}</span>) <span class="mw-rollback-link"  data-rollback-pageid="${e.pageid}" data-rollback-user="${e.user}" data-revid="${e.revid}">${rollback_btn}</span>
							</div>
							`;
						});
						$('.b-border-div').remove();
						$("#auto-updating-watchlist").html(watchlist_items+"<div style='border-bottom:2px solid skyblue;' class='b-border-div'></div>");
						$(".aj-rollback-btn").click(function(e) {custom_rollback(e, this)});
					}
					check_revisions(fetched_revs);
				},
				error:e=>console.log(e),
				complete:function(){
					var timeout=this.loop_timeout;
					watchlist_ajax.timer=setTimeout(function(){update_watchlistAjax(timeout)}, timeout);
				}
			});		
		}
	}

function check_revisions(pageid_array){
	pageid_array = [...new Set(pageid_array)];
	var pageids=pageid_array.join("|");
	$.get("/w/api.php?action=query&format=json&prop=revisions&pageids=" + pageids).then(response => {
		var pages = response.query.pages;
		pageid_array.forEach (pageid => {
			let revision = pages[pageid].revisions[0].revid;
			current_revs[pageid] = revision;
			$(`.mw-rollback-link[data-rollback-pageid=${pageid}]`).each(function(){
				if($(this)[0].dataset.revid != revision){
					$(this).html("");
				}else{
					let pageid = $(this)[0].dataset.rollbackPageid;
					let user = $(this)[0].dataset.rollbackUser;
					let rollback_msg = "ajax rollback";
					if (revision in last_message){
						rollback_msg = last_message[revision];
					}
					let rollback_btn = `[<a href='#' class='aj-rollback-btn' data-rollback-pageid="${pageid}"  data-rollback-revid="${revision}" data-rollback-user="${user}">${rollback_msg}</a>]`;
					$(this).html(rollback_btn);
				}
			});
		});
		$(".aj-rollback-btn").click(function(e) {custom_rollback(e, this)});
	});
}

	function test_currentPage(){
		if($("div#watchlist-ajax")){
			return true;
		}else{
			return false;
		}
	}
	
	function getToken(first_par, second_par){
		if(!token){
			$.ajax( "/w/api.php?action=query&meta=tokens&type=rollback&format=json" ).done(data=> {
				token=data.query.tokens.rollbacktoken; 
				custom_rollback(first_par, second_par, true);
			});
		}else{
			custom_rollback(first_par, second_par, true);
		}
	}
	
	function custom_rollback(e, clicked, withToken){
		e.preventDefault();
		if($(clicked).attr('href')===null){
			return;
		}
		if(!withToken){
			$(clicked).text("getting token");
			getToken(e, clicked);
			return;
		}
		var ID=$(clicked).attr("data-rollback-pageid");
		var user=$(clicked).attr("data-rollback-user");
		$(clicked).text('rollbacking...');
		last_message[$(clicked)[0].dataset.rollbackRevid] = $(clicked).text();
		$.ajax({
			type: 'POST',
			url: '/w/api.php',
			c_b: clicked,
			data: {action:"rollback", pageid:ID, user:user, token:token, format:'json'},
			success:function(e){
				if(!e.error){
					$(this.c_b).text('reverted');
				}else{
					$(this.c_b).text(e.error.code);
					console.log(e);
				}
				last_message[$(this.c_b)[0].dataset.rollbackRevid] = $(this.c_b).text();
			},
			error:function(e){
				$(this.c_b).text('rollback failed');
				last_message[$(this.c_b)[0].dataset.rollbackRevid] = $(this.c_b).text();
				console.log(e);
			}
		});
	}
	 mw.util.addPortletLink('p-cactions', '/wiki/User:RainFall/sandbox', 'Ajax watchlist');
})();