Wikipedia talk:WikiProject Articles for creation/WikiProject templates.json

How will this be updated? edit

@SD0001: Are there any plans to have a bot update this page? It already appears out of date -- just going from the top alphabetically, WP:WikiProject 1000 Women in Religion, WP:WikiProject A Cappella, and WP:WikiProject AIDS are missing. The code to do so is fairly simple, for example, my draft sorter tool uses a variation of the following code:

Extended content
//Set up parameters
var wikiUrl="https://en.wikipedia.org";
var username = "########";
var password = "########";
var templateList = "Wikipedia:WikiProject Articles for creation/WikiProject templates.json";
var templateIncludelistName = "Wikipedia:WikiProject Articles for creation/WikiProject templates.json/includelist.json";
var templateBlocklistName = "Wikipedia:WikiProject Articles for creation/WikiProject templates.json/blocklist.json";
var wikiProjectMainCategory = "Category:WikiProject banner wrapper templates";
var wikiProjectCategories = [ // other WikiProject categories not included in wikiProjectMainCategory
	"Category:WikiProject banners with quality assessment",
	"Category:WikiProject banners without quality assessment",
	"Category:WikiProject banner templates not based on WPBannerMeta",
	"Category:Inactive WikiProject banners",
	"Category:WikiProject banner wrapper templates",
];

//Define globals
require('jsdom-global')(undefined, {"url": wikiUrl});
require('mock-mediawiki');
var wikiprojects = {}, templateBlockList;
var apiUrl = wikiUrl+mw.util.wikiScript('api')
var api = new mw.Api({ ajax: { url: apiUrl} });

//Log in
api.login( username, password )
	.done (function (data) {
		console.log("Logged in as "+data.login.lgusername);
		templateBlockList = fetchJSONList(templateBlocklistName);
		getTemplateCategories();
	} ).fail (function(error) {
		console.warn("Error logging in:");
		console.log(error);
	} );

function fetchJSONList(listName) {
	var parsedList = {};
	console.log("Attempting to fetch " + listName + "...");
	var listData = JSON.parse($.ajax({
		url: apiUrl, async:false,
		error: function (jsondata) {
			console.warn("Unable to fetch contents of " + listName + ":");
			console.log(jsondata);
			return {};				
		}, data: {action:'parse', format:'json', prop:'wikitext', page: listName, formatversion: '2', origin: '*' }
	}).responseText).parse;
	console.log("Attempting to parse " + listName + "...");
	if (listData && listData.wikitext) {
		try {
			parsedList = JSON.parse(listData.wikitext);
		} catch (jsonerror) {
			console.warn("Error parsing JSON list " + listName + ":");
			console.log(jsonerror);
		}
	}

	return parsedList;
}

function getTemplateCategories(cont) { // Recursively call API
	var query = {
		action: "query",
		list: "categorymembers",
		cmtitle: wikiProjectMainCategory,
		cmtype: "subcat",
		cmlimit: "max",
		origin: '*'
	};
	if (cont) {
		query = Object.assign(query, cont);
	}
	console.log("Fetching subcategories of " + query.cmtitle + "...");
	api.get( query )
		.done (function (data) {
			if (data && data.query && data.query.categorymembers) { //API query returned members
				Object.entries(data.query.categorymembers).forEach( function(item) {
					wikiProjectCategories.push(item[1].title);
				} );
			}
			if (data && data.continue) { //More results are available
				getTemplateCategories(data.continue);
			} else {
				getTemplatesFromCategories();
			}
		} ).fail (function(error) {
			console.warn("Error getting list of categories:");
			console.log(error);
		} );
	return;
}

function getTemplatesFromCategories(catTitle, cont) { // Recursively call API
	if (typeof catTitle === 'undefined') { // Grab next item in wikiProjectCategories
		catTitle = wikiProjectCategories.pop();
	}
	if (typeof catTitle === 'undefined') { // No remaining entries in wikiProjectCategories
		// Manually add Wikiprojects with /s in their title
		jQuery.extend( wikiprojects, fetchJSONList(templateIncludelistName) );
		writeList();
	} else {
		
		var query = {
			action: "query",
			list: "categorymembers",
			cmtitle: catTitle,
			cmtype: "page",
			cmnamespace: "10",
			cmlimit: "max",
			origin: '*'
		};
		console.log("Fetching contents of " + query.cmtitle + "...");
		if (cont) {
			query = Object.assign(query, cont);
		}
		api.get( query )
			.done (function (data) {
				if (data && data.query && data.query.categorymembers) { //API query returned members
					Object.entries(data.query.categorymembers).forEach( function(item) {
						var title = item[1].title.match(/^Template:WikiProject\s(.*)$/);
						if ( (title && title[1] && title[1] !== "") && ( title[1].indexOf("/") == -1 || title[1].match(/ task ?force$/i) ) ) { //Valid page name format
							title[1] = title[1].replace(/ task ?force$/i,"");
							if( !(templateBlockList[ title[1] ]) ) { //Not on blocklist
								wikiprojects[ title[1] ] = item[1].title.replace("Template:", "");
							}
						}
					} );
				}
				if (data && data.continue) { //More results are available
					getTemplatesFromCategories(catTitle, data.continue);
				} else {
					getTemplatesFromCategories();
				}
			} ).fail (function(error) {
				console.warn("Error getting list of templates:");
				console.log(error);
			} );
		return;
	}
}

