Jump to content

User:SD0001/T-Watch.js

From Wikipedia, the free encyclopedia
This is an old revision of this page, as edited by SD0001 (talk | contribs) at 17:48, 4 September 2019 (first cut). The present address (URL) is a permanent link to this revision, which may differ significantly from the current revision.
(diff) ← Previous revision | Latest revision (diff) | Newer revision → (diff)
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.
/**
 * Script for enabling temporary watchlisting of pages
 *
 */

// <nowiki>

var api;

$.when(mw.loader.using(['mediawiki.user', 'mediawiki.api', 'mediawiki.util']), $.ready).then(function() {

	api = new mw.Api();

	// Menu interface
	if (mw.config.get('wgNamespaceNumber') >= 0) {
		$(mw.util.addPortletLink('p-cactions', '#', 'Watch – 1 week', 'twl-week', "Watchlist this page for a week's duration")).click(function() {
			watchPage(mw.config.get('wgPageName'), 1000*60*60*24*7);
		});
		$(mw.util.addPortletLink('p-cactions', '#', 'Watch – 1 month', 'twl-month', "Watchlist this page for a month's duration")).click(function() {
			watchPage(mw.config.get('wgPageName'), 1000*60*60*24*30);
		});
	}

	// Edit page interface
	if (mw.config.get('wgAction') === 'edit') {
		$('#wpWatchthisWidget').parent().next().after(
			$('<select>').attr('id', 'watchduration').append(
				$('<option>').text('1 week').val('604800000'),
				$('<option>').text('2 weeks').val('1209600000'),
				$('<option>').text('1 month').val('2592000000'),
				$('<option>').text('2 months').val('5184000000'),
				$('<option>').text('Indefinitely').val('inf').prop('selected', true)
			).change(function() {
				$('#wpWatchthis')[0].checked = true;
			})
		);
		if (window.tempWatchlistDurations) {
			$.each(window.tempWatchlistDurations, function(label, value) {
				$('#watchduration').append(
					$('<option>').text(label).val(value)
				);
			});
		}

		// record in pages object that the page is to be unwatched for said duration
		// watching of the page is done by mediawiki
		$('#wpSave').click(function() {
			if ($('#wpWatchthis')[0].checked) {
				var dur = $('#watchduration').val();
				if (dur === 'inf') {
					return;
				}
				recordAsWatching(mw.config.get('wgPageName'), parseInt(dur));
			}
		});
	}

	// Integration with user scripts that edit pages
	hookEventListener();

	// Special page to see list of temporarily watched pages
	if (mw.config.get('wgPageName') === 'Special:TemporarilyWatchedPages' ||
		mw.config.get('wgPageName') === 'Special:TempWatched') {
			buildSpecialPage();
	}

	// Unwatch expired pages every hour
	var nextCheckTime = mw.user.options.get('userjs-twl-nextcheck');
	if (!nextCheckTime) {  // for first-time users
		api.saveOption('userjs-twl-nextcheck', (new Date().getTime() + 1000*60*60).toString());
	}
	else if (new Date().getTime() > parseInt(nextCheckTime)) {
		removeExpiredPages();
	}

});

/**
 * @param {string} page
 */
function watchPage(page, duration) {
	api.watch(page).done(function() {
		recordAsWatching(page, duration);
		var d = new Date(new Date().getTime() + duration);
		mw.notify('"' + page.replace(/_/g, ' ') + '" and its ' + (mw.Title.newFromText(page).isTalkPage() ? 'associated subject' : 'talk') + ' page have been added to your watchlist till ' + getString(d) + '.');
	});
}

/**
 * @param {string} page
 * @param {number} duration
 */
function recordAsWatching(page, duration) {
	page = new mw.Title(page).getSubjectPage().getPrefixedText(); // normalize talk page to subject page
	var opt = JSON.parse(mw.user.options.get('userjs-twl-pages'));
	if (!opt) opt = {};
	opt[page] = new Date().getTime() + duration; // expiry timestamp
	api.saveOption('userjs-twl-pages', JSON.stringify(opt));
}

