User:Daniel Quinlan/Scripts/HideBots.js

class HideBots { constructor($, mw) { this.$ = $; this.mw = mw; this.apiHighlimits = this.getApiHighlimits; }

getApiHighlimits { return this.mw.config.get('wgUserGroups').some(group => ['sysop', 'researcher'].includes(group)) || this.mw.config.get('wgGlobalGroups').some(group => ['apihighlimits-requestor', 'global-sysop', 'staff', 'steward', 'sysadmin', 'wmf-researcher'].includes(group)); }

chunks(full, n) { const chunkedArray = []; for (let i = 0; i < full.length; i += n) { chunkedArray.push(full.slice(i, i + n)); }		return chunkedArray; }

async postRequest(data, callback, property, largeSize = false) { const cumulativeResult = {}; function successCallback(response) { if (response && response.query && response.query[property]) { response.query[property].forEach(function(element) {					const result = callback(element);					if (result) {						cumulativeResult[result.key] = result.value;					}				}); const responseSize = response.query[property].length; if (largeSize && responseSize >= largeSize) { alert(`${property} response size: ${responseSize}`); }			} else { throw new Error("JSON location not found or empty"); }		}		const url = this.mw.util.wikiScript('api') + '?format=json&action=query'; try { await this.$.post(url, data, successCallback, 'json'); return cumulativeResult; } catch (error) { throw new Error(`Failed to fetch data: ${error.message}`); }	}

async usersQueries(usernames) { function processUser(user) { let state = false; if (user.groups && user.groups.includes('bot')) { state = true; }			return { key: user.name, value: state }; }

const responses = {}; const chunkSize = this.apiHighlimits ? 500 : 50;		const queryData = { list: 'users', usprop: 'groups' };		for (const chunk of this.chunks(usernames, chunkSize)) { await new Promise((resolve, reject) => {				queryData.ususers = chunk.join('|');				this.postRequest(queryData, processUser, 'users')					.then(data => { Object.assign(responses, data); resolve; })					.catch(error => { reject(new Error(`Failed to fetch exact blocks data: ${error.message}`)); });			});		}

return responses; }

async hideBots { let primary, secondary, index;

if (mw.config.get('wgRelevantPageName') === 'Special:Log') { primary = "ul.mw-logevent-loglines li"; secondary = "a"; index = 1; } else if (mw.config.get('wgAction') === 'history') { primary = "ul.mw-contributions-list li[data-mw-revid]"; secondary = "span.history-user a"; index = 0; } else { return; }		const users = {}; const entries = document.querySelectorAll(primary); entries.forEach(function(entry) {			const allLinks = entry.querySelectorAll(secondary);			if (allLinks.length >= index + 1) {				const secondLink = allLinks[index];				const hrefValue = secondLink.getAttribute('href');				if (hrefValue.startsWith('/wiki/User:')) {					let userName = hrefValue.substring('/wiki/User:'.length);					userName = userName.replace(/_/g, ' ')					if (!users[userName]) {						users[userName] = [];					}					users[userName].push(entry);				}			}		}); const bots = await this.usersQueries(Object.keys(users)); Object.entries(users).forEach(([user, log]) => {			if (bots[user]) {				log.forEach(li => { if (li.style.display === "none") { li.style.display = ""; } else { li.style.display = "none"; }				});			}		});	} }

mw.loader.using(['mediawiki.util'], function {	if (mw.config.get('wgAction') === 'history' || mw.config.get('wgRelevantPageName') === 'Special:Log') {		mw.util.addPortletLink('p-tb', '#', 'Hide bots', 'ca-hide-bots');		$("#ca-hide-bots").click(function(event) { event.preventDefault; const hb = new HideBots($, mw); hb.hideBots; });	} });