Jump to content

User:DaxServer/DiscussionCloser.js

From Wikipedia, the free encyclopedia
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.
//<nowiki>
//Temporary fork from [[User:DannyS712/DiscussionCloser.js]
//Credits to Equazcion, Evad37, and Abelmoschus Esculentus
//Date: 6 Mar 2019
//Forked from [[User:Abelmoschus Esculentus/DiscussionCloser.js]
//Maintained by DaxServer
function dc_radio(i) {
	$('#DC-e').val("");
	if (i == 1) {
		$('#DC-e').prop('disabled', false);
	}
	if (i == 2) {
		$('#DC-e').prop('disabled', true);
	}
}

$(function() {
	var api, uri;
	const DiscussionCloser_config = {
		name: '[[User:DaxServer/DiscussionCloser|DiscussionCloser]]',
		version: '1.7.3-6',
		debug: false
	};
	const DiscussionCloser_ending = ' (' + DiscussionCloser_config.name + ' v.' + DiscussionCloser_config.version + ')';

	/* HELPER FUNCTIONS */
	function dc_make_bottom(template){
		var bottom;
		switch (template) {
			case "atop":
			case "atopr":
			case "atopy":
			case "atopg":
			case "subst:RMT":
				bottom = "abot";
				break;
			case "hat":
				bottom = "hab";
				break;
			default:
				bottom = "closed rfc bottom";
				break;
		}
		bottom = "{{" + bottom + "}}";
		return bottom;
	}

	function alreadyClosed ( content ){
		content = content.toLowerCase();
		if (content.includes('{{atop') ||
			content.includes('{{hat') ||
			content.includes('{{abot') ||
			content.includes('{{archive') ||
			content.includes('{{rfctop') ||
			content.includes('{{rfc bottom') ||
			content.includes('{{archive bottom') ||
			content.includes('{{hidden archive bottom') ||
			content.includes('<!-- template:rm top -->')
		) return true;
		return false;
	}

	function generate_template_text(template, status, comment) {
		var templateText = '\n{{'+template;
		if (status !== '') templateText += '\n| status = '+status+'\n';
		if (comment !== '') templateText += '\n| result = '+comment+'\n'
		templateText += '}}';
		return templateText;
	}

	function getWikiText(template, status, comment, section, callback) {
		api.get({
			action:"query",
			titles: mw.config.get('wgPageName'),
			rvsection: section,
			prop: "revisions|info",
			rvslots: "main",
			rvprop: "content",
			formatversion: 2,
		}).done(function(response) {
			const content = response.query.pages[0].revisions[0].slots.main.content;
			const discussiontext = content.substring(content.indexOf('\n'));
			const title = content.substring(0, content.indexOf('\n'));
			const sectiontitle = title.replace(/=/g, '').trim();
			const templateText = generate_template_text(template, status, comment);
			const bottom = dc_make_bottom(template);
			var wikitext = title + templateText + discussiontext + '\n' + bottom;
			if (template === "closed rfc top") {
				wikitext = wikitext.replace(/(\r|\n)?{{rfc[^\}]*}}/g, '')
					.replace(/(\r|\n)?<!--\s\[\[User:DoNotArchiveUntil\]\][^->]*-->{{[^C]+ClueBot\sIII\/DoNotArchiveUntil\|\d*}}/g, '');
			} else if (template === "subst:RMT") {
				wikitext = wikitext.replace(/{{requested move\/dated\|[^}]*?}}\n?/i, '');
			}

			callback(wikitext, sectiontitle, alreadyClosed(content));
		});
	}

	/* MAIN FUNCTIONs */

	function dc_init(){
		if ((($('#ca-addsection').length > 0) ||
				(mw.config.get('wgPageName') == 'Wikipedia:Administrators\'_noticeboard/Edit_warring') ||
				(mw.config.get('wgPageName') == 'Wikipedia:In_the_news/Candidates')) &&
			(mw.config.get('wgAction') == 'view')) {
			dc_run();
		}
	}

	function dc_run() {
		$('div:not(.mw-archivedtalk) > div.mw-heading').each(function(index, value) {
			const editSectionUrl = $(this).find('.mw-editsection a:first').attr('href');
			const sectionRaw = /&section=(\d+)/.exec(editSectionUrl);
			if (sectionRaw === null || typeof sectionRaw[1] === 'undefined') {
				return;
			}
			const sectionHeadingRaw = /mw-heading mw-heading(\d)/.exec($(this).attr('class'));
			if (sectionHeadingRaw === null || typeof sectionHeadingRaw[1] === 'undefined' || ![2, 3, 4].includes(parseInt(sectionHeadingRaw[1]))) {
				return;
			}
			const section = parseInt(sectionRaw[1]);
			if (isNaN(section)) {
				return;
			}
			const uriFragment = $(this).find('h'+section).attr('id');
			$(this).append('<div class="DC-close-widget"><span class="mw-editsection-divider">|</span><a class="DC-closeLink">Close</a></div>');
			$(this).find('a.DC-closeLink').click(function(){
				$('body').prepend('<div id="DC-modal">'+
					'<div id="DC-interface">'+
					'<h4 id="DC-interface-header"></h4>'+
					'<hr>'+
					'<div id="DC-interface-content"></div>'+
					'<hr>'+
					'<div id="DC-interface-footer"></div>'+
					'</div>'+
					'</div>');
				$("#DC-interface-header, #DC-interface-content, #DC-interface-footer").empty();
				$("#DC-interface-header").text("Discussion Closer");
				$("#DC-interface-content").append(
					$('<div class="DC-bottom">').append(
						$('<label>').attr({'id':'DC-label'}).text('Options: '),
						$('<input>').attr({'type':'radio', 'name':'DC-radio','id':'DC-radio1','value':'atop','checked':'true','onchange':'dc_radio(1)'}),
						$('<label>').text('Generic (blue) '),
						$('<input>').attr({'type':'radio', 'name':'DC-radio','id':'DC-radio2','value':'atopg','onchange':'dc_radio(1)'}),
						$('<label>').text('Generic (green) '),
						$('<input>').attr({'type':'radio', 'name':'DC-radio','id':'DC-radio3','value':'atopy','onchange':'dc_radio(1)'}),
						$('<label>').text('Generic (yellow) '),
						$('<input>').attr({'type':'radio', 'name':'DC-radio','id':'DC-radio4','value':'atopr','onchange':'dc_radio(1)'}),
						$('<label>').text('Generic (red) '),
						$('<input>').attr({'type':'radio', 'name':'DC-radio','id':'DC-radio5','value':'closed rfc top','onchange':'dc_radio(2)'}),
						$('<label>').text('RfC '),
						$('<input>').attr({'type':'radio', 'name':'DC-radio','id':'DC-radio6','value':'hat','onchange':'dc_radio(2)'}),
						$('<label>').text('Hidden archive '),
						$('<input>').attr({'type':'radio', 'name':'DC-radio','id':'DC-radio7','value':'subst:RMT','onchange':'dc_radio(2)'}),
						$('<label>').text('Requested move ')
					),
					$('<div class="DC-bottom">').append(
						$('<label>').text('Status (optional): '),
						$('<input>').attr({'type':'text','name':'DC-e','id':'DC-e'})
					),
					$('<div class="DC-bottom">').append(
						$('<label>').text('Closing comment:'),
						$('<span>').css({'float':'right','color':'indianred'}).text('Signature is automatically added if comment is added'),
						$('<textarea>').css({'resize':'none'}).attr({'name':'DC-com','id':'DC-com','rows':'17','cols':'30'})
					),
					$('<div class="DC-bottom">').append(
						$('<label>').text('Edit summary ("Closing discussion" if left blank): '),
						$('<input>').attr({'type':'text','name':'DC-es','id':'DC-es'})
					),
					$('<div class="DC-bottom">').attr('id','DC-prevt'),
					$('<div class="DC-bottom">').attr('id','DC-prevdiv'),
					$('<button>').attr('id', 'DC-closeprev').text('Close preview').hide()
				);
				$("#DC-interface-footer").append(
					$('<button>').attr({'name':'DC-done', 'id':'DC-done'}).text('Close discussion'),
					$('<button>').attr({'name':'DC-prev', 'id':'DC-prev'}).text('Preview'),
					$('<button>').attr('id', 'DC-cancel').text('Cancel'),
					$('<label>').attr('id','DC-loading').text(' Loading preview...').hide()
				);
				document.getElementById("DC-modal").addEventListener( "keydown", function ( key ) {
					if( key.ctrlKey && ( key.keyCode == 10 || key.keyCode == 13 ) ) {
						document.getElementById("DC-done").click();
					}
					else if ( key.keyCode == 27 ){
						document.getElementById("DC-cancel").click();
					}
				});
				$('#DC-cancel').click(function() {
					$('#DC-modal').remove();
				});
				$('#DC-prev').click(function() {
					$('#DC-loading').show();
					const template = $("input[name=DC-radio]:checked").val();
					const status = $('#DC-e').val();
					var comment = $('#DC-com').val().trim();
					if (comment.length > 0) {
						comment += ' ~~~~';
					}
					getWikiText(template, status, comment, section, function(wikitext) {
						api.post({
							format:'json',
							action:'parse',
							pst:1,
							text:wikitext,
							title:mw.config.get('wgPageName'),
							prop:'text'
						}).done(function(r) {
							if(!r.parse || !r.parse.text || !r.parse.text['*']){
								alert('Error previewing.');
							}
							$('#DC-loading').hide();
							$('#DC-prevt').html('<hr>Preview:<br>');
							$('#DC-prevdiv').html(r.parse.text['*']+'<br />').css({'display':'block','background-color':'white'});
							$('#DC-closeprev').show();
							$('#DC-closeprev').click(function() {
								$('#DC-prevt').empty();
								$('#DC-prevdiv').empty().css({'display':'','background-color':'','border-color':'',"border-width":"", "border-style":""});
								$('#DC-closeprev').hide();
							});
						});
					});
				});
				$('#DC-done').click(function() {
					var editsummary = $('#DC-es').val().trim();
					if (editsummary === "") {
						editsummary = "Closing discussion";
					}
					const template = $("input[name=DC-radio]:checked").val();
					const status = $('#DC-e').val();
					var comment = $('#DC-com').val().trim();
					if (comment.length > 0) {
						comment += ' ~~~~';
					}
					$('#DC-done').remove();
					$('#DC-prev').remove();
					$('#DC-cancel').remove();
					$('#DC-interface-content').empty();
					$("#DC-interface-content").text('Retrieving information...');
					$("#DC-interface-content").append('<b>Done!</b><br>Closing discussion...');

					getWikiText(template, status, comment, section, function(wikitext, sectiontitle, alreadyClosed) {
						const sectiontitle2 = sectiontitle.replace(/\s/g, '_');
						const afterCloseCallback = function(result, sectiontitle) {
							$("#DC-interface-content").append(result);
							$('#DC-interface-footer').append(
								$('<button>').attr('id', 'DC-close').text('Done')
							);
							$('#DC-close').click(function() {
								$('#DC-modal').remove();
								uriReload = uri.clone();
								uriReload.fragment = sectiontitle;
								window.location.href = uriReload.toString();
								window.location.reload();
							});
						};

						var willClose = true;
						if (alreadyClosed) {
							willClose = confirm('The discussion may have already been closed. Continue?');
						}
						if (!willClose) {
							afterCloseCallback('<b>Aborted by user</b><br><b>Finished!</b>', sectiontitle2);
							return;
						}

						api.post({
							action:"edit",
							section: section,
							title: mw.config.get('wgPageName'),
							text: wikitext,
							summary: '/* ' + sectiontitle + ' */ ' + editsummary + DiscussionCloser_ending,
							token: mw.user.tokens.get("csrfToken")
						}).done(function() {
							afterCloseCallback('<b>Done!</b><br><b>Finished!</b>', sectiontitle2);
						});
					});
				});
			});
		});
	}

	const styles = `
.DC-close-widget {
	display: inline-block;
	float: right;
	font-weight: normal;
	font-size: 0.8rem;

	.mw-editsection-divider {
		margin: 0 0.2rem;
		display: inline;
	}
}
`;

	mw.loader.using(['mediawiki.util', 'mediawiki.api', 'mediawiki.Title', 'mediawiki.Uri'], function() {
		api = new mw.Api();
		uri = new mw.Uri();
		mw.loader.load('//en.wikipedia.org/w/index.php?title=User:DannyS712/DiscussionCloser.css&action=raw&ctype=text/css', 'text/css'); // Import stylesheet
		mw.loader.addStyleTag(styles);
		dc_init();
	});
});
//</nowiki>