function removeExpiredPages() {
	var opt = JSON.parse(mw.user.options.get('userjs-twl-pages'));
	if (!opt) return;
	var pagesToUnwatch = [];
	$.each(opt, function(page, expiry) {
		if (new Date().getTime() > expiry) {
			pagesToUnwatch.push(page);
		}
	});
	api.unwatch(pagesToUnwatch).done(function() {
		// check again for expired pages after an hour
		api.saveOption('userjs-twl-nextcheck', (new Date().getTime() + 1000*60*60).toString());

		// update pages object
		pagesToUnwatch.forEach(function(page) {
			delete opt[page];
		});
		api.saveOption('userjs-twl-pages', JSON.stringify(opt));
	});
}

/**
 *
 * Re-think this
 *
 */
function hookEventListener() {
	mw.hook('record_watch').add(function(arg) {
		arg.page = arg.page || mw.config.get('wgPageName');
		arg.setting = arg.setting || 'preferences';
		arg.duration = arg.duration || window.tempWatchlistDefaultDuration || 'inf';
		arg.type;

		if (arg.duration === 'inf') return;

		if (arg.setting === 'watch') {
			recordAsWatching(arg.page, arg.duration);
		} else if (arg.setting === 'preferences') {
			var pref;
			switch (arg.type) {
				case 'create': pref = 'watchcreations'; break;
				case 'move': pref = 'watchmoves'; break;
				case 'delete': pref = 'watchdeletions'; break;
				case 'upload': pref = 'watchuploads'; break;
				case 'rollback': pref = 'watchrollbacks'; break;
				default: pref = 'watchdefault';
			}
			if (mw.user.options.get(pref) == 1) { // dunno whether its string or number
				recordAsWatching(arg.page, arg.duration);
			}
		}
	});
}

function buildSpecialPage() {
	$('#firstHeading').text('Temporarily watched pages');
	document.title = 'Temporarily watched pages';
	$('#mw-content-text').empty();

	var opt = JSON.parse(mw.user.options.get('userjs-twl-pages'));

	var $ul = $('<ul>');
	$.each(opt, function(page, expiry) {
		$ul.append(
			$('<li>').html('<a href=//en.wikipedia.org/wiki/' + page.replace(/ /g, '_') + ' title=' + page + '>'+ page + '</a>: ' + getString(new Date(expiry)))
		);
	});
	$('#mw-content-text').append(
		$('<p>').text('The following pages are set to be automatically unwatched after the given time in UTC:'),
		$('<p>').html('This list may include any pages that you may have subsequently unwatched manually, <a id="purgeunwatchedpages">click here to purge such pages</a>.'),
		$ul
	);
	$('#purgeunwatchedpages').click(function() {

		$ul.replaceWith('Purging...');
		var arrayOfPages = Object.keys(opt); // ASSUME < 50 for now
		if (arrayOfPages.length > 50) {
			alert('You have more than 50 pages here: purge feature coming soon');
			return;
		}
		api.get({
			"action": "query",
			"format": "json",
			"prop": "info",
			"titles": arrayOfPages,
			"inprop": "watched"
		}).then(function(json) {
			Object.values(json.query.pages).forEach(function(info) {
				if (info.watched === undefined) {
					delete opt[info.title];
				}
			});
			opt = JSON.stringify(opt);
			api.saveOption('userjs-twl-pages', opt).then(function() {
				mw.user.options.set('userjs-twl-pages', opt);
				buildSpecialPage();
			});
		});


		// var arrayOfArrays = arrayChunk(arrayOfPages, 50);
		// arrayOfArrays.forEach(function(array) {
		// 	api.get({
		// 		"action": "query",
		// 		"format": "json",
		// 		"prop": "info",
		// 		"titles": array,
		// 		"inprop": "watched"
		// 	}).then(function(json) {
		// 		Object.values(json.query.pages).forEach(function(info) {
		// 			if (info.watched === undefined) {
		// 				delete opt[info.title.replace(/ /g, '_')];
		// 			}
		// 		});
		// 	});
		// });

	});
}

// HELPER FUNCTIONS:

/**
 * @param {Date} date
 */
function getString(date) {
	return date.getUTCHours() + ':' + date.getUTCMinutes() + ', ' + date.getUTCDate() + ' ' + mw.config.get('wgMonthNames')[ date.getUTCMonth() + 1 ] + ' ' + date.getUTCFullYear();
}

function arrayChunk(arr, size) {
	var result = [];
	var current;
	for (var i = 0; i < arr.length; ++i) {
		if (i % size === 0) { // when 'i' is 0, this is always true, so we start by creating one.
			current = [];
			result.push(current);
		}
		current.push(arr[i]);
	}
	return result;
}

// </nowiki>