User:Ahecht/sandbox/Scripts/draft-sorter.js
(Redirected from User:Ahecht/Scripts/draft-sorter.js/sandbox)
Code that you insert on this page could contain malicious content capable of compromising your account. If you import a script from another page with "importScript", "mw.loader.load", "iusc", or "lusc", take note that this causes you to dynamically load a remote script, which could be changed by others. Editors are responsible for all edits and actions they perform, including by scripts. User scripts are not centrally supported and may malfunction or become inoperable due to software changes. A guide to help you find broken scripts is available. If you are unsure whether code you are adding to this page is safe, you can ask at the appropriate village pump. This code will be executed when previewing this page. |
This user script seems to have a documentation page at User:Ahecht/sandbox/Scripts/draft-sorter. |
//jshint maxerr:512
//jshint esnext:false
//jshint esversion:8
//Based on [[User:Enterprisey/draft-sorter.js]] <nowiki>
( function ( $, mw ) { mw.loader.using( ["mediawiki.api", "jquery.chosen", "oojs-ui-core"], function () {
mw.loader.load( "mediawiki.ui.input", "text/css" );
var api = new mw.Api();
if ( mw.config.get( "wgNamespaceNumber" ) !== 118 ) {
if ( mw.util.getParamValue('draftsorttrigger') ) {
// "Next draft" was clicked, but we ended up on a non-draft page
nextDraft();
return;
} else {
return;
}
}
var portletLink = mw.util.addPortletLink("p-cactions", "#", "Sort draft (sandbox)", "pt-draftsort", "Manage WikiProject tags");
$( portletLink ).click( function ( e ) {
e.preventDefault();
// If it's already there, don't duplicate
if ( $( "#draft-sorter-wrapper" ).length ) { return; }
// Configure defaults
//var templateCache = mw.config.get("wgFormattedNamespaces")[2]+":"+mw.config.get("wgUserName")+"/Scripts/draft-sorter.json";
var templateCache = "Wikipedia:WikiProject Articles for creation/WikiProject templates.json";
// Define the form
var form = $( "<div>" )
.attr( "id", "draft-sorter-wrapper" )
.css( { "background-image": "url(https://upload.wikimedia.org/wikipedia/commons/e/e2/OOjs_UI_icon_tag-ltr-progressive.svg)",
"background-repeat": "no-repeat",
"background-position-y": "center",
"background-size": "50px",
"min-height": "50px",
"margin": "1em auto",
"border": "thin solid #BBB",
"padding": "0.5em 50px",
"display": "inline-block",
"border-radius": "0.25em"
} ).append( $( "<span>" )
.text( "Loading form..." )
.css( "color", "gray" )
);
// Add the form to the page
form.insertAfter( "#contentSub" );
var select = $( "<select>" )
.attr( "id", "draft-sorter-form" )
.attr( "multiple", "multiple" );
var submitButton = new OO.ui.ButtonWidget ()
.setLabel( "Submit" )
.setFlags( [ 'primary', 'progressive' ] )
.on("click", function ( e ) { submit(); } );
var cancelButton = new OO.ui.ButtonWidget ()
.setLabel( "Cancel" )
.setFlags( ["destructive"] )
.on("click", function( e ) {
$( "#draft-sorter-wrapper" ).remove();
window.location.replace( window.location.href.replace("draftsorttrigger=y","") );
} );
var nextButton = new OO.ui.ButtonWidget ()
.setIcon( "next" )
.setLabel( "Skip" )
.on("click", function ( e ) { nextDraft(); } );
// Determine what templates are already on the talk page
var existingProjects = [];
var wikiprojects = {};
api.get( {
action: "query",
titles: "Draft talk:" + mw.config.get( "wgTitle" ),
generator: "templates",
redirects: "1",
gtllimit: "max",
} ).done (function (data) {
if (data && data.query && data.query.pages) {
$.each(data.query.pages, function (i) {
var item = data.query.pages[i].title.match(/^Template:(WikiProject\s[^\/]*)$/i);
if (item && item[1] && item[1] != "WikiProject banner shell") {
existingProjects.push(item[1]);
}
} );
}
console.log( "Project templates found on talk page: ");
console.log( existingProjects );
fetchJSONList(templateCache).then( (cachedList) => {
wikiprojects = cachedList;
constructForm();
} );
} ).fail (function() {
console.log("Retrieving project templates from talk page failed.");
fetchJSONList(templateCache).then( (cachedList) => {
wikiprojects = cachedList;
constructForm();
} );
});
predicts = [];
async function fetchJSONList(listName) {
var parsedList = {}, listData;
var query = {
action:'parse',
prop:'wikitext',
page: listName,
formatversion: '2',
origin: '*'
};
try {
listData = await api.get( query );
} catch (jsonerror) {
console.warn("Unable to fetch contents of " + listName + ":");
console.log(jsonerror);
}
if (listData && listData.parse && listData.parse.wikitext) {
try {
parsedList = JSON.parse(listData.parse.wikitext);
} catch (jsonerror) {
console.warn("Error parsing JSON list " + listName + ":");
console.log(jsonerror);
}
}
return parsedList;
}
function nextDraft() {
// Special:RandomInCategory isn't random, use toolforge instead
if (nextButton) {
nextButton.setLabel( "Loading..." ).setDisabled( true );
}
window.location.href = "https://randomincategory.toolforge.org/Pending_AfC_submissions?draftsorttrigger=y&cmnamespace=118&cmtype=page&returntype=subject&server=" + mw.config.get("wgServerName");
}
function showPredicts() {
$( "#draft-sorter-status" ).append( "<li>Suggested categories from <a href=\"https://www.mediawiki.org/wiki/ORES#Topic_routing\">ORES</a>:<ul id=\"draft-sorter-suggest\"></ul></li>" );
predicts.forEach( function(item) {
function addWithLink(p) {
$( "#draft-sorter-suggest" ).append(
$( "<li>" ).text( item + " (" ).append(
$( "<a>" ).text("add").click(
function() {
$( select ).val(
$( select ).val().concat( [ "WikiProject " + p ] )
).trigger("chosen:updated");
}
)
).append( ")" )
);
}
var singularItem = item.replace(/s$/, '');
if( !existingProjects.includes( "WikiProject " + item )
&& wikiprojects[item]
) { //Prediction matches a WikiProject and doesn't already exist
addWithLink(item);
} else if( singularItem != item
&& !existingProjects.includes( "WikiProject " + singularItem )
&& wikiprojects[singularItem]
) { //Singular form of prediction matches a WikiProject and doesn't exist
addWithLink(singularItem);
} else { //Prediction doesn't match a WikiProject or already exists
$( "#draft-sorter-suggest" ).append(
$( "<li>" ).append( item )
);
}
} );
return;
}
function getPredicts() {
var lang = mw.config.get("wgServerName").split(".wikipedia.org");
if (lang.length == 1) return;
const liftWingExternalEndpoint = "https://api.wikimedia.org/service/lw/inference/v1/models/";
let headers = new Headers({
"Content-Type": "application/json",
"User-Agent": "draft-sorter (https://en.wikipedia.org/wiki/User:Ahecht/Scripts/draft-sorter.js)"
});
var revID = mw.config.get( "wgCurRevisionId" );
var model = (lang[0] == "en") ? "enwiki-drafttopic" : "outlink-topic-model";
var postBody = JSON.stringify({
"rev_id": revID,
"lang": lang[0],
"page_title": mw.config.get("wgPageName")
});
fetch(liftWingExternalEndpoint + model + ":predict", {
method: "POST",
headers: new Headers({
"Content-Type": "application/json",
"User-Agent": "draft-sorter (https://en.wikipedia.org/wiki/User:Ahecht/Scripts/draft-sorter.js)"
}),
body: postBody
}).then(response => response.json()).then(data => {
var prediction = [];
var dbName = mw.config.get("wgDBname");
if(data && data[dbName] && data[dbName].scores &&
data[dbName].scores[revID] &&
data[dbName].scores[revID].drafttopic &&
data[dbName].scores[revID].drafttopic.score &&
data[dbName].scores[revID].drafttopic.score.prediction) {
prediction = data[dbName].scores[revID].drafttopic.score.prediction;
} else if (data && data.prediction && data.prediction.results) {
data.prediction.results.forEach( p => {
if (p && p.topic) prediction.push(p.topic);
} );
}
if (prediction.length) {
console.log("Got ORES response! Raw predictions:");
console.log(prediction);
prediction.forEach( function (item) {
var last = item.split(".")[item.split(".").length-1];
var penultimate = item.split(".")[item.split(".").length-2];
if ( last.substr(-1) == "*" ) {
// Filter out redundant starred predictions
if (prediction.find(element => (
element.split(".")[element.split(".").length-1] != last &&
element.split(".")[element.split(".").length-2] == penultimate
) ) ) {
console.log("Prediction \"" + last + "\" excluded.");
last = null;
} else {
last = penultimate;
}
}
if ( wikiprojects[last] ) {
// WikiProject found, no need to try splitting
predicts.push(last);
} else if ( last ) {
// Can't find wikiProject, try splitting
var splitLast = last.split(/( & | and )/);
for (i=0;i<=splitLast.length;i+=2) {
splitLast[i] = splitLast[i].charAt(0).toUpperCase()
+ splitLast[i].slice(1);
predicts.push( splitLast[i] );
}
}
} );
console.log("Filtered predictions:");
console.log(predicts);
showPredicts();
} else {
console.warn("Error finding predictions in ORES response:");
console.warn(data);
}
} ).catch( e => console.warn("Error retrieving ORES data: " + e) );
return;
}
// Construct the form
function constructForm() {
mw.loader.load( "oojs-ui.styles.icons-movement");
Object.keys(wikiprojects).sort().forEach( function(name) {
select.append( $( "<option>" )
.attr( "value", wikiprojects[name] )
.text( name ) );
} );
form.hide();
form.empty();
form.append( $( "<span>" )
.text( "Tag WikiProjects: " )
.css( {
"font-size": "115%",
"font-weight": "bold"
} )
);
form.append( select );
form.append( "  " );
form.append( submitButton.$element );
form.append( cancelButton.$element );
form.append( nextButton.$element );
form.append ( $( "<ul>" )
.attr( "id", "draft-sorter-status" )
);
form.show();
$( select )
.val( existingProjects )
.chosen( {"placeholder_text_multiple": "Select some WikiProjects"} )
.on("change", function(evt, params) { //Make existing projects undeletable
$( "#draft-sorter-status" ).empty();
if ( predicts.length > 0 ) { showPredicts(); }
if ( params.deselected && existingProjects.includes(params.deselected) ) {
$( select ).val( $( select ).val().concat([params.deselected]) ).trigger("chosen:updated");
$( "#draft-sorter-status" ).prepend( $( "<li>" )
.text( "Draft Sorter cannot remove existing WikiProjects." )
.addClass( "error" )
);
}
} );
// Add completed form to the page
$( '#draft-sorter-wrapper' ).replaceWith(form);
getPredicts();
return;
}
// The submission function
function submit() {
$( "#draft-sorter-form" )
.attr("disabled", true)
.trigger("chosen:updated");
submitButton
.setLabel( "Submitting..." )
.setDisabled( true );
cancelButton
.setLabel ( "Close" );
var newTags = [];
$( "#draft-sorter-form" ).val().forEach( function (element) {
if ( !existingProjects.includes(element) ) {
newTags.push(element);
}
} );
console.log( newTags.length + " new tag(s): " + newTags.join(", ") );
var statusList = $( "#draft-sorter-status" )
.html( "<li>Saving " + newTags.length + " new tags.</li>" );
var showStatus = function ( status ) {
return $( "<li>" )
.text( status )
.appendTo( statusList );
};
var newText = "";
newTags.forEach( function ( element ) {
newText += "{{" + element + "|importance=|class=draft}}\n";
} );
function editTalk(text, prefix) {
var params = {
action: "edit", section: "0",
title: "Draft talk:" + mw.config.get( "wgTitle" ),
summary: "Tagging draft: +" + newTags.join(", +") +
" ([[User:Ahecht/Scripts/draft-sorter|draft-sorter]])",
};
params[prefix + "text"] = text;
api.postWithEditToken( params ).done( function ( data ) {
if ( data && data.edit && data.edit.result && data.edit.result === "Success" ) {
showStatus( "Edit saved successfully! (" )
.append( $( "<a>" )
.text( "reload" )
.attr( "href", "#" )
.click( function () {
window.location.replace(
window.location.href.replace("draftsorttrigger=y","")
);
} )
).append( ")" );
submitButton.setLabel( "Submitted" );
nextButton.setLabel( "Next draft" ).setFlags( [ 'progressive' ] );
} else {
showStatus( "Couldn't save due to error: " + JSON.stringify( data ) );
}
} ).fail( function ( error ) {
showStatus( "Couldn't save due to error: " + JSON.stringify( error ) );
} );
return;
}
api.get( {
action: "query",
titles: "Draft talk:" + mw.config.get( 'wgTitle' ),
prop: "templates",
tltemplates: "Template:WikiProject_banner_shell"
} ).done (function (data) {
var bannerShellUsed = Object.entries(data.query.pages)[0][1].templates;
if(typeof(bannerShellUsed) == "object" && bannerShellUsed.length > 0) {
api.get( {
action: "parse",
page: "Draft talk:" + mw.config.get( 'wgTitle' ),
prop: "wikitext",
section: "0"
} ).done (function (data) {
var talkText = data.parse.wikitext["*"];
if (typeof(talkText) == "string") {
var pattern = /(\{\{\s*(?:Wiki[ _]?Project[ _]?banners?[ _]?shell(?:\/redirect)?|(?:(?:WP)?[ _]?Banner|(?:Wiki)?Project|Scope)[ _]?shell|Multiple[ _]wikiprojects|WikiProject[ _]?Banners?|WPBS?)\s*\|(?:\s*[a-z1]+\s*=[^\{\}]*)*\s*(?:\\n)*?)/im;
if (talkText.search(pattern) >= 0) {
newText = talkText.replace( pattern, ("$1" + newText) );
editTalk(newText,"");
} else {
console.log("Banner shell on talk page, but not found in wikitext: " + talkText);
editTalk(newText,"prepend");
}
} else {
console.log("typeof(talkText) = " + typeof(talkText));
editTalk(newText,"prepend");
}
} ).fail (function (error) {
console.warn( "Couldn't retrieve talk page text due to error: " + JSON.stringify( error ) );
editTalk(newText,"prepend");
} );
} else if(newTags.length > 2) {
console.log("typeof(bannerShellUsed) = " + typeof(bannerShellUsed) );
newText = "{{WikiProject banner shell|\n" + newText + "}}";
editTalk(newText,"prepend");
} else {
console.log("typeof(bannerShellUsed) = " + typeof(bannerShellUsed) + "; newTags.length = " + newTags.length);
editTalk(newText,"prepend");
}
} ).fail( function ( error ) {
console.warn( "Couldn't retrieve templates on talk page due to error: " + JSON.stringify( error ) );
editTalk(newText,"prepend");
} );
return;
}
} );
if (mw.util.getParamValue('draftsorttrigger')) {
$( portletLink ).trigger("click");
}
} ) }( jQuery, mediaWiki ) );
//</nowiki>