User:Thundercraft5/global.js

// /* jshint esversion: 3, forin: true, immed: true, indent: 4, latedef: false, newcap: true, noarg: true, undef: true, undef: true, unused: true, browser: true, jquery: true, onevar: true, eqeqeq: true, multistr: true, moz: true, maxerr: 999999 // ^ Mediawiki's crappy JS parser won't swallow es6 so I'm forced to use archaic syntax and other bad stuff /* $(document.body).on('.custom-side-tool', {	mouseenter {		$(' ', { class: 'wds-tooltip is-right', css: { left: ($(this).offset.left + 50) + 'px', top: ($(this).offset.top - $(document).scrollTop + 20) + 'px', },			text: 'Test', appendTo: 'body', });	},

mouseleave { $('.wds-tooltip').remove; }, });

/*** Remove Tracking data ***/ var localStorageBlacklist = [ "wkch_val_recommendations_blacklist", /^silver/i, /^optimizely_data\${2}/i, ];

var cookieBlacklist = [ "wikia_beacon_id", /^sailthru/i, "Geo", "ss_galactus_enabled", /^pv_number/i, /^permutive/i, /^tracking/i, /\bbeacon\b/i, ]; var cookies = new Map(document.cookie.split(/\s*;\s*/)		.map(function(entry) { return entry.split("="); })	);

cookies.forEach(function(_, k) {	if (cookieBlacklist.find(function(v) { return v instanceof RegExp ? k.match(v) : k === v })) 		document.cookie = k + "=; expires=" + new Date.toISOString + "; path=/;"; });

Object.keys(localStorage).forEach(function(k) {		if (localStorageBlacklist.find(function(v) { return v instanceof RegExp ? k.match(v) : k === v })) 		localStorage.removeItem(k); });

window.indexedDB.deleteDatabase('silver-surfer');

$('*').attr({ 	'data-tracking': null, 	'data-tracking-label': null, });

/* global mw, loadModules, importArticles */ // Force FandomDesktop mw.loader.using('mediawiki.api', function {	if (mw.config.get('skin') !== 'fandomdesktop' && !mw.util.getParamValue('useskin')) {		new mw.Api.saveOption('skin', 'fandomdesktop').then(console.log, console.warn);		console.warn('[Skin Force] Setting skin back to fandom desktop');		window.location.reload;	}		});

