Community Central
Community Central
No edit summary
No edit summary
Line 118: Line 118:
 
cab.globalNavLink = function(title, url, args) { // Creates a GlobalNavButtons object for an external link
 
cab.globalNavLink = function(title, url, args) { // Creates a GlobalNavButtons object for an external link
 
args = {
 
args = {
p: args.p || undefined,
+
p: args.p || undefined, // child, its parent
m: args.m || false,
+
m: args.m || false, // main, its id
i: (args.i || {}).outerHTML || args.i || undefined
+
i: (args.i || {}).outerHTML || args.i || undefined // icon
 
};
 
};
 
return {
 
return {
 
text: title,
 
text: title,
 
url: url,
 
url: url,
isMain: args.m ? true : false,
+
isMain: !!args.m,
 
whoIsMain: args.m ? false : args.p,
 
whoIsMain: args.m ? false : args.p,
 
shortName: args.m ? args.m : title,
 
shortName: args.m ? args.m : title,
Line 212: Line 212:
 
'PageReport': cab.wg.wgArticleId > 0,
 
'PageReport': cab.wg.wgArticleId > 0,
 
'Rollback/code': 1,
 
'Rollback/code': 1,
  +
'TopHiddenCategories': 1,
   
 
// Admin
 
// Admin

Revision as of 20:42, 18 May 2022

// Caburum's global JS v3

window.dev = window.dev || {};
window.caburum = { // Declare static stuff, extended in the main JS
	wg: mw.config.get([
		'isGamepedia',
		'profileUserId',
		'skin',
		'wgArticleId',
		'wgCanonicalSpecialPageName',
		'wgCityId',
		'wgContentLanguage',
		'wgNamespaceIds',
		'wgNamespaceNumber',
		'wgPageName',
		'wgScriptPath',
		'wgTitle',
		'wgUserGroups',
		'wgUserName'
	]),
	init: function() { // Runs main JS
		if (mw.util.getParamValue('useglobaljs') || mw.util.getParamValue('usecabjs')) return this.log('Did not execute global.js from Community Central, disabled');
		this.main(this, window.mediaWiki, window.jQuery);
	},
	log: function() { // Formatted console.log
		console.log.apply(null, Array.prototype.concat('%c[CABURUM]', 'color: #00D6D6; background-color: #111;', Array.prototype.slice.call(arguments)));
	},
	scripts: []
};

window.caburum.main = function(cab, mw, $) {
	if (cab.mainJSLoaded) return; // Already loaded
	cab.mainJSLoaded = true;

	// Shortcuts
	cab.wg.isBot = /bot/i.test(cab.wg.wgUserName) || cab.wg.wgUserGroups.includes('bot') || !!mw.util.getParamValue('bot');
	cab.wg.isCmod = /sysop|content-moderator/.test(cab.wg.wgUserGroups.join('|'));
	cab.wg.isDmod = /sysop|threadmoderator/.test(cab.wg.wgUserGroups.join('|'));
	cab.wg.wgSpecial = cab.wg.wgCanonicalSpecialPageName;

	// Remove tracking
	if ((uri = new mw.Uri()).query.so) {
		delete uri.query.so;
		history.replaceState(null, '', uri.toString());
	}

	// Script config
	$.extend(/* deep copy = */ true, window, {
		AjaxRename: { // [[w:c:dev:AjaxRename]]
			check: {
				leaveredirect: false,
				watch: false,
				movetalk: true
			},
			renameReasons: {
				'Normal': {
					'Misnamed': 'Misnamed',
					'Better name': 'Better name',
					'Fixing capitalization': 'Fixing capitalization'
				},
				'Other': {
					'Page does not belong in namespace': 'Page does not belong in namespace',
				}
			}
		},
		andrewds1021: {
			view_notifications_users: { // [[w:c:dev:ViewNotificationsUsers]]
				all_types: true,
				content: 'name'
			},
			ignore_notifications: { // [[w:c:dev:IgnoreNotifications]]
				ignore_errors: true,
				filters: [
					{ types: 'discussion-upvote' },
					// { wiki_ids: [], types: 'announcement-target' }
				]
			}
		},
		AutoCreateUserPagesConfig: { // [[w:c:dev:MediaWiki:AutoCreateUserPages.js]]
			content: {
				2: cab.wg.isGamepedia ?
					'{{:gphelp::User:{{subst:' + 'PAGENAME' + '}}}}' : // Temp GP fix
					(cab.wg.isBot ?
						'{{raw:w::User:{{subst:' + 'PAGENAME' + '}}}}' // Bot CC userpage
						: '{{raw:w::User:{{subst:' + 'PAGENAME' + '}}/Profile' + ((cab.wg.wgUserName === 'Caburum' && [ 'fr' ].includes(cab.wg.wgContentLanguage)) ? cab.wg.wgContentLanguage : '') + '}}' // User template
					),
				3: false,
				1202: false
			},
			summary: 'Automated user page creation'
		},
		dev: {
			i18n: {overrides: { // i18n overrides
				Rollback: {
					summary: 'Reverted edits by [[Special:Contributions/$1|$1]] ([[User talk:$1|talk]]) to last version by $2'
				}
			}}
		},
		fdButtons: [ // [[w:c:dev:FastDelete]]
			{ summary: 'Housekeeping', label: 'HK' },
			{ summary: 'Vandalism', label: 'V' },
			{ summary: 'Spam', label: 'S' },
			{ summary: 'Duplicate', label: 'Dp' }
		],
		globalNavButtons: [], // [[w:c:dev:GlobalNavButtons]], populated below
		lastEdited: { // [[w:c:dev:LastEdited]]
			avatar: false,
			diffModal: false // Use [[w:c:dev:QuickDiff]] instead
		},
		MessageBlock: { // [[w:c:dev:MessageBlock]]
			title: 'Blocked',
			message: 'You have received a $2 block for the reason: \'$1\'. Unless otherwise stated, you may appeal your block on my message wall at Community Central.',
			autocheck: true
		}
	});

	// [[w:c:dev:GlobalNavButtons]]
	cab.globalNavLink = function(title, url, args) { // Creates a GlobalNavButtons object for an external link
		args = {
			p: args.p || undefined, // child, its parent
			m: args.m || false, // main, its id
			i: (args.i || {}).outerHTML || args.i || undefined // icon
		};
		return {
			text: title,
			url: url,
			isMain: !!args.m,
			whoIsMain: args.m ? false : args.p,
			shortName: args.m ? args.m : title,
			icon: args.i
		};
	};

	cab.globalNavPage = function(title, page, args) { // Creates a GlobalNavButtons object for an internal page
		return cab.globalNavLink(title, mw.util.getUrl(page) + (args.r ? '?' + args.r : ''), args);
	};

	mw.hook('dev.wds').add(function(wds) {
		window.globalNavButtons.push(
			/* Patrolling */
			cab.globalNavPage('Recent Changes', 'Special:RecentChanges', {m: 'RC', i: wds.icon('activity-small')}),
			cab.globalNavPage('New files', 'Special:NewFiles', {p: 'RC'}),
			cab.globalNavPage('New pages', 'Special:NewPages', {p: 'RC'}),
			cab.globalNavPage('New messages', 'Special:SocialActivity', {p: 'RC', r: 'containerTypes=WALL'}),
			cab.globalNavPage('New comments', 'Special:SocialActivity', {p: 'RC', r: 'containerTypes=ARTICLE_COMMENT'}),
			(cab.wg.isCmod || cab.wg.isDmod) && cab.globalNavLink('Reported posts', cab.wg.wgScriptPath + '/f/reported', {p: 'RC'}),
			/* Social */
			cab.globalNavLink('Discuss', cab.wg.wgScriptPath + '/f', {m: false, p: false, i: wds.icon('discussions-small')}),
			/* MediaWiki */
			cab.globalNavPage('MediaWiki', 'Special:AllPages/MediaWiki:', {m: 'MW', i: wds.icon('controls-small')}),
			cab.globalNavPage('Common CSS', 'MediaWiki:Common.css', {p: 'MW'}),
			cab.globalNavPage('Common JavaScript', 'MediaWiki:Common.js', {p: 'MW'}),
			cab.globalNavPage('FandomDesktop CSS', 'MediaWiki:Fandomdesktop.css', {p: 'MW'}),
			cab.globalNavPage('FandomDesktop JavaScript', 'MediaWiki:Fandomdesktop.js', {p: 'MW'}),
			cab.globalNavPage('Version', 'Special:Version', {p: 'MW'}),
			cab.globalNavPage('ImportJS', 'MediaWiki:ImportJS', {p: 'MW'}),
			cab.globalNavPage('Wiki navigation', 'MediaWiki:Wiki-navigation', {p: 'MW'}),
			cab.wg.wgNamespaceIds.gadget && cab.globalNavPage('Gadgets', 'Special:Gadgets', {p: 'MW'}),
			cab.globalNavPage('Oasis CSS', 'MediaWiki:Wikia.css', {p: 'MW'}),
			cab.globalNavPage('Oasis JS', 'MediaWiki:Wikia.js', {p: 'MW'}),
			/* Special pages */ // @todo: make subitem of MW
			cab.globalNavPage('Special pages', 'Special:SpecialPages', {m: 'SP', i: wds.icon('page-list-small')}),
			/* Personal */
			cab.globalNavPage('Me', 'Special:MyPage', {m: 'ME', i: wds.icon('user-small')}),
			cab.globalNavPage('Sandbox', 'Special:MyPage/Sandbox', {p: 'ME'}),
			cab.globalNavPage('Subpages', 'Special:PrefixIndex/User:' + cab.wg.wgUserName + '/', {p: 'ME'}),
			cab.globalNavPage('Local JavaScript', 'Special:MyPage/common.js', {p: 'ME'}),
			cab.globalNavPage('Local CSS', 'Special:MyPage/common.css', {p: 'ME'}),
			cab.globalNavLink('Global JavaScript', 'https://community.fandom.com/wiki/Special:MyPage/global.js', {p: 'ME'}),
			cab.globalNavLink('Global CSS', 'https://community.fandom.com/wiki/Special:MyPage/global.css', {p: 'ME'}),
			/* Wikis */
			cab.globalNavLink('Wikis', 'https://caburum.fandom.com/wiki/User:Caburum/RecentChanges', {m: 'W', i: wds.icon('wikis-small')}),
			cab.globalNavLink('Among Us Wiki', 'https://among-us.fandom.com/wiki/', {p: 'W'}),
			cab.globalNavLink('Community Central', 'https://community.fandom.com/wiki/', {p: 'W'}),
			cab.globalNavLink('Dev Wiki', 'https://dev.fandom.com/wiki/', {p: 'W'}),
			cab.globalNavLink('Discord Wiki', 'https://discord.fandom.com/wiki/', {p: 'W'}),
			cab.globalNavLink('Test Wiki', 'https://caburum.fandom.com/wiki/', {p: 'W'}),
			cab.globalNavLink('Customize Your Wiki', 'https://custom.fandom.com/wiki/', {p: 'W'})
		);
		mw.config.get('wgWikiaPageActions').forEach(function(item) {
			if (item.id.startsWith('special:')) window.globalNavButtons.push(cab.globalNavLink(item.caption, item.href, {p: 'SP'}));
		});
	});

	// Execute local JS only if main JS ran
	if (mw.util.getParamValue('uselocaljs')) {
		cab.log('Did not execute common.js, disabled');
	} else {
		mw.hook('caburum.runLocalJS').fire(cab);
	}

	// Scripts to import per source, dependent on user groups
	// 1 for always, 2 for bot, see below for more advanced options
	cab.scripts.push(
		{ // Dev Wiki
			prefix: 'u:dev:MediaWiki:',
			scripts: {
				// Libraries
				'WDSIcons/code': 1,

				// Maintenance
				'AjaxBatchDelete': cab.wg.isCmod,
				'AjaxRename/code': 1,
				'AnchoredRollback/code': 1,
				'BulkVideoUpload': 2,
				'FastDelete/code': cab.wg.isCmod,
				'ListFiles/code': ['Listfiles', 'Unusedimages', 'Uncategorizedimages'].includes(cab.wg.wgSpecial),
				'MassCategorization/code': 2,
				'MassEdit/code': 2,
				'MassNullEdit/code': 1,
				'MassRename/code': 2,
				'PageReport': cab.wg.wgArticleId > 0,
				'Rollback/code': 1,
				'TopHiddenCategories': 1,

				// Admin
				// 'AjaxBlock/code': ['sysop'], // Conflicts with MessageBlock
				'MessageBlock/code': cab.wg.wgSpecial === 'Block' ? 'sysop' : false,
				// 'SOAPReport': cab.wg.wgSpecial === 'Contributions',
				'WHAM/code.2': cab.wg.wgSpecial === 'Contributions' ? ['sysop', 'content-moderator', 'threadmoderator', 'rollback'] : false,

				// Tools
				'CopyTitle': 1,
				'DiscussionTemplates': { ns: 1200 },
				'LastEdited/code': cab.wg.wgArticleId > 0,
				'MinimalTestModeAlert': mw.config.get('wgIsTestModeEnabled'),
				'QuickDiff/code': 1,
				'QuickPurge': 1,
				'UploadMultipleFiles': cab.wg.wgSpecial === 'Upload',

				// Personal
				'AutoCreateUserPages': 1,
				'DisplayTimer/code': 1,
				'GlobalNavButtons': 1,

				// Social
				'IgnoreNotifications': 1,
				'UserAndIPTools': !!cab.wg.profileUserId,
			}
		},
		{ // Caburum Testing Wiki
			prefix: 'u:caburum:MediaWiki:',
			scripts: {
				'BadgeStatusUpdater': document.getElementsByClassName('UserProfileAchievementsModule').length > 0,
				'RecentWikiActivityDiff': 1,
				'ThemeSwitcher': 1
			}
		}
	);

	// Load scripts based on criteria
	var articles = [];
	function processScript(script, d) {
		var g = [];
		if (Array.isArray(d)) { // array of groups
			g = d;
		} else if (typeof d === 'string') { // single group
			g = [d];
		} else if (typeof d === 'object' && d !== null) { // advanced config
			g = g.concat(d.groups || d.group || true);
			if ((d.skins || d.skin) && ![].concat(d.skins || d.skin).includes(cab.wg.skin)) return;
			if ((d.wikis || d.wiki) && ![].concat(d.wikis || d.wiki).includes(cab.wg.wgCityId)) return;
			if (d.ns && ![].concat(d.ns).includes(cab.wg.wgNamespaceNumber)) return;
		} else if (d === 2) { // bot
			g = [cab.wg.isBot];
		} else if (Boolean(d)) { // truthy value
			g = [true];
		} else return;

		// If all other checks pass, then check groups
		if (g[0] === true || g.filter(function(group) { return cab.wg.wgUserGroups.includes(group) }).length > 0) {
			articles.push(script);
		}
	}
	
	cab.scripts.forEach(function(s) {
		if (!s) return; // If falsy, do nothing
		if (typeof s === 'object') { // Group of scripts from a single source
			$.each(s.scripts, function(script, d) {
				processScript(s.prefix + script + '.js', d);
			});
		} else { // Singular script
			processScript(s, true);
		}
	});

	importArticles({
		type: 'script',
		articles: articles
	});

	cab.log('Executed global.js from Community Central');
};

mw.loader.using('mediawiki.util', function() {
	$(window.caburum.init.bind(window.caburum));
});