User:Evad37/FFDcloser/sandbox.js

// //global vars var FFDpath = "Wikipedia:Files for discussion/";

/* == Main function == */ $( function($) {

// Only run in FFD/subpages var thispage = mw.config.get( 'wgPageName' ); if ( !thispage.includes("Files_for_discussion") ) { return; }

$.getScript('https://en.wikipedia.org/w/index.php?title=User:Evad37/XFDcloserCommon.js&action=raw&ctype=text/javascript', function { // Make sure User:Evad37/XFDcloserCommon.js is loaded!

setSysopStatus;

/* ##### Sandbox usage only (remove when updating main script) ##### */ if ( mw.config.get("wgUserName") === "Evad37" ) { isSysop = true; console.log("isSysop: " + isSysop); FFDpath = "User:Evad37/sandbox/Files for discussion/"; } /* ##### End of sandbox usage only (remove when updating main script) ##### */

// Add links to actions $("h4 > span.mw-headline ").each(function( index ) {		$(".mw-headline-number", this).prependTo($(this).parent);	//fix for "Auto-number headings" preference		var file = $(":first-child", this).text;		if (!file) {                                   // section header wasn't a link			file = $(this).text;			$(this).wrapInner("  ");     // wrap with span so it can be styled later		}		var filee = mw.util.wikiUrlencode(file);        // "pretty"-encoded

//Check if already closed var discussion_element_class = $(this).parent.next.attr("class"); if ( discussion_element_class ) {          //only closed discussion have element with any class set $(this).parent.addClass("boilerplate ffd vfd xfd-closed"); //add classes to enable hiding of closed section headers } else { var sectionlink = $(this).next.find("a").not(".mw-editsection-visualeditor").attr('href'); var editsection = sectionlink.split("section=")[1]; if ( editsection.search("T")<0 ) {		//if true, we're on the subpage nom_page = thispage; } else {					//if false, section is transcluded from a subpage nom_page = sectionlink.split("title=")[1].split("&")[0]; editsection = editsection.substr(2); //remove "T-" from section number }

//Check for collapsed list, and pop out a non-visible copy if found var $collapsedlist = $(this).parent.next.next.find("dl"); if ($collapsedlist.length > 0) { $collapsedlistitems = $collapsedlist.children.clone; $collapsedlistitems.css( "display", "none" ) $(this).parent.next.append( $collapsedlistitems ).after( " &thinsp;... collapsed list detected (" + $collapsedlistitems.length + " files) " ); }

//Fix for linebreaks between list items var $siblinglists = $(this).parent.next.nextUntil("p, h4", "dl"); if ($siblinglists.length > 0) { $siblinglistsitems = $siblinglists.children.clone; $siblinglistsitems.css( "display", "none" ) $(this).parent.next.append( $siblinglistsitems); }

//Check if this is a multi-file dicussion var $fileslist = $(this).parent.next.children; // elements var $filesspans = $(":first-child", $fileslist);     //1st of each  var $files = $(":first-child", $filesspans).text; var files = $files.split("File:").slice(1); var closing_options; if ( files.length > 1) { //This is a multi-discussion files_e = files.map(function(fname) {					var f = "File:" + fname;					var fe = mw.util.wikiUrlencode(f).replace(/,/g,"__COMMA__"); //"pretty"-encode, then encode commas encoded as __COMMA__					return fe;				}); //console.log( files_e ); closing_options = "Closing options: " + " [qDel] " + " [Delete] " + " [qKeep] " + " [Other close] " + " [Relist] ";

} else if (!checkNS(file, 6)) { //sanity check filee = mw.util.wikiUrlencode($(this).html.replace(/<[^>]*>/g,""));   //this is actually the section header closing_options = "No files detected. [Close] ";

} else { //not a multi-discussion closing_options = "Closing options: " + " [qDel] " + " [<a style='cursor:pointer;' onclick=close_ffd('" + filee + "','" + nom_page + "','" + editsection + "','" + "delete" + "') title='Delete with comments'>Delete</a>] " + " [<a style='cursor:pointer;' onclick=multi_process_close_ffd('" + filee + "','" + nom_page + "'," + null + ",'" + editsection + "','" + "Keep" + "','" + "keep" + "') title='quickKeep'>qKeep</a>] " + " [<a style='cursor:pointer;' onclick=close_ffd('" + filee + "','" + nom_page + "','" + editsection + "','" + "other" + "') title='Other close with comments'>Other close</a>] " + " [<a style='cursor:pointer;' onclick=close_ffd('" + filee + "','" + nom_page + "','" + editsection + "','" + "relist" + "') title='Relist discussion'>Relist</a>] "; }			$(this).append("<span id=XFDClosing_" + filee + " style='font-size:85%;margin-left:13px;font-weight:normal;'>" + closing_options + " "); }	}); });

});

/* == Close FFD section (prompting for RESULT commment) == */

//Get comment function close_ffd(_filename, _pagetitle, _sectionnum, _action) { var prompt_text; if ( _action === "relist" ) { prompt_text = "Enter relist comment (optional)"; } else { prompt_text = "Enter result and comment"; }	var result_comment = prompt(prompt_text); if ( result_comment !== null ) { multi_process_close_ffd(_filename, _pagetitle, null, _sectionnum, result_comment, _action); } }

/* -- Close mulit-FFD section (prompting for RESULT commment) -- */ //Get comment function multi_close_ffd(_filearray, _pagetitle, _sectionheader, _sectionnum, _action) { var prompt_text; if ( _action === "relist" ) { prompt_text = "Enter relist comment (optional)"; } else { prompt_text = "Enter result and comment"; }	var result_comment = prompt(prompt_text); if ( result_comment !== null ) { multi_process_close_ffd(_filearray, _pagetitle, _sectionheader, _sectionnum, result_comment, _action); } }

/* == Multi-Process close == */ function multi_process_close_ffd(filename, pagetitle, sectionheader, sectionnum, resultcomment, action) {

//-Wikitext used for close var editsum_file_or_section, file_or_null, _anchor, ffd_close_top, ffd_close_bottom, ffd_close_editsum; if (sectionheader) { editsum_file_or_section = "\"" + sectionheader + "\""; file_or_null = null; _anchor = sectionheader; } else { editsum_file_or_section = "for " + filename + ""; file_or_null = filename; _anchor = filename; }

// Wikitext used for close if (isSysop) { sig = "" + ""; } else { sig = " (non-admin closure) " + ""; }	// Figure out if/where bold markup should be added var bolding_info = adjustCommentBolding(resultcomment); var bold1 = bolding_info[0]; var bold2 = bolding_info[1]; resultcomment = bolding_info[2];

//reset msg_array, deliver started message //msg_array = []; //console.log("_anchor = " + _anchor); deliverMsg( _anchor, "Started closing...", "working" );

if (action == "relist") { //get today's date var d = new Date; var mmm = getMonthName(d.getUTCMonth); todays_subpage = d.getUTCFullYear + " " + mmm + " " + d.getUTCDate; ffd_close_top = "{" + "{subst:ffd top|Relisted}" + "} on " + FFDpath + todays_subpage + "}" + "}"; ffd_close_bottom = "{" + "{subst:ffd bottom}" + "}"; ffd_close_editsum = "Closing discussion " + editsum_file_or_section + " as relisted on " + todays_subpage + " (using FFDcloser)"; } else { ffd_close_top = "{" + "{subst:ffd top|" + bold1 + resultcomment + bold2 + "}" + "} " + sig; ffd_close_bottom = "{" + "{subst:ffd bottom}" + "}"; ffd_close_editsum = "Closing discussion " + editsum_file_or_section + " as " + resultcomment + " (using FFDcloser)"; }

//-Get page content and remove {Closing} template if present new mw.Api.get( {			action: 'query',			titles: pagetitle,			prop: [ 'revisions', 'info' ],			rvprop: 'content',			indexpageids: 1,			rawcontinue: ''		} ).done( function( result, jqXHR ) {			var p_id = result.query.pageids;			var p_contents = result.query.pages[ p_id ].revisions[ 0 ][ '*' ];			var sections_array = p_contents.split("====");			var section_heading = sections_array[((sectionnum-1)*2-1)];			var section_contents = sections_array[((sectionnum-1)*2)].replace(//gi, "");			var updated_section = "====" + section_heading + "====" + "\n" + ffd_close_top + section_contents + ffd_close_bottom;

//Add relisted discusssions to current day's FFD page if (action == "relist") { var ffdlinks = section_contents.match(/^:<span class="plainlinks nourlexpansion lx"[^\n]*/gim).join("\n"); if ( ffdlinks ) { updated_section = "====" + section_heading + "====" + "\n" + ffd_close_top + "\n" + ffdlinks + ffd_close_bottom; } else { updated_section = "====" + section_heading + "====" + "\n" + ffd_close_top + ffd_close_bottom; }											deliverMsg( _anchor, "Adding discussion to today's FFD subpage...", "working" ); var old_disc = "====" + section_heading + "====" + "\n" + section_contents.replace(/^\n+/,""); relist_disc(file_or_null, old_disc, resultcomment, todays_subpage, sectionheader, _anchor); } else { updated_section = "====" + section_heading + "====" + "\n" + ffd_close_top + section_contents + ffd_close_bottom; }

//-Perform edit to close FFD discussion new mw.Api.postWithToken( 'edit', {					action: 'edit',					title: pagetitle,					section: sectionnum,					text: updated_section,					summary: ffd_close_editsum				} ).done( function( result, jqXHR ) {

//-If successful, mark as closed & move onto next actions (deletes, or update ffd's if relisted, or do old ffd housekeepings) var file_array, i, ii, last_one; if (sectionheader) { file_array = filename.split(","); // filename is a csv string (multiple items) for (i = 0; i < file_array.length; i++) { file_array[i] = decodeURIComponent(file_array[i]).replace(/__COMMA__/g,","); //unencode commas from __COMMA__ }					} else { file_array = [decodeURIComponent(filename)];         // filename is a string (single item) }					var file_array_length = file_array.length;

if ( action == "delete" ) { //Delete: markClosed(_anchor, resultcomment); deliverMsg( _anchor, "Deleting...", "working" ); for (ii = 0; ii < file_array_length; ii++) { if (ii == file_array_length-1) { last_one = true; } else { last_one = false; }							delete_file(file_array[ii], "["+"["+pagetitle+"#"+_anchor+"]"+"]", _anchor, last_one); }

} else if ( action == "relist" ) { //Relist: markClosed(_anchor, "Relisted at <a href=//en.wikipedia.org/wiki/" + FFDpath.replace(/\s/g,"_") + todays_subpage.replace(/\s/g,"_") + "#" + _anchor +">" + FFDpath + todays_subpage + "#" + _anchor + "</a>", true); deliverMsg( _anchor, "Adding discussion to today's FFD subpage...", "working" ); for (ii = 0; ii < file_array.length; ii++) { if (ii == file_array_length-1) { last_one = true; } else { last_one = false; }							update_file_ffd(file_array[ii], todays_subpage, _anchor, last_one); }

} else if ( action == "close_only" ) { //Take no further action markClosed(_anchor, resultcomment); return; } else { //Keep,other: markClosed(_anchor, resultcomment); deliverMsg( _anchor, "Updating file description pages...", "working" ); for (ii = 0; ii < file_array_length; ii++) { if (ii == file_array_length-1) { last_one = true; } else { last_one = false; }							make_old_ffd(file_array[ii], resultcomment, pagetitle, sectionheader, _anchor, last_one); }					}				} ).fail( function( code, result ) { var error_details = apifailed( code, result ); deliverMsg( _anchor, "Could not close discussion " + error_details, "error" ); } );

} ).fail( function( code, result ) { var error_details = apifailed( code, result ); deliverMsg( _anchor, "Could not read contents of page " + pagetitle + "; could not close discussion " + error_details, "error" ); } );	}

/* == Old ffd housekeeping == */ function make_old_ffd(filename, resultcomment, ffdpage, sectionheader, anchor, lastfile) {

var page_param, nomdate, filetalkpage, oldffd_wikitext;

if ( !checkNS(filename, 6) ) { deliverMsg( anchor, "\"" + filename + "\" is not in File: namespace, FFDcloser will not edit this page or its talk page", "error", lastfile, null, !lastfile); return; }

if (sectionheader) { page_param = "|page=" + sectionheader; } else { page_param = ""; }

//Add oldffdfull template to file talk nomdate = ffdpage.split("Files_for_discussion/")[1].replace(/_/gi," ");          //unencode spaces from _ filetalkpage = filename.replace("File", "File_talk"); oldffd_wikitext = "{" + "{oldffdfull|date=" + nomdate + "|result=" + resultcomment + "" + page_param + " }" + "}";

new mw.Api.postWithToken( 'edit', {		action: 'edit',		title: filetalkpage,		prependtext: oldffd_wikitext,		summary: "Old FFD – " + nomdate + ": " + resultcomment + " (using FFDcloser)"	} ).done( function( result, jqXHR ) {		deliverMsg( anchor, "Updated " + filetalkpage, "is_done", null, null, true );

//Get file description page, remove ffd template new mw.Api.get( {			action: 'query',			titles: filename,			prop: [ 'revisions', 'info' ],			rvprop: 'content',			indexpageids: 1,			rawcontinue: ''		} ).done( function( result, jqXHR ) { //			console.log(result);			var f_id = result.query.pageids;			var f_contents = result.query.pages[ f_id ].revisions[ 0 ][ '*' ];			var updated_filedesc = f_contents.replace(/]*}}/gi, "");

//Perform edit to remove ffd template new mw.Api.postWithToken( 'edit', {					action: 'edit',					title: filename,					text: updated_filedesc,					summary: "FFD closed as " + resultcomment + " (using FFDcloser)"				} ).done( function( result, jqXHR ) {					deliverMsg( anchor, "Removed from " + filename, "is_done", null, null, true );					if (lastfile === true) {						deliverMsg( anchor, null, null, true ); //remove working message					}				} ).fail( function( code, result ) {					var error_details = apifailed( code, result );					deliverMsg( anchor, "Could not remove  from " + filename + " " + error_details, "warning", null, null, true );					if (lastfile === true) {						deliverMsg( anchor, null, null, true ); //remove working message					}				} );

} ).fail( function( code, result ) { var error_details = apifailed( code, result ); deliverMsg( anchor, filename + " not found; could not remove " + error_details, "warning", null, null, true ); if (lastfile === true) { deliverMsg( anchor, null, null, true ); //remove working message }		} );

} ).fail( function( code, result ) { var error_details = apifailed( code, result ); deliverMsg( anchor, "Could not edit " + filetalkpage + " " + error_details, "warning", null, null, true ); if (lastfile === true) { deliverMsg( anchor, null, null, true ); //remove working message }	} );

}

/* == Delete file == */ function delete_file(filename, thereason, anchor, lastfile) { if ( !checkNS(filename, 6) ) { deliverMsg( anchor, "\"" + filename + "\" is not in File: namespace, FFDcloser will not delete this page", "error", lastfile, null, !lastfile); return; }	new mw.Api.postWithToken( 'delete', {		action: 'delete',		title: filename,		reason: thereason,	} ).done( function( result, jqXHR ) {		deliverMsg( anchor, "Deleted " + filename, "deleted", null, null, true );		if (lastfile === true) {			deliverMsg( anchor, null, null, true ); //remove "Deleting..." message		}	} ).fail( function( code, result ) {		var error_details = apifailed( code, result );		deliverMsg( anchor, "Could not delete " + filename + " " + error_details, "warning", null, null, true );		if (lastfile === true) {			deliverMsg( anchor, null, null, true ); //remove "Deleting..." message		}	} );

}

/* == Relist discussion == */ function relist_disc(filename, discussion, relistcomment, todaysdate, sectionheader, anchor) {

var relist_editsum, relists, num_relists, rc_if_any, newdiscussion;

//Edit summary varies based on if sectionheader is defined or not if ( sectionheader ) { relist_editsum = "Relisting \"" + sectionheader + "\" (using FFDcloser)"; } else { relist_editsum = "Relisting " + filename + " (using FFDcloser)"; }

//Check for number of relists, append {relist} template relists = discussion.match("Relisted"); if ( relists ) { num_relists = relists.length + 1; } else { num_relists = 1; }	if ( relistcomment !== "" ) { rc_if_any = relistcomment; } else { rc_if_any = ""; }	newdiscussion = discussion + "\n{" + "{subst:Relist|" + rc_if_any + "|" + num_relists + "}}\n";

//Can append to end of daily subpage new mw.Api.postWithToken( 'edit', {		action: 'edit',		title: FFDpath + todaysdate,		appendtext: "\n" + newdiscussion,		summary: relist_editsum	} ).done( function( result, jqXHR ) {		window.open("//en.wikipedia.org/wiki/" + FFDpath + todaysdate, "ffdtoday");	} ).fail( function( code, result ) {		var error_details = apifailed( code, result );		deliverMsg( anchor, "Could not relist discussion " + error_details, "error", true );	} );

}

/* == Update file ffd template (after relisting) == */ function update_file_ffd(filename, today_subpage, anchor, lastfile) { if ( !checkNS(filename, 6) ) { deliverMsg( anchor, "\"" + filename + "\" is not in File: namespace, FFDcloser will not edit this page", "error", lastfile, null, !lastfile); return; }	new mw.Api.get( {		action: 'query',		titles: filename,		prop: [ 'revisions', 'info' ],		rvprop: 'content',		indexpageids: 1,		rawcontinue: ''	} ).done( function( result, jqXHR ) {		var file_id = result.query.pageids;		var file_contents = result.query.pages[ file_id ].revisions[ 0 ][ '*' ];		var new_file_contents = file_contents.replace(/]*/gi, "{{ffd|log=" + today_subpage );		new mw.Api.postWithToken( 'edit', { action: 'edit', title: filename, text: new_file_contents, summary: "Updating template: file was relisted (using FFDcloser)" } ).done( function( result, jqXHR ) { deliverMsg( anchor, "Updated on " + filename, "is_done", null, null, true ); if (lastfile === true) { deliverMsg( anchor, null, null, true ); //remove working message }			} ).fail( function( code, result ) { var error_details = apifailed( code, result ); deliverMsg( anchor, "Could not update on " + filename + " " + error_details, "warning", null, null, true ); if (lastfile === true) { deliverMsg( anchor, null, null, true ); //remove working message }			} );	} ).fail( function( code, result ) {		var error_details = apifailed( code, result );		deliverMsg( anchor, filename + " not found; could not update " + error_details, "warning", null, null, true );		if (lastfile === true) {			deliverMsg( anchor, null, null, true ); //remove working message		}	} );

} //