window.GlobalJS = { wg: mw.config.get([		'wgAction',		'wgPageName',		'wgCodeEditorCurrentLanguage',		'wgNamespaceNumber',		'profileUserName',		'isGamepedia',		'wgUserGroups',	]), createScriptsList: function { var wgPageName = this.wg.wgPageName; var userGroups = this.wg.wgUserGroups.join; var canBlock = /sysop|bureaucrat|staff|soap|util|helper|wiki-representative|wiki-specialist|global-discussions-moderator/.test(userGroups); var canProtect = /sysop|staff|soap|util|helper|wiki-representative|wiki-specialist|content-moderator|vanguard/.test(userGroups); var canDelete = /sysop|staff|soap|util|helper|wiki-representative|wiki-specialist|content-moderator/.test(userGroups); var canRollback = /sysop|staff|soap|util|helper|wiki-representative|wiki-specialist|content-moderator|rollback/.test(userGroups); var canChangeRights = /sysop|bureaucrat|staff|soap|util|soap|helper|wiki-representative/.test(userGroups); var canMassRename = /sysop|content-moderator|bot|bot-global|staff|helper|wiki-representative|global-discussions-moderator|content-volunteer|wiki-specialist|soap/.test(userGroups); var canChangeContentModel = /sysop|content-moderator|staff|helper|wiki-specialist|wiki-representative|soap|vanguard/.test(userGroups); var isUserRelatedPage = (wgPageName.startsWith('Special:Contributions') 			|| wgPageName.startsWith('Special:UserProfileActivity') 			|| wgPageName.startsWith('Special:SpecialPages')			|| wgPageName.startsWith('Special:DeletedContributions')			|| [2, 3, 1200].includes(this.wg.wgNamespaceNumber)			|| this.wg.wgNamespaceNumber === 500 && !wgPageName.includes('/')		);

var scripts = { editor: { 'Standard_Edit_Summary/code.js': 1, },			wikiEditor: { 'AjaxEditPreview.js': 1, 'DecodeURI/code.js': 1, 'LivePreviewWarnings.js': 1, },			codeEditor: {}, view: { // Ajax Scripts 'AjaxRC.js': 1, // 'AjaxRedirect/code.js', 'AjaxUndo/code.js': 1, 'AjaxAbuseLog.js': 1,

// Mass Scripts 'MassRollback.js': wgPageName.startsWith('Special:Contributions'),

// Other Scripts 'FastOldImageDelete/code.js': 1, 'MultipleFileDelete/code.js': canDelete, 'FileUsageAuto-update/code.js': 1, 'RevealAnonIP/usercode.js': 1, 'AllPagesHideRedirect/code.js': wgPageName.startsWith('Special:AllPages'), 'RedirectManagement/code.js': wgPageName === 'Special:DoubleRedirects' || wgPageName === 'Special:BrokenRedirects', 'WHAM/code.2.js': (wgPageName.startsWith('Special:Contributions') || wgPageName.startsWith('Special:UserProfileActivity')) && canDelete, 'MoreDropdown/code.js': 1, 'Nuke/code.js': canDelete && isUserRelatedPage || wgPageName.startsWith('Special:BlankPage') && mw.util.getParamValue('blankspecial') === 'nuke', 'Reconstitution.js': canDelete && isUserRelatedPage || wgPageName.startsWith('Special:BlankPage') && mw.util.getParamValue('blankspecial') === 'reconst', 'RevisionDelete.js': canDelete && this.wg.wgAction === 'history', 'PowerDelete.js': canDelete, 'UserAndIPTools.js': !!this.wg.profileUserName, 'DeleteTalkpage.js': this.wg.wgAction === 'delete' && canDelete, 'BlockLookup.js': 1, 'Discussions Delete All/code.js': isUserRelatedPage, 'MultiUpload.js': wgPageName === 'Special:Upload', 'PageReport.js': 1, },			any: { // Link click scripts 'Rollback/code.js': !canRollback, 'QuickDiff/code.js': 1, 'AnchoredRollback/code.js': canRollback, 'AutoCreateUserPages.js': 1, 'AjaxRename/ucp.js': 1, 'AjaxDelete/code.js': canDelete, 'QuickPurge.js': 1, 'AjaxPatrol/code.js': canDelete, 'AjaxContentModel.js': canChangeContentModel, 'AjaxBlock/code.js': canBlock,

// Other 'GlobalNavButtons.js': 1, 'CodeLinksDropdown.js': 1, 'CollapseGlobalNavButton.js': 1, 'UCXSearchBar.js': 1, 'ThemeToggler.js': 1, 'OldFandomColors.js': 1, 'MassEdit/code.js': 1, 'PortableCSSPad/code.js': 1, 'CopyTitle.js': 1, 'CategorizedNotifications.js': 1, },			toolbar: { // Toolbar scripts 'MassProtect/code.js': canProtect, 'MassRename/code.js': canMassRename, 'MassRedirect/code.1.js': canMassRename, 'MassBlock/code.js': canBlock, 'AjaxBatchUndelete.js': canDelete, 'AjaxBatchDelete.js': canDelete, 'MassNullEdit/code.js': 1, 'MassCategorization/code.js': 1, 'MassUserRights/code.js': canChangeRights, 'DupeArgs.js': 1, 'PortableListUsers.js': 1, 'AjaxUserRights.js': canChangeRights, }		};

this.toolbarScripts = scripts.toolbar;

return this.scripts = Object.entries(scripts).map(function(d) {			var group = d[0];			var items = d[1];			return Object.entries(items).filter(function(d) { return scripts[group] && d[1] && group !== 'toolbar'; }).map(function(d) { return d[0] });		}).flat.map(function(v) { return 'u:dev:MediaWiki:' + v }); },

scriptConfigs: { // Batch Delete batchDelete: { prefixed: true, Delay: 5, },		// Batch Undelete batchUnDelete: { prefixed: true, Delay: 5, },

// Mass Edit MassEditConfig: { interval: 10, placement: { element: "toolbar", type: "append", },		},

// MassCategorization MassCategorization: { delay: 1, },

'dev.editSummaries': { // STD summaries css: '#stdSummaries {}', select: [ '(click to browse)', 'Quick', [ 'Formatting', 'Removing vandalism', 'Fixing error(s)', 'Corrected spelling/grammar', 'Corrected formatting/layout' ],				'General', [ 'Added/removed/corrected link(s)', 'Cleanup', 'HTML/Source mode cleanup', 'Expanded', 'Grammar', 'Punctuation', 'Redlink removal', 'Refactoring', 'Re-ordering/re-organizing', 'Revised', 'Spelling correction', 'Style/layout', 'Netural point of view (NPOV)', 'Tidying', 'Updating', 'Wikifying', 'Added/removed/corrected template(s)', 'Adding new features', 'Testing new features', 'Making source code look better', ],				'Templates', [ 'Parser function modification', 'Fixing template bugs', 'Creating documentation subpage', 'Magic word correction/modification', ],				'Advanced code', [ 'Logic cleanup/Optimiziation', 'Function cleanup', 'Adding comments', 'Fixing errors/bugs', 'Removing deprecated features', 'Minor changes', ],				'Removal/Reversion', [ 'Reverted Spam/Vandalism', 'Reverted test edit', 'Reverted Copy vio\'' ],				'Categories', [ 'Added category(ies)', 'Alphabetised category(ies)', 'Creating Category page', 'Modified category(ies)', ],			],		},		'dev.i18n.overrides.AjaxRC': { 'ajaxrc-refresh-text': 'Auto Refresh', 'ajaxrc-refresh-hover': 'Enable automatically refreshing of this page', },		// Rollback 'dev.i18n.overrides.Rollback': { summary: "Reverted edits by $1 (talk) to last version by $2 (script)", },		AjaxContentModel: { appendToContentMenu: true, },		// AjaxRC ajax: { prefixed: true, Refresh: 30000, Pages: [ "RecentChanges", "WikiActivity", "Watchlist", "Log", "Contributions", "AbuseLog", "SocialActivity", "NewFiles", "BlockList", ].concat([				"abusefilter",				"block",				"contentmodel",				"delete",				"import",				"merge",				"move",				"create",				"patrol",				"protect",				"tag",				"managetags",				"templateclassification",				"timedmediahandler",				"upload",				"newusers",				"rights"			].map(function(v) { return "Log/" + v })) .map(function(v) { return "Special:" + v }), },		//MassBlock massBlock: { prefixed: true, Delay: 5, },		// AjaxBlock AjaxBlock: { blockReasons: { 'General': { 'General Disruptive Behavior': 'General Disruptive Behavior', 'Vandalism': 'Vandalism', 'Disruptive Editing': 'Disruptive Editing', 'Inserting False Information': 'Inserting False Information', 'Spamming Nonsense Comments/Posts': 'Spamming Nonsense Comments/Posts', 'Immature/Innapropriate Behavior or Conduct': 'Immature/Innapropriate Behavior or Conduct', 'Long-Term Abuse': 'Long-Term Abuse', 'Violation of FANDOM Terms of Use': 'Violation of FANDOM ToU', },				'Editing': { 'Edit Warring': 'Edit Warring', 'Creating Nonsense/Vandalism Articles': 'Creating Spam Articles', 'Inserting nonsense/gibberish into pages': 'Inserting nonsense/gibberish into pages', 'Removing Content From Pages': 'Removing Content form Pages', },

'Accounts': { 'Open Proxy/VPN': "Open Proxy/VPN", 'Vandalism-Only Account': 'VoA Account', 'Disruption-Only Account': "Disruption-Only Account", 'Unacceptable/Innapropriate Username': 'Unacceptable/Innapropriate Username', 'Clearly not here to build an Encyclopedia': 'Clearly not here to build an Encyclopedia', 'Abusing Multiple Accounts (Sockpuppetry)': "Sockpuppety", },

'Spam': { 'Spam/Advertising Only account': 'Spam/Advertising Only account', 'Spam/Advertising': 'Spam/Advertising', 'Spambot': 'Spambot', },

'Comments/Posts': { 'Intimidating/Harrasing Comments/Posts': 'Intimidating/Harrasing Comments/Posts', 'Swearing In Comments/Discussions': 'Swearing In Comments/Discussions', 'Discussing Controversial Topics': 'Discussing Controversial Topics', 'Innapropriate Behavior/Comments': 'Innapropriate Behavior/Comments', },

'Behavior': { 'Personal Attacks': 'Personal Attacks', 'Intimidating Behavior/Harassment': 'Intimidating Behavior/Harassment', 'Spreading False Rumors/Information': 'Spreading False Rumors/Information', 'Shouting': 'Shouting', },			},

expiryTimes: { '24 hours': '1 day', '3 days': '3 days', '1 week': '1 week', '2 weeks': '2 weeks', '3 weeks': '3 weeks', '1 month': '1 month', '6 weeks': '6 weeks', '2 months': '2 months', '3 months': '3 months', '4 months': '4 months', '6 months': '6 months', '9 months': '9 months', '1 year': '1 year', '18 months': '18 months', '3 years': '3 years', 'infinite': 'all of eternity', },

check: { talk: true, autoBlock: true, override: true, noCreate: true, rangeBlock: false, refAbuseLog: false, },

extras: { rangeBlock: true, refAbuseLog: true, },		},		// AjaxDelete AjaxDelete: {

deleteReasons: { 'Spam/Vandalism': 'Spam/Vandalism', 'Marked for Devarion': 'Marked for Devarion', 'Empty Article': 'Empty', 'Author request': 'Author request', 'Irrelevant to The Wiki': 'Irrelevant', 'Housekeeping': 'Housekeeping', 'Spam/Vandalism Article': 'Spam/Vandalism Article', 'Deprecated/Unused': 'Deprecated/Unused', 'Personal Attack article': 'Personal Attack article]', 'Disinformation/Hoax': 'Disinformation/Hoax', 'Broken Redirect': 'Broken Redirect', 'Unused Redirect': 'Unused redirect', 'Redirect left from pagemove': 'Page Move redirect', },

imageDeleteReasons: { 'Offensive Image': 'Offensive', 'Inappropriate Image': 'Inappropriate', 'Harassment-Only image': 'Harassment', 'Housekeeping': 'Housekeeping', 'Copyright infringement': 'Copyright', 'Author request': 'Author request', 'Duplicate/Superseded File': 'Duplicate/Superseded', 'Improper Image format': 'Improper Format', 'Spam/Vandalism': 'Spam/Vandalism', },

autoCheckWatch: true, noUndelete: false, reload: false, },

//Nuke nuke: { prefixed: true, Delay: 5, },		//WHAM WHAM: { prefixed: true,

BlockReason: "vandalism", Delay: 5, BlockDuration: '3 months', DeleteReason: "devaring spam/vandalism", },

//AutoRenamePages PRAoptions: { editSummary: 'Updating page links (automatic)' },		// Mass Rename Pages massRename: { prefixed: true, Delay: 25, },		//MassProtect massProtect: { prefixed: true, Delay: 5, },		//MassUndelete batchUndelete: { prefixed: true, Delay: 5, },

LIRoptions: { bottomMessage: '', editSummary: 'Updating file links (automatic)', singleButtonText: 'Rename and update', queueButtonText: 'Add to queue', delay: 10 },		// Global userpage AutoCreateUserPagesConfig: { content:{ // HACK: Use wikitext to check if wiki is gamepedia 2:, 				3:,			},			summary: 'Creating userpage(es)', completeCallback: function(page) { /*new mw.Api.postWithEditToken({					title: page,					action: "protect",					reason: "Protecting Userpage(s)",					protections: Object.entries({ edit: page.includes('talk') ? 'all' : "sysop", move: "sysop", }).map(function(d) { return d[0] + '=' + d[1] }).join('|'),				}).then(console.log, console.warn);*/ },		},

// Mass Null Edit Delay nullEdit: { prefixed: true, Delay: 25, },

// AnchoredRollback anchoredRollback: { prefixed: true, Bot: true, },

//================================		// GlobalNavButtons //=================================		globalNavButtons: [ //===================================		 // Community Centeral //===================================		 // Main Button {			text: 'Community', url: 'https://community.fandom.com', isMain: true, whoIsMain: false, shortName: 'C'		 }, // New users Log (Anti-spam) {			text: 'New users log', url: 'https://community.fandom.com/wiki/Special:Log/newusers', isMain: false, whoIsMain: 'C', shortName: 'NU' },		 // User avatar Log (Anti-spam) {			text: 'User Avatar Log log', url: 'https://community.fandom.com/wiki/Special:Log/useravatar', isMain: false, whoIsMain: 'C', shortName: 'AVL' },		 // Recent Changes {			text: 'Recent Activity log', url: 'https://community.fandom.com/wiki/Special:RecentChanges?hidelogs=1&namespace=2&days=1', isMain: false, whoIsMain: 'C', shortName: 'RA' },		 // Abuse Log (Anti-spam) {			text: 'Abuse Log', url: 'https://community.fandom.com/wiki/Special:AbuseLog?limit=500', isMain: false, whoIsMain: 'C', shortName: 'AL' },		 // Wikis Log {			text: 'Wikis log', url: 'https://community.fandom.com/wiki/Special:Newwikis', isMain: false, whoIsMain: 'C', shortName: 'WL' },		 //===================================		  // SOAP (for Reports) //==================================		 // Main Button {			text: 'SOAP', url: 'https://soap.fandom.com', isMain: true, whoIsMain: false, shortName: 'S'		 }, // Profiles {			text: 'Profiles', url: 'https://soap.fandom.com/wiki/Report:User_profile_headers', isMain: false, whoIsMain: 'S', shortName: 'R:P' },		 // Spam {			text: 'Spam', url: 'https://soap.fandom.com/wiki/Report:Spam', isMain: false, whoIsMain: 'S', shortName: 'R:S' },		 {			text: 'Vandalism', url: 'https://soap.fandom.com/wiki/Report:Vandalism', isMain: false, whoIsMain: 'S', shortName: 'R:V' },		 {			text: 'Wiki', url: 'https://soap.fandom.com/wiki/Report:Wiki', isMain: false, whoIsMain: 'S', shortName: 'R:W' },		 {			text: 'Biglist', url: 'https://soap.fandom.com/wiki/Report:Spam/Biglist', isMain: false, whoIsMain: 'S', shortName: 'R:BL' },		 //=========================================		  // Wikis (Personal) //========================================		 // Main Button {			text: 'Wikis', url: '#', isMain: true, whoIsMain: false, shortName: 'W'		 }, // Hypixel SkyBlock Wiki {			text: 'Hypixel SkyBlock Wiki', url: 'https://hypixel-skyblock.fandom.com/wiki/Special:RecentChanges', isMain: false, whoIsMain: 'W', shortName: 'HSW' },		 // Minecraft Wiki {			text: 'Minecraft', url: 'https://minecraft.fandom.com/wiki/Special:RecentChanges', isMain: false, whoIsMain: 'W', shortName: 'MCW' },		 // Hypixel SkyBlock Korean Wiki {			text: 'Hypixel SkyBlock Korean Wiki', url: 'https://hypixel-skyblock.fandom.com/ko/wiki/Special:RecentChanges', isMain: false, whoIsMain: 'W', shortName: 'HSKW' },		 // Community Centeral {			text: 'Community Centeral', url: 'https://community.fandom.com/wiki/Special:RecentChanges', isMain: false, whoIsMain: 'W', shortName: 'CC' },		 //=========================================		  // Hypixel SkyBlock wiki Stuff //========================================		 // Main Button {			text: 'HSW', url: 'https://hypixel-skyblock.fandom.com/wiki/', isMain: true, whoIsMain: false, shortName: 'HSWDR' },		 // Recent Changes {			text: 'Recent Changes', url: 'https://hypixel-skyblock.fandom.com/wiki/Special:RecentChanges', isMain: false, whoIsMain: 'HSWDR', shortName: 'HSWRC' },		 // Logs {			text: 'All Logs', url: 'https://hypixel-skyblock.fandom.com/wiki/Special:Log', isMain: false, whoIsMain: 'HSWDR', shortName: 'HSWL' },		 // Block List {			text: 'Block List', url: 'https://hypixel-skyblock.fandom.com/wiki/Special:BlockList', isMain: false, whoIsMain: 'HSWDR', shortName: 'HSWBL' },		 // Abuse Log {			text: 'Abuse Log', url: 'https://hypixel-skyblock.fandom.com/wiki/Special:AbuseLog', isMain: false, whoIsMain: 'HSWDR', shortName: 'HSWAL' },		],

//Ignore all announcements announcementsIgnore: { option: 'opt-out-all', exceptWikiIds: [ 177,				2011605,			],		},	},	_names: [], setupConfigs: function { const configs = this.scriptConfigs; for (var name in configs) { var config = configs[name]; if (config.prefixed) { delete config.prefixed; for (var subname in config) { var value = config[subname]; window[name + subname] = value; this._names.push(name + subname); }			} else if (name.includes('.')) { var split = name.split('.'); var segment; var val = window;

while ((segment = split.shift)) { if (split.length === 0) break;

if (!val[segment]) val[segment] = {}; val = val[segment]; }

val[segment] = config; this._names.push(name); } else { window[name] = config; this._names.push(name); }		}	},	doImport: function { window.importArticles({			type: "script",			articles: this.createScriptsList,		}); },	start: function { this.setupConfigs;

if (this.wg.isGamepedia) { window.importStylesheetPage('User:Thundercraft5/global.css', 'community'); window.importScriptPage('User:Thundercraft5/globalGamepedia.js', 'community'); $.getScript('https://dev.fandom.com/wiki/MediaWiki:ArticlesAsResources.js?action=raw&ctype=text/javascript').then(function {				this.doImport;				this.addToolbarScripts;			}.bind(this)); } else { this.doImport; this.addToolbarScripts; }	},	addToolbarMutationObserver: function { new MutationObserver(function(mutations) {			if (mutations[0].addedNodes.length) setTimeout(function { $(mutations[0].addedNodes[0]).find('a').click; }, 250);			$('#my-tools-menu .loading').remove;		}).observe($('#my-tools-menu')[0], {			childList: true,		}); },

