Участник:Mednik/common.js
Материал из Wiki - Факультет компьютерных наук
Замечание. Возможно, после сохранения вам придётся очистить кэш своего браузера, чтобы увидеть изменения.
- Firefox / Safari: Удерживая клавишу Shift, нажмите на панели инструментов Обновить либо нажмите Ctrl-F5 или Ctrl-R (⌘-R на Mac)
- Google Chrome: Нажмите Ctrl-Shift-R (⌘-Shift-R на Mac)
- Internet Explorer: Удерживая Ctrl, нажмите Обновить либо нажмите Ctrl-F5
- Opera: Выберите очистку кэша в меню Инструменты → Настройки
/* * Nuke * Reverse engineered Nuke extension * https://www.mediawiki.org/wiki/Extension:Nuke * @author Ozank Cx (https://dev.fandom.com/wiki/User:Ozank Cx) * @author Thundercraft5 (https://dev.fandom.com/wiki/User:Thundercraft5) */ /* jshint esversion: 6, forin: true, immed: true, indent: 4, latedef: true, newcap: true, onevar: true, eqeqeq: true, multistr: true, maxerr: 999999, noarg: true, undef: true, undef: true, unused: true, browser: true, jquery: true, -W082, -W084 */ /* global mw */ mw.loader.using(['mediawiki.util', 'mediawiki.api', 'mediawiki.user']).then(function() { var api = new mw.Api(); return $.when( mw.user.getRights(), api, api.loadMessagesIfMissing([ 'invert', 'nuke', 'nuke-linkoncontribs', 'nuke-linkoncontribs-text', 'nuke-tools', 'nuke-submit-delete', 'nuke-submit-user', 'nuke-list', 'nuke-list-multiple', 'nuke-deleted', 'nuke-not-deleted', 'nuke-editby', 'nuke-nopages', 'nuke-userorip', 'nuke-namespace', 'nuke-maxpages', ]) ); }).then(function(rights, api) { if (window.Nuke && window.Nuke.loaded) return this.warn('Script was double loaded, exiting...'); else if (![-1, 2, 3, 1200].includes(this.wg.wgNamespaceNumber) && !(this.wg.wgNamespaceNumber === 500 && !this.wg.wgPageName.includes('/')) ) return this.log('Namespace is not supported, exiting...'); else if (!rights.includes('delete')) return this.log('User cannot delete pages, exiting...'); var Nuke = window.Nuke = Object.assign(this, { loaded: true, limit: Number(mw.util.getParamValue('nukelimit') || 500), deleteDelay: window.nukeDelay || 1000, label: mw.msg('nuke'), contribsLabel: mw.msg('nuke-linkoncontribs'), token: mw.user.tokens.get('csrfToken'), init: function() { $('.page-header__title').text(this.label); document.title = this.label + " | " + this.wg.wgSiteName + " | Fandom"; mw.util.addCSS('.thumbnail-nuke {\ max-width: 250px;\ width: auto;\ height: 80px;\ }\ \ li.nuke-query-result:hover {\ cursor: pointer !important;\ background: rgba(0, 0, 0, 0.5)\ }\ \ li.nuke-query-result {\ transition: 0.3s background ease;\ }\ \ button {\ cursor: pointer !important;\ }'); if (mw.util.getParamValue('nukeuser')) { this.loadUserUI(); } else { this.loadMainUI(); } $(document.body).on('click', '.nuke-submit', this.submitHandler); }, msg: function(name) { return mw.message.apply(mw, [name].concat(Array.from(arguments).slice(1))).parse().replace(/'{3}(.+?)'{3}/g, '<b>$1</b>'); }, rcSubmit: function() { if ($('#nuke-rc').attr('disabled')) return; $('#nuke-rc').attr('disabled', true); $('.nuke-check-all, .nuke-invert').remove(); if ($('#nuke-username').val()) { var locationParams = { blankspecial: 'nuke', nukeuser: $('#nuke-username').val() }; if ($('#nuke-namespace').val() !== "All") locationParams.nukenamespace = $('#nuke-namespace').val(); if ($.isNumeric($('#nuke-max').val()) && $('#nuke-max').val() > 0) locationParams.nukelimit = $('#nuke-max').val(); if ($('#nuke-match').val()) locationParams.nukematch = $('#nuke-match').val(); location.replace(mw.util.getUrl('Special:Blankpage', locationParams)); return; } $('#nuke-query-results').empty(); if ($('.nuke-submit').length) { $('.nuke-submit').remove(); $('#mw-content-text > p:nth-child(1) > br:nth-child(14)').remove(); } $('#nuke-status').html('Getting pages... please wait <img src="https://static.wikia.nocookie.net/dev/images/c/c5/Circle_throbber.gif/revision/latest"/>'); this.queryRecentChanges(); }, submitHandler: function() { if (!$('.nuke-query-result, .nuke-title-check:checked').length || $(this).attr('disabled')) return; $('.nuke-submit, .nuke-check-all, .nuke-invert, #nuke-protect').attr('disabled', true); $('#nuke-status').html('Deleting pages... please wait <img src="https://static.wikia.nocookie.net/dev/images/c/c5/Circle_throbber.gif/revision/latest"/>'); $('.nuke-title-check:checked').each(function(i) { var title = $(this).parent().find('a:not(:has(> img))').first().text(); setTimeout(function() { api.post({ action: 'delete', title: title, reason: $('#nuke-delete-reason').val() || '', bot: true, token: this.token, watchlist: 'nochange', }).then(function() { this.notify('success', this.msg('nuke-deleted', title)); $('#nuke-protect').prop('checked') ? api.post({ action: 'protect', protections: 'create=sysop', expiry: 'infinite', bot: true, watchlist: 'nochange', token: this.token, title: title, reason: $('#nuke-delete-reason').val(), }).then(function() { this.notify('success', 'Protection of ' + title + ' successful!'); }.bind(this), function(_, data) { this.notify('warn', 'Failed to protect ' + title + ':', data.error.info); }.bind(this)) : undefined; }.bind(this), function(_, data) { this.notify('warn', this.msg('nuke-not-deleted', title).replace(/\.$/, ': ' + data.error.info)); }.bind(this)); if (i === $('.nuke-title-check:checked').length - 1) { setTimeout(function() { this.log('Deletions All Done, redirecting...'); location.replace( !mw.util.getParamValue('nukeuser') ? mw.util.getUrl( 'Special:BlankPage', $.extend({ blankspecial: 'nuke' }, this.parseUrlParams(location.search)) ) : mw.util.getUrl( mw.util.getParamValue('returnto') || ("Special:Contributions/" + mw.util.getParamValue('nukeuser')), mw.util.getParamValue('returntoparams') ? this.parseUrlParams(mw.util.getParamValue('returntoparams')) : '' ) ); }.bind(this), 1000); } }.bind(Nuke), i * this.deleteDelay); }); }, loadUserUI: function() { var user = mw.util.getParamValue('nukeuser').replace(/_/g, ' '), deleteReason = mw.html.escape( mw.util.getParamValue('nukereason') || window.nukeDeleteReason && window.nukeDeleteReason.replaceAll(/\$1/g, user) || "Mass removal of pages created by [[Special:Contributions/" + user + "|" + user + "]] ([[User talk:" + user + "|talk]])" ); this.addCheckboxHandler(); $('#mw-content-text p').html($('<span>', { html: [ $('<a>', { href: mw.util.getUrl('Special:Blankpage', { blankspecial: 'nuke' }), html: "Switch to Nuke main form", }), '<br/>', this.msg('nuke-list', user), '<br>', 'Deletion reason: ', $('<input>', { css: { width: "400px" }, type: "text", id: "nuke-delete-reason", value: deleteReason, }), $('<div>', { html: [ $('<input>', { type: "checkbox", name: "nuke-protect", id: "nuke-protect", title: 'Check this box to protect deleted pages from re-creation', }), $('<label>', { html: "Protect deleted pages", 'for': 'nuke-protect', id: "nuke-protect-label", title: 'Check this box to protect deleted pages from re-creation', }), ], class: "nuke-label", }), $('<hr>', { css: { 'margin': '0 20px;' }}), $("<button>", { class: "nuke-submit", html: this.msg('nuke-submit-delete') + ' (0)', }), $('<div>', { id: "nuke-status" }), $('<ul>', { id: "nuke-query-results" }), $("<button>", { class: "nuke-submit", html: this.msg('nuke-submit-delete') + ' (0)', }), ]})); $('#nuke-status') .html('Getting pages... please wait <img src="https://static.wikia.nocookie.net/dev/images/c/c5/Circle_throbber.gif/revision/latest"/>'); this.queryUserContribs(user); $('#nuke-status').empty(); }, loadMainUI: function() { this.addCheckboxHandler(); $('#mw-content-text p').html($('<span>', { html: [ this.msg('nuke-tools'), '<br/>', this.msg('nuke-userorip'), $('<input>', { type: "text", id: "nuke-username", }), '<br>', 'Regex pattern (e.g. <code>.*</code>) for the page name: ', $('<input>', { type: "text", id: "nuke-match", value: mw.util.getParamValue('nukepattern'), }), '<br>', this.msg('nuke-namespace'), $('<select>', { id: "nuke-namespace", name: "nuke-namespace", html: [ $('<option>', { value: "all", selected: "", html: "all", }), ].concat(this.generateNamespaceSelect()), }), '<br>', this.msg('nuke-maxpages'), $('<input>', { type: "text", id: "nuke-max", value: mw.util.getParamValue('nukelimit') || 500, }), '<br>', 'Deletion Reason: ', $('<input>', { type: "text", id: "nuke-delete-reason", value: mw.util.getParamValue('nukereason'), }), '<br>', $('<input>', { type: "checkbox", name: "nuke-protect", id: "nuke-protect", title: 'Check this box to protect deleted pages from re-creation', }), $('<label>', { html: "Protect deleted pages", 'for': 'nuke-protect', id: "nuke-protect-label", title: 'Check this box to protect deleted pages from re-creation', }), $('<div>', { html: $("<input>", { class: "wikia-button", id: "nuke-rc", name: "nuke-rc", value: this.msg('nuke-submit-user'), type: "submit", click: this.rcSubmit.bind(this), }), css: { 'margin-top': '10px', 'margin-bottom': "30px", }, }), $('<div>', { id: "nuke-status" }), $('<hr>'), $('<ul>', { id: "nuke-query-results", }), ]})); $('#nuke-namespace').val(mw.util.getParamValue('nukenamespace')); }, queryUserContribs: function(user) { api.get({ action: 'query', list: 'usercontribs', ucnamespace: mw.util.getParamValue('nukenamespace') || '', ucuser: user, uclimit: 'max', }).then(function(d) { var usercontribs = d.query.usercontribs, images = [], count = 0; usercontribs.forEach(function(contrib) { if (count >= this.limit) return; if ('new' in contrib) { if (!mw.util.getParamValue('nukematch') || new RegExp(mw.util.getParamValue('nukematch')).test(contrib.title)) { count++; $('#nuke-query-results').append( $('<li>', { class: "nuke-query-result", html: [ $('<input>', { type: "checkbox", class: "nuke-title-check", checked: "checked", }), $('<a>', { href: mw.util.getUrl(contrib.title), target: "_blank", title: contrib.title, text: mw.html.escape(contrib.title), }), ' (', $('<a>', { target: "_blank", href: mw.util.getUrl(contrib.title, { action: "info" }), title: contrib.title, text: "info", }), ')', ], }) ); if (contrib.title.indexOf(this.wg.wgFormattedNamespaces[6] + ':') === 0) images.push(contrib.title); } } }, this); if (!$('.nuke-query-result').length) { this.notify('error', this.msg('nuke-nopages', user)); } else { if (images.length > 0) this.displayImages(images); this.addCheckToggleButton(); $('.nuke-submit').html(this.msg('nuke-submit-delete') + ' (' + $('.nuke-title-check:checked').length + ')'); } }.bind(this).bind(this), function(_, data) { this.notify('error', "Failed to get user contributions: " + data.error.info); }.bind(this)); }, queryRecentChanges: function() { api.get({ action: 'query', list: 'recentchanges', rcshow: '!bot', rctype: 'new|log', rclimit: 'max', }).then(function(d) { var recentchanges = d.query.recentchanges, rcTitles = [], maxLimit = $('#nuke-max').val() || 5000, images = [], count = 0; recentchanges.forEach(function(page) { if (count >= maxLimit) return; if ( rcTitles.indexOf(page.title, rcTitles) === -1 && ( $('#nuke-namespace').val() === "All" || Number($('#nuke-namespace').val()) === page.ns ) && (page.type === "new" || ( page.type === "log" && page.ns === 6 )) ) { if (!$('#nuke-match').val() || new RegExp($('#nuke-match').val()).test(page.title)) { count++; rcTitles.push(page.title); $('#nuke-query-results').append($('<li>', { class: "nuke-query-result", html: [ $('<input>', { type: "checkbox", class: "nuke-title-check", checked: "checked", }), $('<a>', { href: mw.util.getUrl(page.title), target: "_blank", title: page.title, text: mw.html.escape(page.title), }), ' (', $('<a>', { target: "_blank", href: mw.util.getUrl(page.title, { action: "info" }), title: page.title, text: "info", }), ')', ], })); if (page.title.indexOf(this.wg.wgFormattedNamespaces[6] + ':') === 0) images.push(page.title); } } }, this); if (!$('.nuke-query-result').length) { this.notify('error', "No recent changes found"); } else { var $button = $('<button>', { class: "nuke-submit", html: 'Delete selected (' + $('.nuke-title-check:checked').length + ')</a>', }); $('#nuke-query-results').before($button).after($button.clone()); $('#nuke-status').empty(); $('.nuke-sumbit, .nuke-check-all, .nuke-invert').remove(); this.addCheckToggleButton(); if (images.length > 0) this.displayImages(images); } }.bind(this), function(_, data) { this.notify('error', "Failed to get recent changes: " + data.error.info); }.bind(this)); $('#nuke-status').empty(); $(this).attr('disabled', false); }, generateNamespaceSelect: function() { return Object.entries(this.wg.wgFormattedNamespaces) .map(function(v) { return [+v[0], v[1]] }) .sort(function(a, b) { var id1 = a[0]; var id2 = b[0]; if (id1 < id2) return -1; else if (id1 > id2) return 1; else return 0; }) .slice(2) .map(function(d) { var namespace = d[1]; var id = d[0]; return $('<option>', { value: id, text: namespace === "" ? "(Main)" : namespace, }); }); }, notify: function(level) { var params = Array.from(arguments).slice(1); mw.notify($('<div>', { html: params.join(' ') }), { type: level }); (this[level] || this.log).apply(null, params.map(function(val) { return $($.parseHTML(val)).text(); })); }, addCheckboxHandler: function() { var selected = new Set(); var anchor; $('#mw-content-text').on('click', 'li.nuke-query-result', function(e) { var $input = $(this).find('input'); if (e.target.children.length === 0 && e.target !== $input[0]) return; if (e.target !== $input[0]) $input.prop('checked', !$input[0].checked); if (!e.shiftKey || e.shiftKey && !anchor) anchor = $input[0], selected.clear(), selected.add($input[0]); if (anchor && e.shiftKey && !e.ctrlKey) { var $coll = $(this).parent().children().map(function() { return $(this).find('input[type="checkbox"]')[0] }); var targetIndex = $coll.index($input[0]); var anchorIndex = $coll.index(anchor); if (targetIndex < anchorIndex) $coll = $coll.slice(targetIndex, anchorIndex + 1); else $coll = $coll.slice(anchorIndex, targetIndex + 1); $coll.each(function() { selected.add(this); }); } if (e.ctrlKey && !e.shiftKey) if (selected.has($input[0])) selected.delete($input[0]); else selected.add($input[0]); if (selected.size > 1) selected.forEach(function(node) { $(node).prop('checked', anchor.checked); }); }); }, addCheckToggleButton: function() { $('.nuke-submit') .after( $('<button>', { class: "nuke-check-all", 'data-checked': true, text: "Uncheck All", }), $('<button>', { text: this.msg('invert'), class: "nuke-invert", }) ); $('.nuke-submit').text(this.msg('nuke-submit-delete') + ' (' + $('.nuke-title-check:checked').length + ')'); // Check/Uncheck all $('.nuke-check-all').click(function() { var checked = $(this).attr('data-checked') === "true"; $('.nuke-title-check').prop('checked', !checked); $('.nuke-check-all') .attr('data-checked', !checked) .text(!checked ? "Uncheck All" : 'Check All'); }); // Invert/Uninvert all $('.nuke-invert').click(function() { $('.nuke-title-check').each(function() { $(this).prop('checked', !$(this).prop('checked')); }); }); // Update count $(document.body).on("click", '.nuke-query-result, .nuke-check-all, .nuke-invert', function() { $('.nuke-submit').html(this.msg('nuke-submit-delete') + ' (' + $('.nuke-title-check:checked').length + ')'); }.bind(this)); }, displayImages: function(imgs) { api.post({ //POST instead of GET to avoid http 416 action: 'query', prop: 'imageinfo', titles: imgs.join('|'), iiprop: 'url', iilimit: 'max' }).then(function(d) { Object.values(d.query.pages).forEach(function(page) { if (page.missing !== "" && page.imageinfo) { var href = mw.util.getUrl(page.title); $('a[href="' + href + '"]') .parent() .children('.nuke-title-check') .after($('<a>', { href: href, html: $('<img>', { class: "thumbnail-nuke", src: page.imageinfo[0].url, }), })); } }); }, function(_, data) { this.notify('error', 'Failed to display images: ' + data.error.info); }.bind(this)); }, parseUrlParams: function(s) { var params = s.replace(/^(?:\?|%26)/, '').split(/(?:&|%26)/); var o = {}; params.forEach(function(k) { var tmp = k.match(/(.+?)=(.+)/i); o[tmp[1]] = tmp[2]; }); return o; } }); var inter = setInterval(function() { var username = this.wg.wgRelevantUserName || this.wg.profileUserName; if ($('.page-tools-module').length) { clearInterval(inter); var $el = $('<li>', { id: "t-nuke", html: $('<a>', { text: this.label, title: window.nukeTitle || this.msg('nuke-linkoncontribs-text', username), href: mw.util.getUrl('Special:BlankPage', { blankspecial: 'nuke', nukeuser: username, }), }), }); var $list = $('.page-tools-module ul'); if ($list.find('li#t-reconst').length || window.Reconstitute) { $list.find('li#t-reconst').before($el); } else { $list.find('li:is(#t-userrights, :last-of-type)').first().after($el); } } }.bind(this)); switch (this.wg.wgCanonicalSpecialPageName) { case "UserProfileActivity": case "DeletedContributions": case "Contributions": { var usr = this.wg.wgRelevantUserName || this.wg.profileUserName, nukeTitle = window.nukeTitle || this.msg('nuke-linkoncontribs-text', usr), url = mw.util.getUrl('Special:BlankPage', { blankspecial: 'nuke', nukeuser: usr, }); if (usr) { var $el = $('<span>', { id: "link-nuke", html: $('<a>', { title: nukeTitle, href: url, text: this.contribsLabel, }), }); if (!window.QuickLogs) { if (this.wg.wgCanonicalSpecialPageName === 'DeletedContributions') { $('.page-header__subtitle > a:last-of-type').after(' | ', $el.find('a')); } else { if ($('#link-rconst').length) { $('#link-rconst').before($el); } else { $([ '.mw-contributions-user-tools > .mw-changeslist-links > span:last-child', '.UserProfileActivityModeration__links > span:last-child', ].join(', ')).after($el); } } } mw.hook('QuickLogs.loaded').add(function(ql) { ql.addLink('nuke', { href: url, title: nukeTitle, message: this.contribsLabel, }); }); } break; } case "AdminDashboard": case "Specialpages": { var link = mw.util.getUrl('Special:Blankpage', { blankspecial: 'nuke' }); var canNuke = rights.includes('nuke'); var nukeItem = $('<li>', { class: "mw-specialpagerestricted", html: $('<a>', { title: "Special:Nuke", href: link, text: this.label + (canNuke ? ' (JavaScript)' : ""), }), }); $(canNuke ? '#mw-content-text a[href*="Special:Nuke"]' : '#mw-content-text a[title="Special:Undelete"]' ).parent().after(nukeItem); var pageToolsTable = nukeItem.closest('.mw-specialpages-table'); var pageTools = $('li', pageToolsTable).toArray().sort(function (a, b) { return a.textContent.localeCompare(b.textContent); }); var uls = $('td[width="45%"] ul', pageToolsTable); if (uls.length > 0) { // Avoid divide by zero error. var perChunk = Math.ceil(pageTools.length / uls.length); uls.each(function(i, ul) { $(ul).append(pageTools.slice(i * perChunk, (i + 1) * perChunk)); }); } break; } case "Blankpage": { if (mw.util.getParamValue('blankspecial') === "nuke") this.init(); break; } } }.bind(function() { Object.keys(this).forEach(function(key) { this[key] = function() { console[key].apply(null, [ '[Nuke v1.5] [' + key.toUpperCase() + ']' ].concat(Array.from(arguments))); }; }, this); this.wg = mw.config.get([ 'wgUserGroups', 'wgCanonicalSpecialPageName', 'wgFormattedNamespaces', 'wgMainpage', 'wgPageName', 'wgSiteName', 'wgNamespaceNumber', 'profileUserName', 'wgRelevantUserName', ]); return this; }.call({ error: console.error, warn: console.warn, log: console.log, debug: console.debug, }))); window.Nuke = window.Nuke || {};