MediaWiki:Gadget-StaffColorsUpdater.js

/* jshint esversion: 5, forin: false, immed: true, indent: 4, latedef: true, newcap: true, noarg: true, undef: true, undef: true, unused: true, browser: true, jquery: true, onevar: true, eqeqeq: true, multistr: true, maxerr: 999999, -W082, -W084 /* global mw */ /* Config File for script stored at MediaWiki:Gadget-StaffColorsUpdater.js/staff-colors.json */ mw.loader.using(["mediawiki.api"]).then(function {

function forKeys(o, cb, thisArg) { var count = 0; Object.keys(o).forEach(function (key) {			var value = o[key];			cb.call(thisArg, key, value, o, count);			count++;		}); }

function objectToRule(o) { var ret = []; forKeys(o, function (k, v) {			ret.push("\t" + k + ": " + v + ";");		}); return "{\n" + ret.join("\n") + "\n}"; }

function finalAlert($this) { $this.text("Update Staff Colors"); alert("Staff Color Updater: Successful updated LESS for staff colors.\n\n" +			Object.keys(window.StaffMembersList).map(function (i) { return window.StaffMembersList[i].rank + ": " + new Set(window.StaffMembersList[i].users).size; }).join("\n") + "\n\n" +			"File Updated: Custom-common.less/staff-colors.less\n" +			"Script: Gadget-StaffColorsUpdater.js\n" +			"Configs: Gadget-StaffColorsUpdater.js/staff-colors.json\n\n" +			"Note:\nTo see the changes, you still have to update CSS."		); }

function parse { var def = new $.Deferred;

window.fetchStaffList.then(function {			var data = window.StaffJsonData;			new mw.Api.get({ action: "query", list: "allusers", augroup: Object.keys(data.ids).join("|"), auprop: "groups", aulimit: 500, }).then(function (d) { var states = ["LINKS", "ICONS", "TAGS"]; d = d.query.allusers .map(function (v) {						return {							name: v.name,							groups: v.groups								.filter(function (v) { return !data.implicitGroups.includes(v); })								.map(function (v) { return data.ids[v]; }),						};					});

var overrides = data.overrides; var overridesList = { ICONS: [], LINKS: [], TAGS: [], };

forKeys(overrides, function (state, v) {					forKeys(v, function (rank_, list) { list.forEach(function (user) {							overridesList[state].push(user);							if (window.StaffGroupsList[rank_].indexOf(user) === -1) window.StaffGroupsList[rank_].push(user);						}); });				});

function eachState(state, i) { var temp = []; var done = {};

for (var j in window.StaffMembersList) { if (window.StaffMembersList[j].parse) { var rank = window.StaffMembersList[j].rank, validusers = window.StaffMembersList[j].users;

var userList = []; var hidden = []; var ruleType = []; temp.push("\n/* " + rank + "*/");

function each(user) { if (data.ignore.indexOf(user) !== -1) return; if (user.includes(" ")) each(user.replace(/ /g, "_")); var sel = data.selectors[state].replace(/\$1/g, user);

if (!done[user] && overridesList[state].indexOf(user) === -1) { ruleType.push("normal"); userList.push(sel); } else if (overrides[state][rank].indexOf(user) !== -1 && !done[user]) { ruleType.push("override"); userList.push(sel); } else if (!done[user] && overridesList[state].indexOf(user) !== -1) { ruleType.push("overridden"); userList.push("/* " + sel + " */"); }

if (done[user]) hidden.push(" " + sel);

if (overridesList[state].indexOf(user) === -1) done[user] = true; }

validusers.forEach(each);

var lastElem = -1; for (var index = ruleType.length - 1; index >= 0; index--) { if (ruleType[index] === "normal" || ruleType[index] === "override") { lastElem = index; break; }							}							for (index = 0; index < ruleType.length; index++) { if (index === lastElem) userList[index] = userList[index].replace(/,(\s*)$/, "$1"); if (ruleType[index] === "override") userList[index] += " /* This selector is an override */"; if (ruleType[index] === "overridden") userList[index] += " /* This selector is overridden */"; }

temp.push("/* " + data.abbr[rank] + "\'s with higher ranks are removed\n" + hidden.join("\n") + "\n*/"); temp.push(userList.join("\n"));

var rule = objectToRule(data.styles[state]); if (i === 0) rule = rule.replace(/\$1/, data.colors[rank][0]).replace(/\$2/, data.colors[rank][1]); else if (i === 1) rule = rule.replace(/\$1/, data.imageUrls[rank]); else if (i === 2) rule = rule.replace(/\$1/, data.wallText[rank]);

if (lastElem === -1) rule = "/*\n" + rule + "\n*/"; temp.push(rule); }					}					return "\n/*** " + state + " ***/\n" + temp.join("\n"); }

var allstates = states.map(function (state, i) {					return eachState(state, i);				});

var ret = ["/* Staff Colors\n\nThis stylesheet contains the css to color staff member\'s names. \nIt is automatically updated, any changes you make will be \noverwritten next time this stylesheet gets updated. \n*/"]; for (var i in allstates) ret.push(allstates[i]);

def.resolve(ret.join("\n")); }).catch(console.warn);		}).catch(console.warn);

return def; }

(function init {		window.updateStaffColors = function (cb, thisArg) {			parse.then(function (css) { new mw.Api.postWithEditToken({					action: "edit",					text: css,					title: "MediaWiki:Custom-common.less/staff-colors.less",					summary: "Updating Staff Colors (StaffColorsUpdater)",					minor: 1,				}).then(function (r) {					if (cb) cb.call(thisArg, css, r);				}, console.warn); console.log("Staff Colors (Less) Updated."); });		};

mw.hook("hsw.gadget.staffColorsUpdater").fire(window.updateStaffColors); if (			window.StaffColorsUpdaterLoaded ||			(mw.config.get("wgNamespaceNumber") !== 8) // not in MediaWiki namespace			||			( ["Custom-common.less", "Common.css"] .indexOf(mw.config.get("wgTitle")) < 0 // not in one of these pagenames ) ||			mw.config.get("wgAction") !== "view" // not viewing page content			||			!/sysop|codeeditor|staff|util|soap|wiki-manager|content-team-member|content-reviewer|content-volunteer/			.test(mw.config.get("wgUserGroups").join("\n").toLowerCase) // not in one of these usergroups		) return; window.StaffColorsUpdaterLoaded = true;

$("#mw-content-text").before($("", { class: "wds-button", html: $(" ", {				click: function {					var $this = $(this);					$this.text("Updating...");					$this.attr({ disabled: true });					window.updateStaffColors(finalAlert.bind(null, $this));				},				text: "Update Staff Colors",				title: "Update Staff Colors",			}), title: "Update Staff Colors", css: { cursor: "pointer", "margin-bottom": "5px", }		}));	});

window.fetchStaffList = function { var def = new $.Deferred;

$.getJSON(new mw.Title("Gadget-StaffColorsUpdater.js/staff-colors.json", 8).getUrl({ action: "raw", ctype: "text/json" })).then(function (data) {			window.StaffJsonData = data;

var bypassn = []; var staffn = {};

function waitTill(rank, users) { return new mw.Api.get({					action: "query",					list: "users",					ususers: users.join("|"),					usprop: "groupmemberships",					aulimit: 500,				}).then(function (dt) {					function searchid(rank) {						var rankid;

function cb(k, v) { if (v === rank) rankid = k;						} forKeys(data.ids, cb); return rankid; }

dt = dt.query.users; var valid = {}; for (var k in dt) { valid[dt[k].name] = true; if (dt.hasOwnProperty(k) && dt[k].hasOwnProperty("groupmemberships")) { var arr = dt[k].groupmemberships; for (var i in arr) { if (arr[i].group === searchid(rank)) { valid[dt[k].name] = arr[i].expiry === "infinity"; if (!valid[dt[k].name]) bypassn.push(dt[k].name); }							}						}					}					staffn[rank] = users.filter(function (user) {						return valid[user];					}); return { "rank": rank, "users": staffn[rank], };				});			}

new mw.Api.get({				action: "query",				list: "allusers",				augroup: Object.keys(data.ids).join("|"),				auprop: "groups",				aulimit: 500,			}).done(function (d) {				d = d.query.allusers					.map(function (v) { return { name: v.name, groups: v.groups .filter(function (v) {									return !data.implicitGroups.includes(v);								}) .map(function (v) {									return data.ids[v];								}), };					});

var groupsList = {}; data.ranks.forEach(function (rank) {					groupsList[rank] = [];					d.forEach(function (v) { if (v.groups.indexOf(rank) !== -1) { groupsList[rank].push(v.name); }					});				});				window.StaffGroupsList = groupsList;

var allwaits = [];

forKeys(groupsList, function (rank, users) {					allwaits.push(waitTill(rank, users));				});

return $.when.apply($, allwaits).then(function {					var obj = [];					if (Object.keys(staffn).length) {						Object.keys(data.order).sort(function (a, b) { data.order[a] > data.order[b]; }).forEach(function (k) { obj.push({								rank: k,								users: Array.from(new Set(staffn[k])),								parse: true,							}); });						obj.push({ rank: "Skipped Temporary Ranks", users: Array.from(new Set(bypassn)), parse: false, });					}

console.log("Staff Lists Updated."); window.StaffMembersList = obj; def.resolve; }).catch(console.warn);			}).catch(console.warn); }).catch(console.warn);

return def; }; });