function writeList() {
	wikiprojects = Object.keys(wikiprojects).sort().reduce(
		(obj, key) => { 
			obj[key] = wikiprojects[key]; 
			return obj;
		}, 
		{}
	);
	
	var params = {
		action: 'edit',
		title: templateList,
		text: JSON.stringify(wikiprojects),
		summary: "Update WikiProject list",
		watchlist:"unwatch"
	}
	console.log("Writing to " + params.title + "...");
	api.postWithToken("csrf", params ).done( function(reslt) {
		console.log(templateList + " updated:");
		console.log(reslt);
	} ).fail( function(reslt) {
		console.warn("Error updating " + templateList + ":");
		console.log(reslt);
	} );
}

--Ahecht (TALK
PAGE
) 01:17, 10 January 2021 (UTC)Reply

Sorry for the late reply. The problem with such an update is that it's indiscriminate. Since this page was created for use from MediaWiki:AFC-add-project-tags.js (and soon MediaWiki:AFC-submit-wizard.js when that becomes a thing), it would help to keep only the content-based wikiprojects in the list, so that it's not confusing for new users. Projects like Wikipedia:WikiProject Abandoned Articles, Abandoned Drafts, etc etc and even WikiProject 1000 Women in Religion don't really belong here.
I see that your update has added a lot of new content wikiprojects, but it has only also added back the non-content projects that had been removed earlier. – SD0001 (talk) 10:28, 1 April 2021 (UTC)Reply
@Ahecht: forgot to ping. – SD0001 (talk) 10:32, 1 April 2021 (UTC)Reply
@Ahecht I have removed the non-content/maintenance projects in this edit. Maybe we can set up a blacklist with these pages and then have the script ignore those – though the blacklist will need to be manually maintained. – SD0001 (talk) 07:53, 26 June 2021 (UTC)Reply
@SD0001: I created a blacklist page at Wikipedia:WikiProject_Articles_for_creation/WikiProject_templates.json/blocklist.json (I didn't add WP:WikiProject MIT/Media Lab to the list, since that is a content Wikiproject about an organization called the "MIT/Media Lab"). I'll work on updating the script a bit later today. --Ahecht (TALK
PAGE
) 22:27, 27 June 2021 (UTC)Reply
@SD0001: I updated the script above. When run in the console, it will update Wikipedia:WikiProject Articles for creation/WikiProject templates.json. If we wanted this to be a bot task, we'd probably have to convert from javascript to some other language (python?). --Ahecht (TALK
PAGE
) 18:48, 28 June 2021 (UTC)Reply
@Ahecht: Awesome, thanks. Since this only needs an update once in a while, a bot task might be overkill. That being said, some time ago I created https://github.com/wikimedia-gadgets/mock-mediawiki that makes mw interfaces usable in node.js. So with that, you should be able to run this script straight in node.js after adding await new mw.Api().login("USERNAME", "PASSWORD"); at the top, and maybe setting the apiUrl in mw.Api usages. – SD0001 (talk) 19:59, 28 June 2021 (UTC)Reply
@SD0001: I'll have to play around with that a bit. I'm getting CORS errors (Cross origin null forbidden) when I try to log in using the script as updated above. --Ahecht (TALK
PAGE
) 19:27, 29 June 2021 (UTC)Reply
@Ahecht Looks like you have the jsdom-global syntax slightly wrong. Looking at its source, it should be require('jsdom-global')(undefined, {"url": wikiUrl});SD0001 (talk) 07:16, 3 July 2021 (UTC)Reply
@SD0001: Thanks, that did it! --Ahecht (TALK
PAGE
) 18:06, 4 July 2021 (UTC)Reply