addToolbarScripts: function { console.log(this.toolbarScripts, this); Object.entries(this.toolbarScripts).filter(function(d) { return d[1] }).forEach(function(d) {			var script = d[0];			var scriptName = script.split(/[./]/).shift;			$('#my-tools-menu').prepend($('', {				html: $('', { class: "custom", text: scriptName, click: function { $.getScript('//dev.fandom.com/index.php?action=raw&ctype=text/javascript&title=MediaWiki:' + script); $(this) .text('') .css({ 								'background': 'url(https://static.wikia.nocookie.net/dev/images/4/42/Loading.gif/revision/latest?cb=20120218000406&format=original) no-repeat center' 							}) .parent .addClass('loading'); },				}),			}));		});

this.addToolbarMutationObserver; }, };

window.GlobalJS.start;

/** * JS subpage loader */ window.ignoreModules = [];

var start = new Date;

var wgAction = mw.config.get('wgAction'), wgPageName = mw.config.get('wgPageName'), wgCodeEditorCurrentLanguage = mw.config.get('wgCodeEditorCurrentLanguage'), wgNamespaceNumber = mw.config.get('wgNamespaceNumber');

var isWikiEditor = ['edit', 'submit'].includes(wgAction) && !wgCodeEditorCurrentLanguage, isView = !['edit', 'submit'].includes(wgAction), isCodeEditor = ['edit', 'submit'].includes(wgAction) && wgCodeEditorCurrentLanguage;

