User:Theleekycauldron/DYK promoter.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>
var api = new mw.Api();
importScript('User:Theleekycauldron/Query pages.js');
let nompage, nomtext, preptexts;
let isEmpty = [];
let alphanumericals="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";

function mod(n, m) {
  return ((n % m) + m) % m;
}

$.when(
	mw.loader.using('ext.gadget.morebits'),
	$.ready
).then(async function() {
	console.log("ready!");
	await nomtext;
	if (mw.config.get('wgPageName').includes("Template:Did_you_know_nominations/")) {
		$(mw.util.addPortletLink(window.DYKH_portlet || 'p-cactions', '#', 'PSHAW', 'dyk-portlet', 'Close nomination')).click(promote);
	} else if (mw.config.get('wgPageName').includes("Template:Did_you_know/Preparation_area")) {
        importScript('User:Theleekycauldron/Prep tools.js');
		$(mw.util.addPortletLink(window.DYKH_portlet || 'p-cactions', '#', 'PSHAW', 'dyk-portlet', 'Prep set tools')).click(preptools_handler);
	}
	
});
function getHooks(wikiText) {
	var re = /('''ALT.+?)?(\.\.\..*?)(?:{{-\?}}|\?)/g;
	var hooks = wikiText.match(re);
	return hooks;
}

function biwikitext(t){
	while (t.includes("\'\'\'")){
		t = t.replace(/'''/,"<b>");
		t = t.replace(/'''/,"</b>");
	}
	while (t.includes("\'\'")){
		t = t.replace(/''/,"<i>");
		t = t.replace(/''/,"</i>");
	}
	return t;
}

promote = async function (e) {
	nompage = await get_pages(mw.config.get('wgPageName'),"user|content",null,"older");
	nomtext = nompage[0].revisions[0].slots.main.content;
	await nomtext;
	if (nomtext.includes("'''No further edits should be made to this page'''.")){
		alert("Hang on, you can't promote a closed nomination!");
		return;
	}
	for (revision of nompage[0].revisions){
		user = revision.user;
		if (user==mw.config.get('wgUserName')){
			alert("Looks like you've edited this nompage before. Make sure you're not an \"involved user\" before proceeding with a close; if you've nominated or edited the article, reviewed the nomination, or wrote the hook you're about to promote, you are most likely involved.");
			break;
		}
	}
	//nomtext = nomtext.replaceAll(/<s>.*?<\/s>/g,"");
	e.preventDefault();
	var Window = new Morebits.simpleWindow(900, 800);
	Window.setTitle( "The prep set's half-assed workbench (PSHAW)" );
	Window.addFooterLink( "DYK promoter's rules", "WP:DYKSG#Rules of thumb for preparing updates" );
	var form = new Morebits.quickForm();
	
	function reject(w){
		form.root.childs = [];
		console.log(w,(w)?("withdrawn"):("unsuccessful"))
		form.append({type: 'div', name: 'closing', label: 'Closing as '+((w)?("withdrawn"):("unsuccessful"))+"... "});
		nomtext = nomtext.split("\n");
		nomtext[0] = "{{subst:DYKsubpage";
		nomtext[2] = "|passed="+((w)?"withdrawn":"no");
		nomtext = nomtext.join("\n");
		var params = {
				action: 'edit',
				title: nompage[0].title,
				summary: "Closing as "+((w)?("withdrawn"):("unsuccessful"))+" ([[User:Theleekycauldron/DYK promoter|PSHAW]])",
				text: nomtext,
				format: 'json'
			}
		api.postWithToken( 'csrf', params ).done( function ( data ) {
			console.log( data );
			
			form.root.childs[0].data.label += 'done! :)';
			console.log(form.root.childs[0]);
			show();
			location.reload(true);
		} );
		
	}
	
	form.append({type: 'button', name: 'reject', label: 'mark as rejected', style: 'float: right', event: function r(){reject(false)}})
	form.append({type: 'button', name: 'withdrawn', label: 'mark as withdrawn', style: 'float: right', event: function w(){reject(true)}})
	
	// Grabbing hooks from nomination page
	
	function createHookObject(){
		var res = [];
		let u=0;
		let hooks = getHooks(nomtext);
		for (hook of hooks){
		    hook = hook.split("...");
			if (hook[0].includes("ALT")){
				let i;
				for (i=hook[0].indexOf("ALT")+3; alphanumericals.includes(hook[0].charAt(i)); i++){}
				hook[0] = hook[0].substring(hook[0].indexOf("ALT"),i);
			} else {
				hook[0] = "U"+u;
				u++;
			}
			res.push({ type: 'option', label: "<b>"+hook[0]+"</b>: ..."+biwikitext(hook[1].slice()), value: "* ..."+hook[1]});
		}
		return res;
	}
	hooks = createHookObject()
	
	//prep and queue selection
	
	form.append({type: 'select',name: 'area',label: 'Transport hook to:',list: [{ type: 'option', label: "Prep", value: "Template:Did you know/Preparation area "},{ type: 'option', label: "Queue (admins only)", value: "Template:Did you know/Queue/"}]});
	form.append({type: 'number', name: 'pqid', label: 'Prep/queue number:', min: 1, max: 7, step: 1})
	
	// render
	let result;
	function show(){
		result = form.render();
		Window.setContent(result);
		Window.display();
	}
	
	show();
	
	// load up the prep/queue
	
	let firstLoad = true;
	
	form.append({type: 'button',name: 'load', label: 'load prep/queue', event: load});
	
	async function load(){
		console.log("howdy :)");
		let pagename = result.area.value+result.pqid.value;
		let nextpreppage = await get_pages("Template:Did you know/Queue/NextPrep","user|content",null,"older");
		await nextpreppage;
		let nextpreptext = nextpreppage[0].revisions[0].slots.main.content;
		let previousprep = mod(nextpreptext[0]-2,7)+1;
		let dolastprepmessage = previousprep == result.pqid.value;
		console.log(form,previousprep,result.pqid.value,dolastprepmessage);
		form.root.childs[4].data.disabled = true; //disable button
		show(); //reload while button is being disabled
		if (firstLoad){ //these should only be done once
			if (!(nomtext.includes("[[File:Symbol voting keep.svg|16px]]") || nomtext.includes("[[File:Symbol confirmed.svg|16px]]")|| nomtext.match(/\|.*?status.*?=.*?y/g)!=undefined)){
				alert("Looks like you're trying to promote a nomination that hasn't been approved yet. Make sure the nomination's got a green or grey check mark!")
			}
			
			form.append({type: 'div', name: 'preppagename', label: "<b>[["+pagename+"]]</b>"}) //child 5
			form.append({name: 'hooksinprep', type: 'radio', label: 'Hooks:', list: []});
			form.append({type: 'div', name: 'hooktopromote', label: '<b>Hook to promote: </b>'})
			form.append({type: 'radio', name: 'nomhooks', list: []});
		} else { //update prepnum
			form.root.childs[5].data.label = "<b>[["+pagename+"]]</b>";
		}
		
		preppage = await get_pages(pagename,"content",null,"older");
		preptext = preppage[0].revisions[0].slots.main.content;
		prephooks = preptext.split("\n");
		prephooks = prephooks.slice(prephooks.indexOf("<!--Hooks-->")+2,prephooks.indexOf("<!--HooksEnd-->"));
		form.root.childs[6].data.list = []; //clear prep set's hook list
		for (var i=0; i<prephooks.length; i++){
			let matches = prephooks[i].match(/('{3}[^']*?\[\[.*?]].*?'{3})|(\[\[.*'{3}.*?'{3}]])/g);
			if (matches != null){
				form.root.childs[6].data.list.push({ type: 'option', label: i+": "+matches.join(", ").replaceAll("\'\'\'",""), value: i});
				isEmpty.push(false);
			} else {
				form.root.childs[6].data.list.push({ type: 'option', label: i+": barren", value: i});
				isEmpty.push(true);
			}
		}
        if (isEmpty.slice(1).every(v => v === false)){
		    form.root.childs[6].data.list.push({ type: 'option', label: "  create new slot", value: "[append]"});
        }
		form.root.childs[8].data.list = createHookObject();
		
		if (nomtext.includes("{{main page image/DYK") && firstLoad){
			imgfiles = nomtext.match(/\{\{main page image\/DYK.*?}}/g);
			console.log(imgfiles);
			optionsbox = [{type: 'option', label: 'nope', value: ""}];
			for (file of imgfiles){
				file = file.replaceAll(/= /g,"=");
				s = file.match(/\|image=.*?(?:\||})/g)[0];
				optionsbox.push({ type: 'option', label: s.slice(7,s.length-1), value: file})
			}
			console.log(optionsbox);
			form.append({type: 'div', name: 'label', label: '<b>File: </b>'});
			form.append({type: 'radio', name: 'images', list: optionsbox});
		}
		
		if (firstLoad){
			form.append({type: 'button', name: 'submit', label: 'submit!', event: function l(){evaluate(e, result)}});
		}
		
		if (dolastprepmessage){
            alert("This appears to be the bottom prep set – per WP:DYKSG#J14, try to leave the image slot, quirky slot, and at least two middle slots open for bumps and replacements!");
		}
		firstLoad = false;
		form.root.childs[4].data.disabled = false; //re-enable button
		show();
	}
	show();
	
	evaluate = function (e, result){
		
		let slotnum = result.hooksinprep.value;
		if (slotnum == ""){
			alert("Which slot is this hook going in?");
			return;
		}
		
		let hook = result.nomhooks.value;
		if (hook == ""){
			alert("You gotta pick a hook!");
			return;
		}
		
		let imgfile;
		if (result.images==undefined){
			imgfile="";
		} else {
			imgfile=result.images.value;
		}
		if (imgfile==""){ //scrub ''(pictured)'' from hook if no image
			hook = hook.replace(/[^']''\(.*?\)''/,"");
		}
		
		if (slotnum == 0 && imgfile == ""){
			alert("You can't put this in the lead slot unless you've got an image to go along with it!");
			return;
		}
		
		form.root.childs = [];
		
		form.append({type: 'div', name: 'Promoting hook', label: 'Promoting hook to [['+preppage[0].title+']]... '})
		form.append({type: 'div', name: 'Closing nomination', label: 'Closing [['+nompage[0].title+']]... '})
		
		show();
		preptext = preptext.split("\n");
		if (slotnum == "[append]"){
			preptext.splice(preptext.indexOf("<!--HooksEnd-->"),0,hook);
			preptext.splice(preptext.lastIndexOf("</div>"),0,getCredits(nomtext));
		} else {
			preptext[preptext.indexOf("<!--Hooks-->")+parseInt(slotnum)+2] = hook;
			isEmpty[slotnum] = "a";
			let j=1;
			for (i=0; i<isEmpty.length; i++){
				if (isEmpty[i]=="a") {break;}
				else if (isEmpty[i]) {j++;}
			}
			let p=0;
			while (j>0){
				p++;
				if (preptext[p].includes("* {{DYKmake|Example|Editor|subpage=}}")) {j--;}
				if (preptext[p]=="===Credit templates===") {alert("I couldn't find anywhere to put the credits? Make sure that there are enough empty credit slots for all the empty hook slots."); return null;}
			}
			preptext[p] = getCredits(nomtext);
			if (slotnum==7 && preptext.includes("* {{DYKnom|Example|Nominator}}")){
				preptext.splice(preptext.indexOf("* {{DYKnom|Example|Nominator}}"),1);
			}
		}
		if (imgfile != ""){
			preptext[preptext.indexOf("<!--Hooks-->")+1]=result.images.value;
		}
		preptext = preptext.join("\n");
		nomtext = nomtext.split("\n");
		nomtext[0] = "{{subst:DYKsubpage";
		nomtext[2] = "|passed=yes";
		nomtext.splice(nomtext.length-1,"To [[" + preppage[0].title + "]]");
		nomtext = nomtext.join("\n");
		console.log(preppage[0].title,nompage[0].title);
		var params = {
				action: 'edit',
				title: nompage[0].title,
				summary: "To [[" + preppage[0].title + "]] ([[User:Theleekycauldron/DYK promoter|PSHAW]])",
				text: nomtext,
				format: 'json'
			}
		api.postWithToken( 'csrf', params ).done( function ( data ) {
			form.root.childs[1].data.label += 'done! :)';
			console.log( data );
			show();
			location.reload(true);
		} );
		
		var params = {
				action: 'edit',
				title: preppage[0].title,
				summary: "Promoting [[" + nompage[0].title + "]] ([[User:Theleekycauldron/DYK promoter|PSHAW]])",
				text: preptext,
				format: 'json'
			}
		api.postWithToken( 'csrf', params ).done( function ( data ) {
			console.log( data );
			
			form.root.childs[0].data.label += 'done! :)';
			console.log(form.root.childs[0]);
			show();
		} );
	}
	
}

function getCredits(t){
	matches = t.match(/\* \{\{DYK(make|nom).*?\}\}/g);
	if (matches != null){
		return matches.join("\n");
	} else {
		return "* {{DYKmake|Example|Editor|subpage=}}"
	}
}

preptools_handler = async function(e){
    preptools(e);
}
// </nowiki>