User:Synoman Barris/common.js: Difference between revisions
Content added Content deleted
(Undid revision 41490 by Synoman Barris (talk)) Tag: Undo |
No edit summary |
||
(One intermediate revision by the same user not shown) | |||
Line 1: | Line 1: | ||
// |
//<nowiki> |
||
$(function() { |
|||
/* |
|||
var namespace = mw.config.get('wgNamespaceNumber'), |
|||
* SpamUserPage |
|||
pageName = mw.config.get('wgPageName'), |
|||
* |
|||
myUserName = mw.config.get('wgUserName'), |
|||
* This gadget deletes a user page, blocks the user, and notifies them on their |
|||
userName = mw.config.get('wgRelevantUserName'), |
|||
* talk page. See [[User:Mr. Stradivarius/gadgets/SpamUserPage]] for |
|||
templateName = "script", |
|||
* documentation. |
|||
blockReason, |
|||
* |
|||
api; |
|||
* To install the script, add the following to your personal .js page: |
|||
importScript( 'User:Mr. Stradivarius/gadgets/SpamUserPage.js' ); // Linkback: [[User:Mr. Stradivarius/gadgets/SpamUserPage.js]] |
|||
* Author: Mr. Stradivarius |
|||
* Licence: MIT |
|||
* |
|||
* The MIT License (MIT) |
|||
* |
|||
* Copyright (c) 2015 Mr. Stradivarius |
|||
* |
|||
* Permission is hereby granted, free of charge, to any person obtaining a copy |
|||
* of this software and associated documentation files (the "Software"), to deal |
|||
* in the Software without restriction, including without limitation the rights |
|||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
|||
* copies of the Software, and to permit persons to whom the Software is |
|||
* furnished to do so, subject to the following conditions: |
|||
* |
|||
* The above copyright notice and this permission notice shall be included in |
|||
* all copies or substantial portions of the Software. |
|||
* |
|||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
|||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
|||
* THE SOFTWARE. |
|||
*/ |
|||
if([0,1,2,3,4,5].indexOf(namespace) !== -1) { |
|||
mw.loader.using( [ |
|||
mw.loader.using( [ 'mediawiki.api', 'mediawiki.util' ] ).done( function() { |
|||
api = new mw.Api(); |
|||
'mediawiki.Title', |
|||
mw.util.addPortletLink( |
|||
'mediawiki.util', |
|||
'p-cactions', 'javascript:void(0)', |
|||
'oojs-ui' |
|||
'Block vandal', 'ca-spamublock', 'Delete user page and execute {{uw-spamublock}} on current user' |
|||
], function () { |
|||
); |
|||
"use strict"; |
|||
} ); |
|||
$('#ca-spamublock').on('click', function() { |
|||
var config = mw.config.get( [ |
|||
if (confirm('This script will delete the current user page, block the relevant user or page creator as {{uw-spamublock}} and leave that template on their talk page, or the template specified at [[Special:MyPage/uw-spamublock]], if present.\n\nARE YOU SURE YOU WANT TO PROCEED?')) { |
|||
'wgTitle', |
|||
$('#ca-spamublock').text('Please wait...'); |
|||
'wgNamespaceNumber', |
|||
if(!userName) { |
|||
'wgUserName' |
|||
api.get({ |
|||
] ); |
|||
action: 'query', |
|||
prop: 'revisions', |
|||
titles: pageName, |
|||
rvdir: 'newer', |
|||
rvlimit: '1', |
|||
rvprop: 'user' |
|||
}).then(function(data) { |
|||
var pages = data.query.pages; |
|||
userName = pages[Object.keys(pages)[0]].revisions[0].user; |
|||
getTemplate(); |
|||
}); |
|||
} else { |
|||
getTemplate(); |
|||
} |
|||
} |
|||
}); |
|||
} |
|||
function getTemplate() { |
|||
// Exit if we are not in user or user talk space. |
|||
api.get({ |
|||
if ( config.wgNamespaceNumber !== 2 && config.wgNamespaceNumber !== 3 ) { |
|||
action: 'query', |
|||
return; |
|||
titles: 'User:'+myUserName+'/uw-spamublock' |
|||
} |
|||
}).then(function(data) { |
|||
var query = data.query.pages; |
|||
if(Object.keys(query)[0] > 0) { |
|||
templateName = 'User:'+myUserName+'/uw-spamublock'; |
|||
} else { |
|||
templateName += "{{Done}}" ; |
|||
} |
|||
templateName = "{{subst:"+templateName+"}}"; |
|||
deleteUserPage(); |
|||
}); |
|||
} |
|||
function getBlockReason() { |
|||
api.get({ |
|||
action: 'query', |
|||
titles: 'User:'+myUserName+'/spamublock-message' |
|||
}).then(function(data) { |
|||
var query = data.query.pages; |
|||
if(Object.keys(query)[0] > 0) { |
|||
blockReason = '{{User:'+myUserName+'/spamublock-message}}'; |
|||
} else { |
|||
blockReason = 'Testing blocking script'; |
|||
} |
|||
blockUser(); |
|||
}); |
|||
} |
|||
function deleteUserPage() { |
|||
/************************************************************************** |
|||
api.postWithToken("delete", { |
|||
* ApiManager class |
|||
action: 'delete', |
|||
**************************************************************************/ |
|||
reason: 'Testing script', |
|||
title: pageName |
|||
}).then(function(deleteData) { |
|||
$("#mw-content-text").html( |
|||
"<p><b>Deleted</b> page <a href='"+mw.util.getUrl(pageName)+"'>"+pageName+"</a> <i>(<a href='"+mw.util.getUrl('WP:G11')+"'>G11</a>: Unambiguous <a href='"+mw.util.getUrl('WP:NOTADVERTISING')+"'>advertising</a> or promotion)</i></p>" |
|||
); |
|||
getBlockReason(); |
|||
},function(error) { |
|||
$("#mw-content-text").html( |
|||
"<p><b>Error</b> deleting page "+pageName+": "+error+"</p>" |
|||
); |
|||
}); |
|||
} |
|||
function blockUser() { |
|||
api.postWithToken("block", { |
|||
var i, len, preset, key, customPresetIds, defaultPreset, hasUserPreference; |
|||
action: 'block', |
|||
allowusertalk: false, |
|||
autoblock: true, |
|||
nocreate: true, |
|||
reason: blockReason, |
|||
user: userName |
|||
}).then(function(blockData) { |
|||
$("#mw-content-text").append( |
|||
"<p><b>Blocked</b> <a href='"+mw.util.getUrl('User:'+userName)+"'>"+userName+"</a> (account creation blocked) with an expiry time of indefinite <i>(<span id='spamublock-blocked-reason'></span>)</i></p>" |
|||
); |
|||
$('<span/>').text(blockReason).appendTo("#spamublock-blocked-reason"); |
|||
templateUser(); |
|||
}, function(error) { |
|||
$("#mw-content-text").append( |
|||
"<p><b>Error</b> blocking <a href='"+mw.util.getUrl('User:'+userName)+"'>"+userName+"</a>: "+error+"</p>" |
|||
); |
|||
}); |
|||
} |
|||
function templateUser() { |
|||
this.api = new mw.Api(); |
|||
var monthNames = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"], |
|||
this.currentTitle = new mw.Title( config.wgTitle, config.wgNamespaceNumber ); |
|||
d = new Date(); |
|||
this.userName = this.currentTitle.getMainText().replace( /\/.*$/, '' ); |
|||
this.userTalkTitle = new mw.Title( this.userName, 3 ); |
|||
this.userPreferences = typeof window.SpamUserPage === 'object' ? window.SpamUserPage : {}; |
|||
api.postWithToken( "edit", { |
|||
// Set up caches |
|||
action: "edit", |
|||
this.menuItemCache = {}; |
|||
section: 'new', |
|||
sectiontitle: monthNames[d.getMonth()] + ' ' + d.getFullYear(), |
|||
// Get presets |
|||
summary: "You have been indefinitely blocked because am testing a script", |
|||
this.presets = {}; |
|||
text: "\n"+templateName, |
|||
this.presetIds = []; |
|||
title: "User talk:"+userName |
|||
customPresetIds = []; // Track custom preset IDs separately so that we can put them first. |
|||
}).then(function(editData) { |
|||
$("#mw-content-text").append( |
|||
function setPreset( obj, thisArg ) { |
|||
"<p><b>Edited</b> <a href='"+mw.util.getUrl('User talk:'+userName)+"'>User talk:"+userName+"</a>: Created new section with template "+templateName+"</p>" + |
|||
var ret = thisArg.presets[ obj.id ] || {}; |
|||
"<p><b>Complete (<a href='javascript:document.location.reload()'>reload</a>)</b></p>" |
|||
ret.id = obj.id; |
|||
); |
|||
for ( key in ApiManager.static.presetDefaults ) { |
|||
},function(error) { |
|||
if ( ApiManager.static.presetDefaults.hasOwnProperty( key ) ) { |
|||
$("#mw-content-text").append( |
|||
if ( obj[ key ] !== undefined ) { |
|||
"<p><b>Error</b> editing <a href='"+mw.util.getUrl('User talk:'+userName)+"'>User talk:"+userName+"</a>: "+error+"</p>" |
|||
ret[ key ] = obj[ key ]; |
|||
); |
|||
} |
|||
}); |
|||
if ( ret[ key ] === undefined ) { |
|||
} |
|||
ret[ key ] = ApiManager.static.presetDefaults[ key ]; |
|||
}); |
|||
} |
|||
//</nowiki> |
|||
} |
|||
} |
|||
thisArg.presets[ ret.id ] = ret; |
|||
} |
|||
for ( i = 0, len = ApiManager.static.presets.length; i < len; i++ ) { |
|||
preset = ApiManager.static.presets[ i ]; |
|||
this.presetIds.push( preset.id ); |
|||
setPreset( preset, this ); |
|||
} |
|||
if ( $.isArray( this.userPreferences.presets ) ) { |
|||
for ( i = 0, len = this.userPreferences.presets.length; i < len; i++ ) { |
|||
preset = this.userPreferences.presets[ i ]; |
|||
if ( typeof preset === 'object' ) { |
|||
if ( typeof preset.id === 'string' ) { |
|||
if ( !this.presets[ preset.id ] ) { |
|||
customPresetIds.push( preset.id ); |
|||
} |
|||
setPreset( preset, this ); |
|||
} else { |
|||
throw new Error( "missing or invalid 'id' field in custom preset #" + i ); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
this.presetIds = customPresetIds.concat( this.presetIds ); |
|||
// Get defaults |
|||
this.defaults = {}; |
|||
hasUserPreference = false; |
|||
if ( typeof this.userPreferences.preset === 'string' ) { |
|||
defaultPreset = this.userPreferences.preset; |
|||
if ( !this.presets[ defaultPreset ] ) { |
|||
throw new Error( "'" + defaultPreset + "' is not a valid preset ID" ); |
|||
} |
|||
} else { |
|||
defaultPreset = ApiManager.static.otherDefaults.preset; |
|||
} |
|||
function setDefaults( obj, thisArg ) { |
|||
for ( key in obj ) { |
|||
if ( obj.hasOwnProperty( key ) ) { |
|||
if ( thisArg.userPreferences[ key ] !== undefined ) { |
|||
hasUserPreference = true; |
|||
thisArg.defaults[ key ] = thisArg.userPreferences[ key ]; |
|||
} else if ( thisArg.presets[ defaultPreset ][ key ] !== undefined ) { |
|||
thisArg.defaults[ key ] = thisArg.presets[ defaultPreset ][ key ]; |
|||
} else { |
|||
thisArg.defaults[ key ] = ApiManager.static.otherDefaults[ key ]; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
setDefaults( ApiManager.static.presetDefaults, this ); |
|||
setDefaults( ApiManager.static.otherDefaults, this ); |
|||
if ( hasUserPreference ) { |
|||
this.defaults.preset = null; |
|||
} else { |
|||
this.defaults.preset = defaultPreset; |
|||
} |
|||
}; |
|||
OO.initClass( ApiManager ); |
|||
ApiManager.static.presets = [ |
|||
{ |
|||
id: 'spamublock', |
|||
label: 'Spam-only account, username violation', |
|||
deletesummary: '[[WP:CSD#G11|G11]]: Unambiguous [[WP:NOTADVERTISING|advertising]] or promotion', |
|||
blocksummary: '{{uw-spamublock}}', |
|||
editsummary: 'You have been indefinitely blocked from editing because your account is being ' + |
|||
'used only for [[WP:SPAM|spam or advertising]] and your username is a violation of the ' + |
|||
'[[WP:U|username policy]].', |
|||
template: '{{subst:uw-spamublock|sig=yes}}' |
|||
}, |
|||
{ |
|||
id: 'soablock', |
|||
label: 'Spam-only account', |
|||
deletesummary: '[[WP:CSD#G11|G11]]: Unambiguous [[WP:NOTADVERTISING|advertising]] or promotion', |
|||
blocksummary: '[[WP:Spam|Spam]] / [[WP:NOTADVERTISING|advertising]]-only account', |
|||
editsummary: 'You have been indefinitely blocked from editing because your account is being ' + |
|||
'used only for [[WP:SPAM|spam, advertising, or promotion]]', |
|||
template: '{{subst:uw-soablock|sig=yes}}' |
|||
}, |
|||
{ |
|||
id: 'sblock', |
|||
label: 'Spamming', |
|||
deletesummary: '[[WP:CSD#G11|G11]]: Unambiguous [[WP:NOTADVERTISING|advertising]] or promotion', |
|||
expiry: '31 hours', |
|||
blocksummary: 'Using Wikipedia for [[WP:SPAM|spam]] purposes', |
|||
editsummary: 'You have been blocked from editing for using Wikipedia for [[WP:SPAM|spam]] purposes', |
|||
template: '{{subst:uw-sblock|sig=yes}}' |
|||
}, |
|||
{ |
|||
id: 'vaublock', |
|||
label: 'Vandalism-only account, username violation', |
|||
deletesummary: '[[WP:CSD#G3|G3]]: [[WP:Vandalism|Vandalism]]', |
|||
blocksummary: '{{uw-vaublock}}', |
|||
editsummary: 'You have been indefinitely blocked from editing because your account is being ' + |
|||
'[[WP:VOA|used only for vandalism]] and your username is a blatant violation of the ' + |
|||
'[[WP:U|username policy]]', |
|||
template: '{{subst:uw-vaublock|sig=yes}}' |
|||
}, |
|||
{ |
|||
id: 'voablock', |
|||
label: 'Vandalism-only account', |
|||
deletesummary: '[[WP:CSD#G3|G3]]: [[WP:Vandalism|Vandalism]]', |
|||
blocksummary: '[[WP:Vandalism-only account|Vandalism-only account]]', |
|||
editsummary: 'You have been indefinitely blocked from editing because your account is being ' + |
|||
'[[WP:VOA|used only for vandalism]]', |
|||
template: '{{subst:uw-voablock|sig=yes}}' |
|||
}, |
|||
{ |
|||
id: 'vblock', |
|||
label: 'Vandalism', |
|||
deletesummary: '[[WP:CSD#G3|G3]]: [[WP:Vandalism|Vandalism]]', |
|||
expiry: '31 hours', |
|||
blocksummary: '[[WP:Vandalism|Vandalism]]', |
|||
editsummary: 'You have been blocked from editing for persistent [[WP:VAND|vandalism]]', |
|||
template: '{{subst:uw-vblock|sig=yes}}' |
|||
}, |
|||
{ |
|||
id: 'softerblock', |
|||
label: 'Promotional username, soft block', |
|||
deletesummary: '[[WP:CSD#G11|G11]]: Unambiguous [[WP:NOTADVERTISING|advertising]] or promotion', |
|||
blocksummary: '{{uw-softerblock}}', |
|||
editsummary: 'You have been indefinitely blocked from editing because your [[WP:U|username]] ' + |
|||
'gives the impression that the account represents a group, organization or website.', |
|||
template: '{{subst:uw-softerblock|sig=yes}}', |
|||
nocreate: false, |
|||
autoblock: false |
|||
}, |
|||
{ |
|||
id: 'causeblock', |
|||
label: 'Username of a non-profit, soft block', |
|||
deletesummary: '[[WP:CSD#G11|G11]]: Unambiguous [[WP:NOTADVERTISING|advertising]] or promotion', |
|||
blocksummary: '{{uw-causeblock}}', |
|||
editsummary: 'You have been indefinitely blocked from editing because your [[WP:U|username]] ' + |
|||
'gives the impression that the account represents a group, organization or website.', |
|||
template: '{{subst:uw-causeblock|sig=yes}}', |
|||
nocreate: false, |
|||
autoblock: false |
|||
}, |
|||
{ |
|||
id: 'copyrightblock', |
|||
label: 'Copyright violations', |
|||
deletesummary: '[[WP:CSD#G12|G12]]: Unambiguous [[WP:CV|copyright infringement]]', |
|||
expiry: '24 hours', |
|||
blocksummary: '[[WP:Copyright violations|Copyright violations]]', |
|||
editsummary: 'You have been blocked from editing for continued [[WP:COPYVIO|copyright infringement]]', |
|||
template: '{{subst:uw-copyrightblock|sig=yes}}' |
|||
}, |
|||
{ |
|||
id: 'myblock', |
|||
label: 'Using Wikipedia as a blog or web host', |
|||
deletesummary: '[[WP:CSD#U5|U5]]: [[WP:NOTWEBHOST|Misuse of Wikipedia as a web host]]', |
|||
expiry: '24 hours', |
|||
blocksummary: 'Using Wikipedia as a [[WP:NOTMYSPACE|blog, web host, social networking site or forum]]', |
|||
editsummary: 'You have been blocked from editing for using user and/or article pages ' + |
|||
'as a [[WP:NOTMYSPACE|blog, web host, social networking site or forum]]', |
|||
template: '{{subst:uw-myblock|sig=yes}}' |
|||
}, |
|||
{ |
|||
id: 'npblock', |
|||
label: 'Creating nonsense pages', |
|||
deletesummary: '[[WP:CSD#G1|G1]]: [[WP:PN|Patent nonsense]], meaningless, or incomprehensible', |
|||
expiry: '24 hours', |
|||
blocksummary: 'Creating [[WP:Patent nonsense|patent nonsense]] or other inappropriate pages', |
|||
editsummary: 'You have been blocked from editing for creating [[WP:PN|nonsense pages]]', |
|||
template: '{{subst:uw-npblock|sig=yes}}' |
|||
} |
|||
]; |
|||
ApiManager.static.menuDefaults = { |
|||
expiry: [ |
|||
'indefinite', |
|||
'3 hours', |
|||
'12 hours', |
|||
'24 hours', |
|||
'31 hours', |
|||
'36 hours', |
|||
'48 hours', |
|||
'60 hours', |
|||
'72 hours', |
|||
'1 week', |
|||
'2 weeks', |
|||
'1 month', |
|||
'3 months', |
|||
'6 months', |
|||
'1 year', |
|||
'2 years', |
|||
'3 years' |
|||
], |
|||
deletesummary: [ |
|||
// If you change the order of these, please also update the number of the |
|||
// default deletion summary in ApiManager.static.presetDefaults. |
|||
'[[WP:CSD#G1|G1]]: [[WP:PN|Patent nonsense]], meaningless, or incomprehensible', |
|||
'[[WP:CSD#G2|G2]]: Test page', |
|||
'[[WP:CSD#G3|G3]]: [[WP:Vandalism|Vandalism]]', |
|||
'[[WP:CSD#G3|G3]]: Blatant [[WP:Do not create hoaxes|hoax]]', |
|||
'[[WP:CSD#G4|G4]]: Recreation of a page that was [[WP:DEL|deleted]] per a [[WP:XFD|deletion discussion]]', |
|||
'[[WP:CSD#G5|G5]]: Creation by a [[WP:BLOCK|blocked]] or [[WP:BAN|banned]] user in violation of block or ban', |
|||
'[[WP:CSD#G6|G6]]: Housekeeping and routine (non-controversial) cleanup', |
|||
'[[WP:CSD#G7|G7]]: One author who has requested deletion or blanked the page', |
|||
'[[WP:CSD#G8|G8]]: Page dependent on a deleted or nonexistent page', |
|||
'[[WP:CSD#G10|G10]]: [[WP:ATP|Attack page]] or negative unsourced [[WP:BLP|BLP]]', |
|||
'[[WP:CSD#G11|G11]]: Unambiguous [[WP:NOTADVERTISING|advertising]] or promotion', |
|||
'[[WP:CSD#G12|G12]]: Unambiguous [[WP:CV|copyright infringement]]', |
|||
'[[WP:CSD#G13|G13]]: Abandoned [[WP:AFC|Article for creation]]? to retrieve it, see [[WP:REFUND/G13]]', |
|||
'[[WP:CSD#U1|U1]]: User request to delete page in own userspace', |
|||
'[[WP:CSD#U2|U2]]: Userpage or subpage of a nonexistent user', |
|||
'[[WP:CSD#U3|U3]]: [[WP:NFC|Non-free]] [[Help:Gallery|gallery]]', |
|||
'[[WP:CSD#U5|U5]]: [[WP:NOTWEBHOST|Misuse of Wikipedia as a web host]]' |
|||
], |
|||
blocksummary: [ |
|||
'{{uw-spamublock}}', |
|||
'[[WP:Spam|Spam]] / [[WP:NOTADVERTISING|advertising]]-only account', |
|||
'Using Wikipedia for [[WP:Spam|spam]] or [[WP:NOTADVERTISING|advertising]] purposes', |
|||
'{{uw-vaublock}}', |
|||
'[[WP:Vandalism-only account|Vandalism-only account]]', |
|||
'[[WP:Vandalism|Vandalism]]', |
|||
'[[WP:Copyright violations|Copyright violations]]', |
|||
'{{uw-softerblock}}', |
|||
'{{uw-causeblock}}', |
|||
'Creating [[WP:Attack page|attack pages]]', |
|||
'Violations of the [[WP:Biographies of living persons|Biographies of living persons]] policy', |
|||
'Creating [[WP:Patent nonsense|patent nonsense]] or other inappropriate pages', |
|||
'[[WP:Disruptive editing|Disruptive editing]]', |
|||
'[[WP:No personal attacks|Personal attacks]] or [[WP:Harassment|harassment]]', |
|||
'[[WP:Blocking policy#Evasion of blocks|Block evasion]]', |
|||
'Abusing [[WP:Sock puppetry|multiple accounts]]', |
|||
'[[WP:Long-term abuse|Long-term abuse]]', |
|||
], |
|||
editsummary: [ |
|||
'You have been blocked from editing because your account ' + |
|||
'is being used only for [[WP:SPAM|spam or advertising]] and your ' + |
|||
'username is a violation of the [[WP:U|username policy]].', |
|||
'You have been blocked from editing for [[WP:SOAP|advertising or self-promotion]]', |
|||
'You have been blocked from editing for using Wikipedia for [[WP:SPAM|spam]] purposes', |
|||
'You have been blocked from editing because your account is being ' + |
|||
'used only for [[WP:SPAM|spam, advertising, or promotion]]', |
|||
'You have been indefinitely blocked from editing because your account ' + |
|||
'is being [[WP:VOA|used only for vandalism]] and your username is ' + |
|||
'a blatant violation of the [[WP:U|username policy]]', |
|||
'You have been blocked from editing for persistent [[WP:VAND|vandalism]]', |
|||
'You have been blocked from editing because your account is being ' + |
|||
'[[WP:VOA|used only for vandalism]]', |
|||
'You have been indefinitely blocked from editing because your [[WP:U|username]] ' + |
|||
'gives the impression that the account represents a group, organization or website.', |
|||
'You have been blocked from editing for continued [[WP:COPYVIO|copyright infringement]]', |
|||
'You have been blocked from editing for using user and/or article ' + |
|||
'pages as a [[WP:NOTMYSPACE|blog, web host, social networking site or forum]]', |
|||
], |
|||
template: [ |
|||
'{{subst:uw-spamublock|sig=yes}}', |
|||
'{{subst:uw-sblock|sig=yes}}', |
|||
'{{subst:uw-soablock|sig=yes}}', |
|||
'{{subst:uw-adblock|sig=yes}}', |
|||
'{{subst:uw-aoablock|sig=yes}}', |
|||
'{{subst:uw-vaublock|sig=yes}}', |
|||
'{{subst:uw-vblock|sig=yes}}', |
|||
'{{subst:uw-voablock|sig=yes}}', |
|||
'{{subst:uw-softerblock|sig=yes}}', |
|||
'{{subst:uw-causeblock|sig=yes}}', |
|||
'{{subst:uw-copyrightblock|sig=yes}}', |
|||
'{{subst:uw-myblock|sig=yes}}' |
|||
] |
|||
}; |
|||
ApiManager.static.presetDefaults = { |
|||
label: '<label missing>', |
|||
deletesummary: ApiManager.static.menuDefaults.deletesummary[ 10 ], |
|||
expiry: ApiManager.static.menuDefaults.expiry[ 0 ], |
|||
blocksummary: ApiManager.static.menuDefaults.blocksummary[ 0 ], |
|||
nocreate: true, |
|||
autoblock: true, |
|||
noemail: false, |
|||
nousertalk: false, |
|||
template: ApiManager.static.menuDefaults.template[ 0 ], |
|||
editsummary: ApiManager.static.menuDefaults.editsummary[ 0 ] |
|||
}; |
|||
ApiManager.static.otherDefaults = { |
|||
preset :ApiManager.static.presets[ 0 ].id, |
|||
watchlist: 'preferences', |
|||
menulocation: 'p-cactions', |
|||
menuposition: null, |
|||
oneclick: false |
|||
}; |
|||
ApiManager.static.months = [ |
|||
'January', |
|||
'February', |
|||
'March', |
|||
'April', |
|||
'May', |
|||
'June', |
|||
'July', |
|||
'August', |
|||
'September', |
|||
'October', |
|||
'November', |
|||
'December' |
|||
]; |
|||
ApiManager.static.summarySuffix = '([[WP:SUPG|SUPG]])'; |
|||
ApiManager.prototype.getCurrentTitle = function () { |
|||
return this.currentTitle; |
|||
}; |
|||
ApiManager.prototype.getUserName = function () { |
|||
return this.userName; |
|||
}; |
|||
ApiManager.prototype.getUserTalkTitle = function () { |
|||
return this.userTalkTitle; |
|||
}; |
|||
ApiManager.prototype._getNotificationDate = function () { |
|||
// We cache the result of this method so that we will always get the |
|||
// same date string as we used for the talk notification, even if a |
|||
// user happened to have the page open over a month boundary. |
|||
var date, month; |
|||
if ( !this.notificationDate ) { |
|||
date = new Date(); |
|||
month = this.constructor.static.months[ date.getMonth() ]; |
|||
this.notificationDate = month + ' ' + date.getFullYear(); |
|||
} |
|||
return this.notificationDate; |
|||
}; |
|||
ApiManager.prototype.getDefault = function ( key ) { |
|||
return this.defaults[ key ]; |
|||
}; |
|||
ApiManager.prototype.getPresetIds = function () { |
|||
return this.presetIds; |
|||
}; |
|||
ApiManager.prototype.getPresetValue = function ( presetId, key ) { |
|||
return this.presets[ presetId ][ key ]; |
|||
}; |
|||
ApiManager.prototype.getMenuItems = function ( key ) { |
|||
var menuItems, pref, keyItems, isDupe, i, len, val; |
|||
if ( typeof key !== 'string' ) { |
|||
throw new TypeError( "argument #1 to 'getMenuItems' was not a string" ); |
|||
} |
|||
function copyArray ( arr ) { |
|||
var ret = []; |
|||
for ( var i = 0, len = arr.length; i < len; i++ ) { |
|||
ret[ i ] = arr[ i ]; |
|||
} |
|||
return ret; |
|||
} |
|||
if ( this.menuItemCache[ key ] === undefined ) { |
|||
menuItems = this.constructor.static.menuDefaults[ key ]; |
|||
if ( menuItems ) { |
|||
this.menuItemCache[ key ] = menuItems; |
|||
pref = this.userPreferences[ key ]; |
|||
if ( pref ) { |
|||
isDupe = false; |
|||
for ( i = 0, len = menuItems.length; i < len; i++ ) { |
|||
val = menuItems[ i ]; |
|||
if ( val === pref ) { |
|||
isDupe = true; |
|||
break; |
|||
} |
|||
} |
|||
if ( !isDupe ) { |
|||
// Create a copy of the static array so we can manipulate it. |
|||
menuItems = copyArray( menuItems ); |
|||
menuItems.unshift( pref ); |
|||
this.menuItemCache[ key ] = menuItems; |
|||
} |
|||
} |
|||
} else { |
|||
this.menuItemCache[ key ] = null; |
|||
} |
|||
} |
|||
return this.menuItemCache[ key ]; |
|||
}; |
|||
ApiManager.prototype.addPortletLink = function () { |
|||
return mw.util.addPortletLink( |
|||
this.getDefault( 'menulocation' ), |
|||
'#', |
|||
'Delete and block', |
|||
'ca-spamuserpage', |
|||
'Delete this page and block this user', |
|||
null, |
|||
this.getDefault( 'menuposition' ) |
|||
); |
|||
}; |
|||
ApiManager.prototype.openTalkPage = function () { |
|||
window.open( |
|||
this.getUserTalkTitle().getUrl() + |
|||
'#' + |
|||
mw.util.wikiUrlencode( this._getNotificationDate() ), |
|||
'_top' |
|||
); |
|||
}; |
|||
ApiManager.prototype._deleteCurrentPage = function ( options ) { |
|||
options = options || {}; |
|||
var reason = options.deletesummary !== undefined ? |
|||
options.deletesummary : |
|||
this.getDefault( 'deletesummary' ); |
|||
reason += ' ' + this.constructor.static.summarySuffix; |
|||
return this.api.postWithToken( 'delete', { |
|||
format: 'json', |
|||
action: 'delete', |
|||
title: this.currentTitle.getPrefixedText(), |
|||
reason: reason, |
|||
watchlist: options.watchlist || this.getDefault( 'watchlist' ) |
|||
} ); |
|||
}; |
|||
ApiManager.prototype._blockUser = function ( options, deletePromise ) { |
|||
var deleteFinishedPromise, reason; |
|||
var apiManager = this; |
|||
options = options || {}; |
|||
// Make a new promise that is resolved when the delete promise is |
|||
// either resolved or rejected. |
|||
deleteFinishedPromise = $.Deferred( function ( deferred ) { |
|||
deletePromise.always( function () { |
|||
deferred.resolve(); |
|||
} ); |
|||
} ).promise(); |
|||
reason = options.blocksummary !== undefined ? |
|||
options.blocksummary : |
|||
apiManager.getDefault( 'blocksummary' ); |
|||
reason += ' <!-- ' + apiManager.constructor.static.summarySuffix + ' -->'; |
|||
return deleteFinishedPromise.then( function () { |
|||
return apiManager.api.postWithToken( 'block', { |
|||
format: 'json', |
|||
action: 'block', |
|||
user: apiManager.getUserName(), |
|||
expiry: options.expiry !== undefined ? |
|||
options.expiry : |
|||
apiManager.getDefault( 'expiry' ), |
|||
reason: reason, |
|||
nocreate: options.nocreate ? '' : undefined, |
|||
autoblock: options.autoblock ? '' : undefined, |
|||
noemail: options.noemail ? '' : undefined, |
|||
allowusertalk: !options.nousertalk ? '' : undefined |
|||
} ); |
|||
} ); |
|||
}; |
|||
ApiManager.prototype._postTalkNotification = function ( options, blockPromise ) { |
|||
var self = this; |
|||
options = options || {}; |
|||
return $.Deferred( function ( deferred ) { |
|||
// Reject the deferred if the block failed. |
|||
blockPromise.fail( function () { |
|||
return deferred.reject( 'usernotblocked', { error: { |
|||
id: 'usernotblocked', |
|||
info: 'There was an error while trying to block the user, ' + |
|||
'so notification was aborted' |
|||
} } ); |
|||
} ); |
|||
blockPromise.done( function () { |
|||
// Get the talk page content. We will use this to check if there is |
|||
// already a section heading for the current month. |
|||
return self.api.get( { |
|||
format: 'json', |
|||
action: 'query', |
|||
prop: 'revisions', |
|||
rvprop: 'content', |
|||
indexpageids: '', |
|||
titles: self.getUserTalkTitle().getPrefixedText(), |
|||
redirects: '' |
|||
} ).then( function ( obj ) { |
|||
var title, content, headings, lastHeading, |
|||
notificationDate, editPromise, summary; |
|||
var template = options.template !== undefined ? |
|||
options.template : |
|||
self.getDefault( 'template' ); |
|||
var pageid = obj.query.pageids[ 0 ]; |
|||
// If we got a redirect from the GET request, follow it. |
|||
if ( obj.query.redirects ) { |
|||
title = obj.query.redirects[ 0 ].to; |
|||
} else { |
|||
title = self.getUserTalkTitle().getPrefixedText(); |
|||
} |
|||
if ( pageid === '-1' ) { |
|||
// The page doesn't exist. |
|||
content = ''; |
|||
} else { |
|||
// The page exists; get the content. |
|||
content = obj.query.pages[ pageid ].revisions[ 0 ][ '*' ]; |
|||
// Separate our notification from whatever the previous content was. |
|||
if ( content.match( /\S/ ) ) { |
|||
content += '\n\n'; |
|||
} |
|||
} |
|||
// Add a heading for the current month if it is not already the |
|||
// last heading on the page. |
|||
headings = content.match( /^==[^=].*==[ \t]*$/gm ); |
|||
if ( headings ) { |
|||
lastHeading = headings[ headings.length - 1 ].slice( 2, -2 ).trim(); |
|||
} |
|||
notificationDate = self._getNotificationDate(); |
|||
if ( !lastHeading || lastHeading !== notificationDate ) { |
|||
content += '== ' + notificationDate + ' ==\n\n'; |
|||
} |
|||
// Add the block template. |
|||
content += template; |
|||
// Generate the edit summary. |
|||
summary = options.editsummary !== undefined ? |
|||
options.editsummary : |
|||
self.getDefault( 'editsummary' ); |
|||
summary += ' ' + self.constructor.static.summarySuffix; |
|||
// Overwrite the page with our new content. |
|||
editPromise = self.api.postWithToken( 'edit', { |
|||
format: 'json', |
|||
action: 'edit', |
|||
title: title, |
|||
summary: summary, |
|||
notminor: '', |
|||
text: content, |
|||
watchlist: options.watchlist || self.getDefault( 'watchlist' ) |
|||
} ); |
|||
editPromise.done( function () { |
|||
return deferred.resolve(); |
|||
} ); |
|||
editPromise.fail( function ( id, obj ) { |
|||
return deferred.reject( id, obj ); |
|||
} ); |
|||
} ); |
|||
} ); |
|||
} ).promise(); |
|||
}; |
|||
ApiManager.prototype.submit = function ( options ) { |
|||
var promises = {}; |
|||
options = options || {}; |
|||
promises[ 'delete' ] = this._deleteCurrentPage( options ); |
|||
promises.block = this._blockUser( options, promises[ 'delete' ] ); |
|||
promises.notify = this._postTalkNotification( options, promises.block ); |
|||
promises.all = $.when( |
|||
promises[ 'delete' ], |
|||
promises.block, |
|||
promises.notify |
|||
); |
|||
return promises; |
|||
}; |
|||
/************************************************************************** |
|||
* Dialog class |
|||
**************************************************************************/ |
|||
var Dialog = function ( options ) { |
|||
options = options || {}; |
|||
this.apiManager = new ApiManager(); |
|||
this.hasBeenSubmitted = false; |
|||
Dialog.super.call( this, options ); |
|||
}; |
|||
OO.inheritClass( Dialog, OO.ui.ProcessDialog ); |
|||
Dialog.static.name = 'SpamUserPageDialog'; |
|||
Dialog.static.title = 'Delete, block and notify'; |
|||
Dialog.static.actions = [ |
|||
{ action: 'submit', label: 'Submit', flags: [ 'primary', 'destructive' ] }, |
|||
{ label: 'Cancel', flags: 'safe' } |
|||
]; |
|||
Dialog.prototype.getApiManager = function () { |
|||
return this.apiManager; |
|||
}; |
|||
Dialog.prototype.getBodyHeight = function () { |
|||
return 440; |
|||
}; |
|||
Dialog.prototype.initialize = function () { |
|||
Dialog.super.prototype.initialize.apply( this, arguments ); |
|||
var apiManager = this.getApiManager(); |
|||
// Converts an array of data from ApiManager into a format usable with |
|||
// OOjs-ui menus. |
|||
function makeMenu( arr, labelCallback ) { |
|||
var i, len; |
|||
var items = []; |
|||
for ( i = 0, len = arr.length; i < len; i++ ) { |
|||
items[ i ] = new OO.ui.MenuOptionWidget( { |
|||
data: arr[ i ], |
|||
label: labelCallback ? labelCallback( arr[ i ] ) : arr[ i ] |
|||
} ); |
|||
} |
|||
return { items: items }; |
|||
} |
|||
// Initialize edit panel |
|||
this.editPanel = new OO.ui.PanelLayout( { |
|||
expanded: false |
|||
} ); |
|||
this.editFieldset = new OO.ui.FieldsetLayout( { |
|||
classes: [ 'container' ] |
|||
} ); |
|||
this.editPanel.$element.append( this.editFieldset.$element ); |
|||
// Initialize preset widget |
|||
this.presetDropdown = new OO.ui.DropdownWidget( { |
|||
data: { label: 'Select a preset' }, |
|||
menu: makeMenu( apiManager.getPresetIds(), function ( id ) { |
|||
return apiManager.getPresetValue( id, 'label' ); |
|||
} ) |
|||
} ); |
|||
if ( apiManager.getDefault( 'preset' ) ) { |
|||
this.presetDropdown.getMenu().selectItemByData( |
|||
apiManager.getDefault( 'preset' ) |
|||
); |
|||
} else { |
|||
this.presetDropdown.setLabel( this.presetDropdown.getData().label ); |
|||
} |
|||
this.editFieldset.addItems( [ |
|||
new OO.ui.FieldLayout( this.presetDropdown, { |
|||
label: 'Preset', |
|||
} ) |
|||
] ); |
|||
// Initialize deletion widgets |
|||
this.deleteSummaryInput = new OO.ui.ComboBoxInputWidget( { |
|||
value: apiManager.getDefault( 'deletesummary' ), |
|||
menu: makeMenu( apiManager.getMenuItems( 'deletesummary' ) ) |
|||
} ); |
|||
this.editFieldset.addItems( [ |
|||
new OO.ui.FieldLayout( this.deleteSummaryInput, { |
|||
label: 'Deletion summary' |
|||
} ) |
|||
] ); |
|||
// Initialize notification widgets |
|||
this.editSummaryInput = new OO.ui.ComboBoxInputWidget( { |
|||
value: apiManager.getDefault( 'editsummary' ), |
|||
menu: makeMenu( apiManager.getMenuItems( 'editsummary' ) ) |
|||
} ); |
|||
this.templateInput = new OO.ui.ComboBoxInputWidget( { |
|||
value: apiManager.getDefault( 'template' ), |
|||
menu: makeMenu( apiManager.getMenuItems( 'template' ) ) |
|||
} ); |
|||
this.editFieldset.addItems( [ |
|||
new OO.ui.FieldLayout( this.templateInput, { |
|||
label: 'Notification template' |
|||
} ), |
|||
new OO.ui.FieldLayout( this.editSummaryInput, { |
|||
label: 'Edit summary' |
|||
} ) |
|||
] ); |
|||
// Initialize block widgets |
|||
this.blockSummaryInput = new OO.ui.ComboBoxInputWidget( { |
|||
value: apiManager.getDefault( 'blocksummary' ), |
|||
menu: makeMenu( apiManager.getMenuItems( 'blocksummary' ) ) |
|||
} ); |
|||
this.expiryInput = new OO.ui.ComboBoxInputWidget( { |
|||
value: apiManager.getDefault( 'expiry' ), |
|||
menu: makeMenu( apiManager.getMenuItems( 'expiry' ) ) |
|||
} ); |
|||
this.nocreateToggleButton = new OO.ui.ToggleButtonWidget( { |
|||
label: 'Block account creation', |
|||
value: apiManager.getDefault( 'nocreate' ) |
|||
} ); |
|||
this.noemailToggleButton = new OO.ui.ToggleButtonWidget( { |
|||
label: 'Block email', |
|||
value: apiManager.getDefault( 'noemail' ) |
|||
} ); |
|||
this.nousertalkToggleButton = new OO.ui.ToggleButtonWidget( { |
|||
label: 'Block talk', |
|||
value: apiManager.getDefault( 'nousertalk' ) |
|||
} ); |
|||
this.autoblockToggleButton = new OO.ui.ToggleButtonWidget( { |
|||
label: 'Autoblock', |
|||
value: apiManager.getDefault( 'autoblock' ) |
|||
} ); |
|||
this.blockButtonGroup = new OO.ui.ButtonGroupWidget( { |
|||
items: [ |
|||
this.nocreateToggleButton, |
|||
this.noemailToggleButton, |
|||
this.nousertalkToggleButton, |
|||
this.autoblockToggleButton |
|||
] |
|||
} ); |
|||
this.editFieldset.addItems( [ |
|||
new OO.ui.FieldLayout( this.blockSummaryInput, { |
|||
label: 'Block summary' |
|||
} ), |
|||
new OO.ui.FieldLayout( this.expiryInput, { |
|||
label: 'Block expiry' |
|||
} ), |
|||
new OO.ui.FieldLayout( this.blockButtonGroup, { |
|||
label: 'Block options', |
|||
align: 'top' |
|||
} ), |
|||
] ); |
|||
// Initialize watchlist widgets |
|||
this.watchlistOptions = {}; |
|||
this.watchlistOptions.watch = new OO.ui.ButtonOptionWidget( { |
|||
data: 'watch', |
|||
label: 'Watch', |
|||
title: 'Watch option' |
|||
} ); |
|||
this.watchlistOptions.unwatch = new OO.ui.ButtonOptionWidget( { |
|||
data: 'unwatch', |
|||
label: 'Unwatch', |
|||
title: 'Unwatch option' |
|||
} ); |
|||
this.watchlistOptions.preferences = new OO.ui.ButtonOptionWidget( { |
|||
data: 'preferences', |
|||
label: 'Follow preferences', |
|||
title: 'Follow preferences option' |
|||
} ); |
|||
this.watchlistOptions.nochange = new OO.ui.ButtonOptionWidget( { |
|||
data: 'nochange', |
|||
label: 'No change', |
|||
title: 'No change option' |
|||
} ); |
|||
this.watchlistButtonSelect = new OO.ui.ButtonSelectWidget( { |
|||
items: [ |
|||
this.watchlistOptions.watch, |
|||
this.watchlistOptions.unwatch, |
|||
this.watchlistOptions.preferences, |
|||
this.watchlistOptions.nochange |
|||
] |
|||
} ); |
|||
this.watchlistButtonSelect.selectItemByData( |
|||
apiManager.getDefault( 'watchlist' ) |
|||
); |
|||
this.editFieldset.addItems( [ |
|||
new OO.ui.FieldLayout( this.watchlistButtonSelect, { |
|||
label: 'Watchlist options', |
|||
align: 'top' |
|||
} ) |
|||
] ); |
|||
// Initialize submit panel |
|||
this.submitPanel = new OO.ui.PanelLayout( { |
|||
$: this.$, |
|||
expanded: false |
|||
} ); |
|||
this.submitFieldset = new OO.ui.FieldsetLayout( { |
|||
classes: [ 'container' ] |
|||
} ); |
|||
this.submitPanel.$element.append( this.submitFieldset.$element ); |
|||
this.deleteProgressLabel = new OO.ui.LabelWidget(); |
|||
this.deleteProgressField = new OO.ui.FieldLayout( this.deleteProgressLabel ); |
|||
this.blockProgressLabel = new OO.ui.LabelWidget(); |
|||
this.blockProgressField = new OO.ui.FieldLayout( this.blockProgressLabel ); |
|||
this.notifyProgressLabel = new OO.ui.LabelWidget(); |
|||
this.notifyProgressField = new OO.ui.FieldLayout( this.notifyProgressLabel ); |
|||
this.openTalkProgressField = new OO.ui.FieldLayout( new OO.ui.LabelWidget() ); |
|||
this.submitFieldset.addItems( [ |
|||
this.deleteProgressField, |
|||
this.blockProgressField, |
|||
this.notifyProgressField, |
|||
this.openTalkProgressField |
|||
] ); |
|||
// Initialize stack widget |
|||
this.stackLayout= new OO.ui.StackLayout( { |
|||
items: [ this.editPanel, this.submitPanel ], |
|||
padded: true |
|||
} ); |
|||
// Add widgets to the DOM |
|||
this.$body.append( this.stackLayout.$element ); |
|||
// Add event handlers |
|||
if ( apiManager.getDefault( 'preset' ) ) { |
|||
this.changeInputEventHandlers( 'on', this.onFirstChangeAfterPreset, null, this ); |
|||
} |
|||
this.presetDropdown.getMenu().on( 'select', this.onPresetSelect, null, this ); |
|||
}; |
|||
Dialog.prototype.onPresetSelect = function () { |
|||
var presetId = this.presetDropdown.getMenu().findSelectedItem().getData(); |
|||
var apiManager = this.getApiManager(); |
|||
// Detach any input event handlers. If they are still attached, they will |
|||
// clear the preset selection, which we don't want. |
|||
this.changeInputEventHandlers( 'off', this.onFirstChangeAfterPreset, this ); |
|||
// Set values |
|||
this.deleteSummaryInput.getInput().setValue( |
|||
apiManager.getPresetValue( presetId, 'deletesummary' ) |
|||
); |
|||
this.deleteSummaryInput.getMenu().toggle( false ); |
|||
this.expiryInput.getInput().setValue( |
|||
apiManager.getPresetValue( presetId, 'expiry' ) |
|||
); |
|||
this.expiryInput.getMenu().toggle( false ); |
|||
this.templateInput.getInput().setValue( |
|||
apiManager.getPresetValue( presetId, 'template' ) |
|||
); |
|||
this.templateInput.getMenu().toggle( false ); |
|||
this.editSummaryInput.getInput().setValue( |
|||
apiManager.getPresetValue( presetId, 'editsummary' ) |
|||
); |
|||
this.editSummaryInput.getMenu().toggle( false ); |
|||
this.blockSummaryInput.getInput().setValue( |
|||
apiManager.getPresetValue( presetId, 'blocksummary' ) |
|||
); |
|||
this.blockSummaryInput.getMenu().toggle( false ); |
|||
this.nocreateToggleButton.setValue( |
|||
apiManager.getPresetValue( presetId, 'nocreate' ) |
|||
); |
|||
this.autoblockToggleButton.setValue( |
|||
apiManager.getPresetValue( presetId, 'autoblock' ) |
|||
); |
|||
this.noemailToggleButton.setValue( |
|||
apiManager.getPresetValue( presetId, 'noemail' ) |
|||
); |
|||
this.nousertalkToggleButton.setValue( |
|||
apiManager.getPresetValue( presetId, 'nousertalk' ) |
|||
); |
|||
// Attach one-time event handler |
|||
this.changeInputEventHandlers( 'on', this.onFirstChangeAfterPreset, null, this ); |
|||
}; |
|||
Dialog.prototype.changeInputEventHandlers = function ( method, func, arg3, arg4 ) { |
|||
this.deleteSummaryInput.getInput()[ method ]( 'change', func, arg3, arg4 ); |
|||
this.deleteSummaryInput.getMenu()[ method ]( 'select', func, arg3, arg4 ); |
|||
this.expiryInput.getInput()[ method ]( 'change', func, arg3, arg4 ); |
|||
this.expiryInput.getMenu()[ method ]( 'select', func, arg3, arg4 ); |
|||
this.templateInput.getInput()[ method ]( 'change', func, arg3, arg4 ); |
|||
this.templateInput.getMenu()[ method ]( 'select', func, arg3, arg4 ); |
|||
this.editSummaryInput.getInput()[ method ]( 'change', func, arg3, arg4 ); |
|||
this.editSummaryInput.getMenu()[ method ]( 'select', func, arg3, arg4 ); |
|||
this.blockSummaryInput.getInput()[ method ]( 'change', func, arg3, arg4 ); |
|||
this.blockSummaryInput.getMenu()[ method ]( 'select', func, arg3, arg4 ); |
|||
this.nocreateToggleButton[ method ]( 'change', func, arg3, arg4 ); |
|||
this.autoblockToggleButton[ method ]( 'change', func, arg3, arg4 ); |
|||
this.noemailToggleButton[ method ]( 'change', func, arg3, arg4 ); |
|||
this.nousertalkToggleButton[ method ]( 'change', func, arg3, arg4 ); |
|||
}; |
|||
Dialog.prototype.onFirstChangeAfterPreset = function () { |
|||
// Detach all input event handlers |
|||
this.changeInputEventHandlers( 'off', this.onFirstChangeAfterPreset, this ); |
|||
// Clear the selected preset. Before doing this we detach its select event |
|||
// listener, as that will cause problems if it's still attached. |
|||
this.presetDropdown.getMenu().off( 'select', this.onPresetSelect, this ); |
|||
this.presetDropdown.getMenu().selectItem(); |
|||
this.presetDropdown.setLabel( this.presetDropdown.getData().label ); |
|||
this.presetDropdown.getMenu().on( 'select', this.onPresetSelect, null, this ); |
|||
}; |
|||
Dialog.prototype.onSubmit = function () { |
|||
var self = this; |
|||
var options, promises; |
|||
var apiManager = this.getApiManager(); |
|||
var title = apiManager.getCurrentTitle().getPrefixedText(); |
|||
var user = apiManager.getUserName(); |
|||
// Record that the dialog has been submitted. This is necessary to |
|||
// prevent the "Submit" button from being reactivated after the window |
|||
// is closed and reopened. |
|||
self.hasBeenSubmitted = true; |
|||
// Disable input |
|||
self.actions.setAbilities( { submit: false } ); |
|||
// Increase the pending level by 4: one each for the delete, block, |
|||
// notify, and all promises. |
|||
self.pushPending(); |
|||
self.pushPending(); |
|||
self.pushPending(); |
|||
self.pushPending(); |
|||
// Set progress labels |
|||
self.deleteProgressField.setLabel( 'Deleting "' + title + '"...' ); |
|||
self.blockProgressField.setLabel( 'Blocking ' + user + '...' ); |
|||
self.notifyProgressField.setLabel( 'Notifying ' + user + '...' ); |
|||
self.stackLayout.setItem( self.submitPanel ); |
|||
// Get options and submit |
|||
options = { |
|||
watchlist: self.watchlistButtonSelect.findSelectedItem().getData(), |
|||
deletesummary: self.deleteSummaryInput.getInput().getValue(), |
|||
expiry: self.expiryInput.getInput().getValue(), |
|||
template: self.templateInput.getInput().getValue(), |
|||
editsummary: self.editSummaryInput.getInput().getValue(), |
|||
blocksummary: self.blockSummaryInput.getInput().getValue(), |
|||
nocreate: self.nocreateToggleButton.getValue(), |
|||
autoblock: self.autoblockToggleButton.getValue(), |
|||
noemail: self.noemailToggleButton.getValue(), |
|||
nousertalk: self.nousertalkToggleButton.getValue() |
|||
}; |
|||
promises = self.getApiManager().submit( options ); |
|||
// Update progress |
|||
// This involves editing the progress labels and reducing the pending |
|||
// level. |
|||
function updateProgress( promise, label ) { |
|||
promise.done( function () { |
|||
label.setLabel( $( '<span>' ) |
|||
.addClass( 'spamuserpage-success' ) |
|||
.text( 'Done.' ) |
|||
); |
|||
} ); |
|||
promise.fail( function ( id, obj ) { |
|||
if ( obj && obj.error && obj.error.info ) { |
|||
label.setLabel( $( '<span>' ) |
|||
.addClass( 'spamuserpage-error' ) |
|||
.text( 'Error: ' + obj.error.info + '.' ) |
|||
); |
|||
} else { |
|||
label.setLabel( 'An unknown error occurred.' ); |
|||
} |
|||
} ); |
|||
promise.always( function () { |
|||
self.popPending(); |
|||
} ); |
|||
} |
|||
updateProgress( promises[ 'delete' ], self.deleteProgressLabel ); |
|||
updateProgress( promises.block, self.blockProgressLabel ); |
|||
updateProgress( promises.notify, self.notifyProgressLabel ); |
|||
// Clean up when everything is done |
|||
promises.all.done( function () { |
|||
self.openTalkProgressField.setLabel( |
|||
'Opening "' + |
|||
apiManager.getUserTalkTitle().getPrefixedText() + |
|||
'"...' |
|||
); |
|||
apiManager.openTalkPage(); |
|||
} ); |
|||
promises.all.fail( function () { |
|||
// Pop pending only on failure, so that it still looks like we're |
|||
// loading something while the talk page is being opened. |
|||
self.popPending(); |
|||
} ); |
|||
}; |
|||
Dialog.prototype.getReadyProcess = function ( data ) { |
|||
// Parent getReadyProcess method |
|||
return Dialog.super.prototype.getReadyProcess.call( this, data ) |
|||
.next( function () { |
|||
if ( this.hasBeenSubmitted ) { |
|||
// The dialog has already been submitted when it was previously |
|||
// opened, so disable the Submit button. |
|||
this.actions.setAbilities( { submit: false } ); |
|||
} else if ( this.getApiManager().getDefault( 'oneclick' ) ) { |
|||
this.executeAction( 'submit' ); |
|||
} |
|||
}, this ); |
|||
}; |
|||
Dialog.prototype.getActionProcess = function ( action ) { |
|||
return Dialog.super.prototype.getActionProcess.call( this, action ) |
|||
.next( function () { |
|||
if ( action === 'submit' ) { |
|||
return this.onSubmit(); |
|||
} else { |
|||
return Dialog.super.prototype.getActionProcess.call( this, action ); |
|||
} |
|||
}, this ); |
|||
}; |
|||
/************************************************************************** |
|||
* Main |
|||
**************************************************************************/ |
|||
function main() { |
|||
var portletLink; |
|||
var supDialog = new Dialog( { size: 'large' } ); |
|||
var apiManager = supDialog.getApiManager(); |
|||
var userName = apiManager.getUserName(); |
|||
if ( |
|||
// Don't run in the current user's userspace or on any user talk pages. |
|||
userName !== config.wgUserName && |
|||
!( |
|||
config.wgNamespaceNumber === 3 && |
|||
config.wgTitle === userName |
|||
) |
|||
) { |
|||
// Load CSS |
|||
importStylesheet( "User:Mr. Stradivarius/gadgets/SpamUserPage.css" ); |
|||
// Set up window manager |
|||
var windowManager = new OO.ui.WindowManager(); |
|||
$( 'body' ).append( windowManager.$element ); |
|||
windowManager.addWindows( [ supDialog ] ); |
|||
// Add portlet link |
|||
portletLink = apiManager.addPortletLink(); |
|||
$( portletLink ).click( function ( event ) { |
|||
event.preventDefault(); |
|||
windowManager.openWindow( supDialog ); |
|||
} ); |
|||
} |
|||
} |
|||
main(); |
|||
} ); |
|||
// </nowiki> |
Latest revision as of 17:57, 6 March 2022
//<nowiki>
$(function() {
var namespace = mw.config.get('wgNamespaceNumber'),
pageName = mw.config.get('wgPageName'),
myUserName = mw.config.get('wgUserName'),
userName = mw.config.get('wgRelevantUserName'),
templateName = "script",
blockReason,
api;
if([0,1,2,3,4,5].indexOf(namespace) !== -1) {
mw.loader.using( [ 'mediawiki.api', 'mediawiki.util' ] ).done( function() {
api = new mw.Api();
mw.util.addPortletLink(
'p-cactions', 'javascript:void(0)',
'Block vandal', 'ca-spamublock', 'Delete user page and execute {{uw-spamublock}} on current user'
);
} );
$('#ca-spamublock').on('click', function() {
if (confirm('This script will delete the current user page, block the relevant user or page creator as {{uw-spamublock}} and leave that template on their talk page, or the template specified at [[Special:MyPage/uw-spamublock]], if present.\n\nARE YOU SURE YOU WANT TO PROCEED?')) {
$('#ca-spamublock').text('Please wait...');
if(!userName) {
api.get({
action: 'query',
prop: 'revisions',
titles: pageName,
rvdir: 'newer',
rvlimit: '1',
rvprop: 'user'
}).then(function(data) {
var pages = data.query.pages;
userName = pages[Object.keys(pages)[0]].revisions[0].user;
getTemplate();
});
} else {
getTemplate();
}
}
});
}
function getTemplate() {
api.get({
action: 'query',
titles: 'User:'+myUserName+'/uw-spamublock'
}).then(function(data) {
var query = data.query.pages;
if(Object.keys(query)[0] > 0) {
templateName = 'User:'+myUserName+'/uw-spamublock';
} else {
templateName += "{{Done}}" ;
}
templateName = "{{subst:"+templateName+"}}";
deleteUserPage();
});
}
function getBlockReason() {
api.get({
action: 'query',
titles: 'User:'+myUserName+'/spamublock-message'
}).then(function(data) {
var query = data.query.pages;
if(Object.keys(query)[0] > 0) {
blockReason = '{{User:'+myUserName+'/spamublock-message}}';
} else {
blockReason = 'Testing blocking script';
}
blockUser();
});
}
function deleteUserPage() {
api.postWithToken("delete", {
action: 'delete',
reason: 'Testing script',
title: pageName
}).then(function(deleteData) {
$("#mw-content-text").html(
"<p><b>Deleted</b> page <a href='"+mw.util.getUrl(pageName)+"'>"+pageName+"</a> <i>(<a href='"+mw.util.getUrl('WP:G11')+"'>G11</a>: Unambiguous <a href='"+mw.util.getUrl('WP:NOTADVERTISING')+"'>advertising</a> or promotion)</i></p>"
);
getBlockReason();
},function(error) {
$("#mw-content-text").html(
"<p><b>Error</b> deleting page "+pageName+": "+error+"</p>"
);
});
}
function blockUser() {
api.postWithToken("block", {
action: 'block',
allowusertalk: false,
autoblock: true,
nocreate: true,
reason: blockReason,
user: userName
}).then(function(blockData) {
$("#mw-content-text").append(
"<p><b>Blocked</b> <a href='"+mw.util.getUrl('User:'+userName)+"'>"+userName+"</a> (account creation blocked) with an expiry time of indefinite <i>(<span id='spamublock-blocked-reason'></span>)</i></p>"
);
$('<span/>').text(blockReason).appendTo("#spamublock-blocked-reason");
templateUser();
}, function(error) {
$("#mw-content-text").append(
"<p><b>Error</b> blocking <a href='"+mw.util.getUrl('User:'+userName)+"'>"+userName+"</a>: "+error+"</p>"
);
});
}
function templateUser() {
var monthNames = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
d = new Date();
api.postWithToken( "edit", {
action: "edit",
section: 'new',
sectiontitle: monthNames[d.getMonth()] + ' ' + d.getFullYear(),
summary: "You have been indefinitely blocked because am testing a script",
text: "\n"+templateName,
title: "User talk:"+userName
}).then(function(editData) {
$("#mw-content-text").append(
"<p><b>Edited</b> <a href='"+mw.util.getUrl('User talk:'+userName)+"'>User talk:"+userName+"</a>: Created new section with template "+templateName+"</p>" +
"<p><b>Complete (<a href='javascript:document.location.reload()'>reload</a>)</b></p>"
);
},function(error) {
$("#mw-content-text").append(
"<p><b>Error</b> editing <a href='"+mw.util.getUrl('User talk:'+userName)+"'>User talk:"+userName+"</a>: "+error+"</p>"
);
});
}
});
//</nowiki>