jQuery.Deferred.exceptionHook = function(error, stack) { if (error instanceof Error) { window.console.warn('jQuery.Deferred exception: ' + error.message, error, stack); } };

window.loadModules = function(modules) { var origModules = Array.from(modules || []); modules = modules || []; modules.forEach(function(v, i, arr) {		arr[i] = 'User:Thundercraft5/global.js/' + v.replace(/\.js$/i, '') + '.js';	});

var loadModules = { init: function { this.def = new $.Deferred; for (var key in localStorage) { if (					key.indexOf('loadModules-cache-module-') === 0 					&& (!!origModules.length ? origModules.includes(						'User:Thundercraft5/global.js/' + key.replace('loadModules-cache-module-', '')					) : true)				) { var script = JSON.parse(localStorage.getItem(key)), mName = key.replace('loadModules-cache-module-', ''); this.log('Script "' + mName + '" was found in module cache, executing from cache...'); this.executeScript(script.content, mName, script.id); modules.splice(modules.indexOf('User:Thundercraft5/global.js/' + mName), 1); }			}			if (!modules.join('|')) return this.def.resolve, this.def;

$.ajax({				data: {					action: 'query',					cb: Date.now,					format: 'json',					indexpageids: true,					prop: 'revisions',					rvprop: 'content',					titles: modules.join('|'),				},				dataType: 'jsonp',				error: this.onError.bind(this),				success: this.onSuccess.bind(this),				type: 'GET',				url: 'https://community.fandom.com/api.php'			}).done(this.def.resolve); },		executeScript: function(js, module, id, fullName) { var script = document.createElement('script'); var blob = new Blob(['/*** ' + fullName + " ***/\n\n(async => {\n" + js.replaceAll(/\n?\/\*\s*(jshint|global)([^\0]+?)\*\/\n?|\s*(?<!["'`])\/\/\s*jshint([^\n\/]*?)$/gmi, '') + "\n});"], { type: "text/javascript" });			var blobUrl = URL.createObjectURL(blob);			script.setAttribute('data-module-name', module);			script.src = blobUrl;			script.async = true;			script.class = 'loadModules-Module';			window.loadModules.blobList[module] = {				blobUrl: blobUrl,				blob: blob,				element: script,				name: module,				id: id,				content: js,			};			this.log('Executing script "' + module + '" (module id #' + id + ')');			try {				document.head.append(script);			} catch(e) {				this.warn('Failed to execute module "' + module + '":', e);			}		},		runScripts: function(scripts) {			Object.keys(scripts).forEach(function(k, i, arr) {				this.executeScript(scripts[k].content, k, scripts[k].id, scripts[k].fullName); if (i === arr.length) this.def.resolve; }.bind(this));		},		prepareExecution: function(data) {			var ids = data.query.pageids,				pages = data.query.pages,				o = {};			ids.forEach(function(id) { var currentData = pages[id], title = currentData.title.replace('User:Thundercraft5/global.js/', ''); if (!currentData.revisions) return this.warn('The requested module "' + title + '" does not exist, skipping.'); var content = currentData.revisions[0]["*"]; var obj = o[title] = { content: content, id: id, fullName: title, };				localStorage.setItem('loadModules-cache-module-' + title, JSON.stringify(obj)); }.bind(this));			return o;		},		onError: function(e) {			this.warn('API error in fetching modules:', e);		},		onSuccess: function(data) {			var scripts = this.prepareExecution(data);			this.log('Executing scripts...');			this.runScripts(scripts);		},		logBuilder: function(name, args) {			window.console[name.toLowerCase].apply(null, ["[" + name.toUpperCase + "] loadModules:"].concat(Array.from(args)));		},		warn: function {			this.logBuilder('warn', arguments);		},		log: function {			this.logBuilder('log', arguments);			},	};	loadModules.init;	return loadModules.def; };

window.loadModules.listModulesCache = function { for (var key in localStorage) { if (key.indexOf('loadModules-cache-module-') === 0) { console.log(key, JSON.parse(localStorage.getItem(key))); }	} };

window.loadModules.blobList = {}; window.loadModules.listModules = function { var self = { logBuilder: function(name, args) { window.console[name.toLowerCase].apply(null, ["[" + name.toUpperCase + "] loadModules:"].concat(Array.from(args))); return Array.from(args).join(' '); },		warn: function { return this.logBuilder('warn', arguments); },		log: function { return this.logBuilder('log', arguments); },		init: function { this.def = new $.Deferred; $.ajax({				data: {					action: 'query',					list: 'allpages',					format: 'json',					aplimit: 500,					apnamespace: 2,					apprefix: 'Thundercraft5/global.js/',				},				dataType: 'jsonp',				type: 'GET',				url: 'https://community.fandom.com/api.php'			}).done(function(res) {				if (typeof(res) !== "object") return this.def.reject(this.warn('Failed to get modules:', res));

var arr = []; res.query.allpages.forEach(function(o, i) {					arr[i] = o.title;					});

return this.getData(arr); }.bind(this));

return this.def; },		getData: function(d) { return $.ajax({				data: {					action: 'query',					cb: Date.now,					format: 'json',					indexpageids: true,					prop: 'revisions',					rvprop: 'content',					titles: d.join('|'),				},				dataType: 'jsonp',				error: this.onError.bind(this),				type: 'GET',				url: 'https://community.fandom.com/api.php'			}).always(this.prepareData.bind(this)); },		prepareData: function(data) { if (typeof(data) !== "object") return this.def.reject(this.warn('Failed to get page content:', data)); var ids = data.query.pageids, pages = data.query.pages, o = {}; ids.forEach(function(id) {				var currentData = pages[id],					title = currentData.title.replace('User:Thundercraft5/global.js/', '');				if (!currentData.revisions) return this.warn('The requested module "' + title + '" does not exist, skipping.');				var content = currentData.revisions[0]["*"];				o[title] = {					content: content,					id: id,				};			}.bind(this)); console.log(o); this.def.resolve(o); return o;		}, onError: function(e) { this.def.reject(this.warn(e)); },	};	return self.init; }; /*=============================================== *Imports *===============================================

$.when(	loadModules([ "utils.js", ]) ).then(function {

// Clear cache $(document.body).on('keydown', function(e) {	if (e.key.toLowerCase === 'f5' && e.ctrlKey) {		console.log('Clearing cache...');		localStorage.clear;	} });

// Contribs link $('.wds-global-navigation__user-menu .wds-list.wds-is-linked > li:nth-child(1)').after($('', { html: $('', {		href: mw.util.getUrl('Special:Contributions/' + window.wgUserName),		html: "Contributions",	}), }));

$('.global-navigation__bottom ul.wds-list.wds-is-linked > li > a[href*="bingebot"]').remove;

var observer = new MutationObserver(function(mutations, o) {	$(mutations.map(function(mutation) { 		return $(mutation.addedNodes[0])			.find('input')				.attr('placeholder', 'Search...');	}))		.parent		.addClass('wiki-tools__ucxsearch');	o.disconnect; });

observer.observe($('.wiki-tools')[0], {	subtree: true,	childList: true,	attributes: true, });

observer.observe($('.wiki-tools')[1], {	subtree: true,	childList: true,	attributes: true, });

// Add hook for protecting Userpage mw.hook('AutoCreateUserPages.loaded').add(function(pages) {	pages.forEach(window.AutoCreateUserPagesConfig.completeCallback); });

// Editor toolbar posistioning $('#wpMinoreditWidget, #wpWatchthisWidget').each(function {	$(this).prop('outerHTML', $(this).children('input').prop('outerHTML')); }); // CodeMirror Customization if (['submit', 'edit'].includes(mw.config.get('wgAction')) && !mw.config.get('wgIsProbablyEditable')) { mw.loader.using([ 'ext.wikiEditor', 'ext.fandom.wikiEditor.codeMirrorTheming.css' ]).then(function {		$('.CodeMirror').css({ 'font-size': "14px", });	}); } else if (!window.wgCodeEditorCurrentLanguage && ['submit', 'edit'].includes(mw.config.get('wgAction'))) mw.loader.using([ 'ext.wikiEditor', 'ext.fandom.wikiEditor.codeMirrorTheming.css' ]).then(function {	// Quick Submit 	$('#wpSave').click(function(e) { if (e.shiftKey || e.ctrlKey) return; else if (e.altKey) { e.preventDefault; e.stopImmediatePropagation; $(this).click; }		e.preventDefault; e.stopImmediatePropagation; window.navigator.clipboard.writeText($('.editor').length ? window.ace.editor.session.getValue : $('#wpTextbox1').val); new mw.Api.postWithEditToken({			action: 'edit',			bot: false,			text: $('.editor').length ? window.ace.editor.session.getValue : $('#wpTextbox1').val,			title: mw.config.get('wgPageName'),			summary: mw.util.getParamValue('section') === 'new' ? undefined : $('#wpSummary').val,			minor: $('#wpMinoredit').prop('checked'),			watchlist: $('#wpWatchthis').prop('checked') ? 'watch' : 'nochange',			undoafter: mw.util.getParamValue('undoafter'),			undo: mw.util.getParamValue('undo'),			section: mw.util.getParamValue('section') || undefined,			sectiontitle: mw.util.getParamValue('section') === 'new' ? $('#wpSummary').val : undefined,		}).then(function(res) {			$(window).off('beforeunload');			console.log('Edit:', res);			window.location.replace(mw.util.getUrl(mw.config.get('wgPageName')));		}).catch(function(_, e) {			console.warn('Failed to edit "' + mw.config.get('wgPageName') + '": ' + e.error.info); alert('Failed to edit "' + mw.config.get('wgPageName') + '", check console.'); });	}); });

}).catch(console.warn);

// Personal Imports loadModules(Object.entries({ 'AjaxRedirect.js': isView, 'Ace.js': isCodeEditor, 'JSConsole.js': isCodeEditor && wgCodeEditorCurrentLanguage === 'javascript', 'Wikimarks.js': isView, 'CodeMirror.js': isWikiEditor, 'OutreachMessage.js': !!(mw.config.get('profileUserId') || mw.config.get('wgRelevantUserName')) && isView && ![7931, 1233861, 177, 65099, 1634335].includes(mw.config.get('wgCityId')) // Exclude official wikis && mw.config.get('wgUserGroups').length < 6, // Exclude if I have local rights 'LuaModuleImport.js': 1, }).filter(function(d) { return d[1]; }).map(function(d) { return d[0]; })).then(function {	console.log('Loading Custom Global JS modules took ' + (new Date - start) + 'ms'); }); //