User:SD0001/GAR-helper.js

This is an old revision of this page, as edited by SD0001 (talk | contribs) at 04:11, 8 February 2023 (fix bad promise handling). 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.
/**
 * Script to easily make Good Article Reassessment (GAR)
 * nominations.
 */

/* <nowiki> */
/* jshint maxerr: 999 */

var gar = {};
window.gar = gar;

$.when(
	mw.loader.using('ext.gadget.morebits'),
	$.ready
).then(function() {
	if ([0, 1].indexOf(mw.config.get('wgNamespaceNumber')) !== -1) {
		mw.util.addPortletLink('p-cactions', '#', 'GAR', 'gar-portlet', 'Nominate for GAR');
		$('#gar-portlet').click(gar.callback);
	}
});

gar.advert = ' ([[User:SD0001/GAR-helper|GAR-helper]])';

gar.callback = function garCallback(e) {
	if (e) e.preventDefault();

	var Window = new Morebits.simpleWindow(600, 450);
	Window.setTitle( "Nominate article for GAR" );
	Window.setScriptName('GAR-helper');
	Window.addFooterLink('GAR instructions', 'WP:GAR');

	var form = new Morebits.quickForm(gar.evaluate);
	
	mw.util.addCSS('.quickform * { font-size: 12px; }');

	var field = form.append({
		type: 'field',
		label: 'Details',
		name: 'details'
	});

	field.append({
		type: 'checkbox',
		list: [
			{
				label: 'Notify article creator',
				value: 'notify',
				name: 'notify',
				tooltip: "A notification template will be placed on the creator's talk page if this is checked.",
				checked: true
			}
		]
	});

	field.append({
		type: 'textarea',
		name: 'reason',
		label: 'Rationale:',
		style: 'height: 130px',
		tooltip: 'You can expand the rationale after the page has been saved as well.'
	});

	form.append({ type: 'submit', label: 'Submit' });

	var result = form.render();
	Window.setContent(result);
	Window.display();

};

gar.evaluate = function(e) {
	var form = e.target;
	gar.params = {
		notify: form.notify.checked,
		reason: form.reason.value
	};

	Morebits.simpleWindow.setButtonsEnabled(false);
	Morebits.status.init(form);

	var title_obj = new mw.Title.newFromText(Morebits.pageNameNorm);
	gar.title = title_obj.getSubjectPage().toText();
	gar.talktitle = title_obj.getTalkPage().toText();

	gar.usersToNotify = [];

	var tm = new Morebits.taskManager();
	tm.add(gar.tasks.getNumber, []);
	tm.add(gar.tasks.editTalkPage, [ gar.tasks.getNumber ]);
	tm.add(gar.tasks.createNomPage, [ gar.tasks.editTalkPage ]);
	tm.add(gar.tasks.getCreator, []);
	tm.add(gar.tasks.getLastGanNominator, []);
	tm.add(gar.tasks.getOtherEditors, []);
	tm.add(gar.tasks.notify, [ gar.tasks.getCreator, gar.tasks.getLastGanNominator, gar.tasks.getOtherEditors ]);

	tm.execute().then(function() {
		Morebits.status.actionCompleted('Nomination completed.');
		new Morebits.status('Notifications', ['The script has notified the the reviewer and page creator. ' +
		'Please consider manually notifying other involved editors and WikiProjects using ',
		Morebits.htmlNode('code', '{{subst:GARMessage|' + gar.title + '|GARpage=' + gar.num + '}} ~~~~') ], 'warn');
	});

};

gar.tasks = {

	getNumber: function() {
		var def = $.Deferred();
		var query = {
			action: 'query',
			format: 'json',
			formatversion: '2',
			list: 'allpages',
		};
		query.apnamespace = '4', // WP
		query.apprefix = 'Good article reassessment/' + gar.title + '/';
		var api = new Morebits.wiki.api('Getting numbering', query);
		api.post().then(function(apiobj) {
			var pages = apiobj.response.query.allpages;
			gar.num = pages.length + 1; // HACK
			apiobj.getStatusElement().info('Next number is ' + gar.num);
			def.resolve();
		}, def.reject);
		return def;
	},

	createNomPage: function() {
		var def = $.Deferred();
		var appendtext = '{{subst:GAR/header}}\n' + gar.params.reason;
		var pageobj = new Morebits.wiki.page(gar.garpage, 'Creating nomination page');
		pageobj.setAppendText(appendtext);
		pageobj.setCreateOption('createonly');
		pageobj.setWatchlist(true);
		pageobj.setEditSummary('Creating GAR nomination page' + gar.advert);
		pageobj.append(def.resolve, def.reject);
		return def;
	},

	editTalkPage: function() {
		var def = $.Deferred();
		gar.garpage = 'Wikipedia:Good article reassessment/' + gar.title + '/' + gar.num;
		var talkpage = new Morebits.wiki.page(gar.talktitle, 'Editing talk page');
		talkpage.load(function(talkpage) {
			var text = talkpage.getPageText();
			// prepend tag:
			text = '{{subst:GAR}}\n' + text;
			// append transclusion:
			text += '\n\n==GA Reassessment==\n' + 
				'{{' + gar.garpage + '}}';
			talkpage.setPageText(text);
			talkpage.setEditSummary('Nominating for good article reassessment' + gar.advert);
			talkpage.save(def.resolve, def.reject);
		}, def.reject);
		return def;
	},

	getCreator: function() {
		var def = $.Deferred();
		var page = new Morebits.wiki.page(gar.title, 'Fetching article creator');
		page.setLookupNonRedirectCreator(true);
		page.lookupCreation(function() {
			var author = page.getCreator();
			page.getStatusElement().info('Got ' + author);
			gar.usersToNotify.push(author);
			def.resolve();
		}, def.reject);
		return def;
	},
	
	getLastGanNominator: function () {
		return $.get({
			url: 'https://sdzerobot.toolforge.org/gans/credit/' + mw.util.wikiUrlencode(gar.title) + '?raw=1',
			timeout: 4000
		}).then(function (nom) {
			if (nom === '<Unknown>') {
				return;
			}
			gar.usersToNotify.push(nom);
		}).catch(function () {
			return $.Deferred().resolve(); // might be some server issue; don't fail
		});
	},

	getOtherEditors: function() {
		var query = {
			"action": "query",
			"format": "json",
			"formatversion": "2",
			"list": "allpages",
		};
		var api_gan = new Morebits.wiki.api('Getting previous GAN reviewers', $.extend(query, {
			"apprefix": gar.title + '/GA',
			"apnamespace": "1"
		})).post();
		var api_gar = new Morebits.wiki.api('Getting previous GAR nominators', $.extend(query, {
			"apprefix": 'Good article reassessment/' + gar.title + '/',
			"apnamespace": "4"
		})).post();

		return $.when(api_gar, api_gan).then(function(result_gan, result_gar) {
			var pages = result_gar.response.query.allpages
				.concat(result_gan.response.query.allpages);
			var defs = pages.map(function(page) {
				var def = $.Deferred();
				var p = new Morebits.wiki.page(page.title, 'Looking up creator of ' + page.title);
				p.lookupCreation(function() {
					gar.usersToNotify.push(p.getCreator());
					p.getStatusElement().info('found ' + p.getCreator());
					def.resolve();
				}, def.reject);
				return def;
			});
			return $.when.apply($, defs);
		});
	},

	notify: function() {
		var users = Morebits.array.uniq(gar.usersToNotify).filter(function (user) {
			return user !== mw.config.get('wgUserName');
		});
		var appendtext = '\n\n' +
			'{{subst:GARMessage|' + gar.title + '|GARpage=' + gar.num + '}} ~~~~';
		var editsummary = '[[' + gar.title + ']] listed for good article reassessment' + gar.advert;
		var defs = users.map(function(user, idx) {
			var def = $.Deferred();
			var usertalk = new Morebits.wiki.page('User talk:' + user, 'Notifying ' + user);
			usertalk.setAppendText(appendtext);
			usertalk.setEditSummary(editsummary);
			usertalk.append(def.resolve, def.reject);
			return def;
		});
		return $.when.apply($, defs);
	}

};
/* </nowiki> */